React AriaExamples

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={`${coords.x},${coords.y}`}
            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={`${coords.x},${coords.y}`}
            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={`${coords.x},${coords.y}`}
            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.