Ripple Button
A Button with an animated ripple effect styled with Tailwind CSS.
Example#
import {Button} from 'react-aria-components';
import {useEffect, useRef, useState} from 'react';
import Airplane from '@spectrum-icons/workflow/Airplane';
function RippleButton(props) {
const [coords, setCoords] = useState(null);
let timeout = useRef<ReturnType<typeof setTimeout> | null>(null);
let onPress = (e) => {
setCoords({ x: e.x, y: e.y });
if (e.x !== -1 && e.y !== -1) {
clearTimeout(timeout.current);
timeout.current = setTimeout(() => setCoords(null), 600);
}
};
useEffect(() => {
return () => {
clearTimeout(timeout.current);
};
}, []);
return (
<div className="bg-gradient-to-r from-teal-300 to-cyan-500 p-12 rounded-lg flex justify-center">
<Button
onPress={onPress}
className={`
relative overflow-hidden
inline-flex items-center justify-center rounded-md bg-black bg-opacity-50 bg-clip-padding border border-white/20 px-6 py-4 text-white text-lg
hover:bg-opacity-60 pressed:bg-opacity-70 transition-colors cursor-default outline-none focus-visible:ring-2 focus-visible:ring-white/75`}
>
{coords && (
<div
key={` , `}
className="absolute h-8 w-8 rounded-full opacity-100 bg-white/60"
style={{
animation: 'ripple 600ms linear',
left: coords.x - 15,
top: coords.y - 15
}}
/>
)}
<span className="flex items-center gap-4">{props.children}</span>
</Button>
</div>
);
}
<RippleButton>
<Airplane size="S" /> Book flight
</RippleButton>
import {Button} from 'react-aria-components';
import {useEffect, useRef, useState} from 'react';
import Airplane from '@spectrum-icons/workflow/Airplane';
function RippleButton(props) {
const [coords, setCoords] = useState(null);
let timeout = useRef<
ReturnType<typeof setTimeout> | null
>(null);
let onPress = (e) => {
setCoords({ x: e.x, y: e.y });
if (e.x !== -1 && e.y !== -1) {
clearTimeout(timeout.current);
timeout.current = setTimeout(
() => setCoords(null),
600
);
}
};
useEffect(() => {
return () => {
clearTimeout(timeout.current);
};
}, []);
return (
<div className="bg-gradient-to-r from-teal-300 to-cyan-500 p-12 rounded-lg flex justify-center">
<Button
onPress={onPress}
className={`
relative overflow-hidden
inline-flex items-center justify-center rounded-md bg-black bg-opacity-50 bg-clip-padding border border-white/20 px-6 py-4 text-white text-lg
hover:bg-opacity-60 pressed:bg-opacity-70 transition-colors cursor-default outline-none focus-visible:ring-2 focus-visible:ring-white/75`}
>
{coords && (
<div
key={` , `}
className="absolute h-8 w-8 rounded-full opacity-100 bg-white/60"
style={{
animation: 'ripple 600ms linear',
left: coords.x - 15,
top: coords.y - 15
}}
/>
)}
<span className="flex items-center gap-4">
{props.children}
</span>
</Button>
</div>
);
}
<RippleButton>
<Airplane size="S" /> Book flight
</RippleButton>
import {Button} from 'react-aria-components';
import {
useEffect,
useRef,
useState
} from 'react';
import Airplane from '@spectrum-icons/workflow/Airplane';
function RippleButton(
props
) {
const [
coords,
setCoords
] = useState(null);
let timeout = useRef<
ReturnType<
typeof setTimeout
> | null
>(null);
let onPress = (e) => {
setCoords({
x: e.x,
y: e.y
});
if (
e.x !== -1 &&
e.y !== -1
) {
clearTimeout(
timeout.current
);
timeout.current =
setTimeout(
() =>
setCoords(
null
),
600
);
}
};
useEffect(() => {
return () => {
clearTimeout(
timeout.current
);
};
}, []);
return (
<div className="bg-gradient-to-r from-teal-300 to-cyan-500 p-12 rounded-lg flex justify-center">
<Button
onPress={onPress}
className={`
relative overflow-hidden
inline-flex items-center justify-center rounded-md bg-black bg-opacity-50 bg-clip-padding border border-white/20 px-6 py-4 text-white text-lg
hover:bg-opacity-60 pressed:bg-opacity-70 transition-colors cursor-default outline-none focus-visible:ring-2 focus-visible:ring-white/75`}
>
{coords && (
<div
key={` , `}
className="absolute h-8 w-8 rounded-full opacity-100 bg-white/60"
style={{
animation:
'ripple 600ms linear',
left:
coords
.x -
15,
top:
coords
.y - 15
}}
/>
)}
<span className="flex items-center gap-4">
{props
.children}
</span>
</Button>
</div>
);
}
<RippleButton>
<Airplane size="S" />
{' '}
Book flight
</RippleButton>
@keyframes ripple {
from {
transform: scale(0);
opacity: 1;
}
to {
transform: scale(6);
opacity: 0;
}
}
@keyframes ripple {
from {
transform: scale(0);
opacity: 1;
}
to {
transform: scale(6);
opacity: 0;
}
}
@keyframes ripple {
from {
transform: scale(0);
opacity: 1;
}
to {
transform: scale(6);
opacity: 0;
}
}
Tailwind config#
This example uses the tailwindcss-react-aria-components plugin. Add it to your tailwind.config.js
:
module.exports = {
// ...
plugins: [
require('tailwindcss-react-aria-components')
]
};
module.exports = {
// ...
plugins: [
require('tailwindcss-react-aria-components')
]
};
module.exports = {
// ...
plugins: [
require(
'tailwindcss-react-aria-components'
)
]
};
Components#
Button
A button allows a user to perform an action.