Description:
M3-Ripple is a React component library that implements Google’s Material Design 3 ripple effect specification.
You can integrate it into buttons, cards, list items, or any interactive element that requires visual confirmation of user interaction.
Features
- 🎯 Perfect Material Design 3 compliance with authentic ripple animations
- ⚡ Zero-configuration setup that works out of the box with any parent element
- 🎨 Automatic color inheritance from parent elements using currentColor
- 🔧 Customizable opacity levels for both hover and pressed states
- ⏱️ Configurable animation duration and timing parameters
- 📱 Touch and mouse event support for cross-platform compatibility
- 🎛️ CSS variable support for global theming control
- 🚫 Built-in disabled state management
- 🎪 Custom easing functions for fine-tuned animation control
- 📦 Lightweight implementation with minimal bundle impact
Preview

Use Cases
- Interactive buttons in web applications requiring Material Design feedback patterns
- Card components in data dashboards where users need visual confirmation of selection
- Navigation menu items that benefit from tactile feedback during user interaction
- Form controls and input fields that require modern interaction patterns
- E-commerce product listings where visual feedback improves user engagement
How to Use It
1. Install the package through your preferred package manager:
npm install m3-ripple2. Import both the component and its required CSS file into your React application:
import { Ripple } from 'm3-ripple'
import 'm3-ripple/ripple.css'3. Add the Ripple component inside any interactive element and apply position: relative to the parent container:
function BasicButton() {
return (
<button
style={{
position: 'relative',
padding: '12px 24px',
backgroundColor: '#1976d2',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: 'pointer'
}}
>
<Ripple />
Click Me
</button>
)
}4. The ripple effect automatically inherits the color from its parent element through CSS’s currentColor property. You can control the ripple color by setting the color style on the parent element:
function ColoredRippleButton() {
return (
<div
style={{
position: 'relative',
padding: '16px 32px',
backgroundColor: '#f5f5f5',
color: '#e91e63', // This controls the ripple color
border: '2px solid #e91e63',
borderRadius: '8px',
cursor: 'pointer'
}}
>
<Ripple />
Pink Ripple Button
</div>
)
}5. Configure ripple opacity globally using CSS custom properties:
:root {
--ripple-hover-opacity: 0.08;
--ripple-pressed-opacity: 0.12;
}6. Override global settings with component-specific props:
function CustomOpacityRipple() {
return (
<button style={{ position: 'relative', padding: '10px 20px' }}>
<Ripple
hoverOpacity={0.15}
pressedOpacity={0.25}
/>
High Opacity Ripple
</button>
)
}7. Customize animation timing and behavior with detailed props:
function AdvancedRipple() {
return (
<div style={{ position: 'relative', padding: '20px' }}>
<Ripple
duration={200}
minimumPressDuration={300}
touchDelay={100}
easing="cubic-bezier(0.2, 0, 0, 1)"
className="custom-ripple-class"
style={{ zIndex: 1 }}
/>
Advanced Ripple Configuration
</div>
)
}8. Disable ripple effects conditionally:
function ConditionalRipple({ isDisabled }) {
return (
<button
style={{
position: 'relative',
padding: '12px 24px',
opacity: isDisabled ? 0.6 : 1
}}
disabled={isDisabled}
>
<Ripple disabled={isDisabled} />
{isDisabled ? 'Disabled Button' : 'Active Button'}
</button>
)
}9. All available component props.
export interface RippleProps {
/**
* Disables the ripple.
*/
disabled?: boolean
/**
* hoverOpacity: The opacity of the ripple when hovered.
*
* @default 0.08
*/
hoverOpacity?: number
/**
* pressedOpacity: The opacity of the ripple when pressed.
*
* @default 0.12
*/
pressedOpacity?: number
/**
* Additional CSS classes to apply to the ripple container.
*/
className?: string
/**
* Additional styles to apply to the ripple container.
*/
style?: React.CSSProperties
/**
* Easing function for the ripple animation.
*/
easing?: 'cubic-bezier(0.2, 0, 0, 1)'
/**
* The duration in milliseconds for the ripple to grow when pressed.
*
* @default 150
*/
duration?: number
/**
* The minimum duration in milliseconds for the ripple to be considered a
* valid press.
*
* @default 225
*/
minimumPressDuration?: number
/**
* * The duration in milliseconds for the ripple to wait before starting the
*
* @default 150
*/
touchDelay?: number
}FAQs
Q: Why isn’t the ripple effect appearing on my element?
A: The parent element must have position: relative applied to it. The ripple component uses absolute positioning and requires this CSS property to position itself correctly within the parent boundaries.
Q: Can I use M3-Ripple with existing UI libraries like Material-UI or Ant Design?
A: Yes, M3-Ripple works with any React component or HTML element.
Q: How do I customize the ripple color to match my design system?
A: Set the color CSS property on the parent element. The ripple automatically inherits this color through currentColor. You can also use CSS variables for global theming control.
Q: Does M3-Ripple support server-side rendering?
A: Yes, the component works with server-side rendering frameworks like Next.js. The CSS animations are handled client-side after hydration.





