Material Design ink ripple effect component for web element interactions with JavaScript and CSS-only implementations
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
The MDCRipple component is the primary JavaScript interface for attaching and controlling ripples. It extends MDCComponent and provides methods for programmatic ripple control.
Main ripple component providing programmatic ripple control.
/**
* Main ripple component providing programmatic ripple control
* Extends MDCComponent to provide component lifecycle management
*/
class MDCRipple extends MDCComponent<MDCRippleFoundation> implements MDCRippleCapableSurface {
/** Attach ripple to element with optional configuration */
static attachTo(root: Element, opts?: MDCRippleAttachOpts): MDCRipple;
/** Create adapter for custom framework integration */
static createAdapter(instance: MDCRippleCapableSurface): MDCRippleAdapter;
/** Whether ripple extends beyond element bounds */
unbounded: boolean;
/** Whether ripple is disabled */
disabled: boolean;
/** Programmatically activate the ripple */
activate(): void;
/** Programmatically deactivate the ripple */
deactivate(): void;
/** Recompute ripple dimensions and positions */
layout(): void;
}Usage Examples:
import { MDCRipple } from "@material/ripple";
// Basic attachment
const surface = document.querySelector('.my-button');
const ripple = new MDCRipple(surface);
// Using static method
const ripple2 = MDCRipple.attachTo(document.querySelector('.my-surface'));
// Unbounded ripple (for checkboxes, radio buttons)
const unboundedRipple = MDCRipple.attachTo(surface, { isUnbounded: true });
// Configure properties
ripple.unbounded = true;
ripple.disabled = false;
// Programmatic control
ripple.activate();
setTimeout(() => ripple.deactivate(), 300);
// Recompute layout (useful after dynamic size changes)
ripple.layout();Convenience method to create and attach a ripple to an element.
/**
* Attach ripple to element with optional configuration
* @param root - Element to attach ripple to
* @param opts - Optional configuration including unbounded setting
* @returns New MDCRipple instance
*/
static attachTo(root: Element, opts?: MDCRippleAttachOpts): MDCRipple;Creates a standard adapter implementation for MDCRippleCapableSurface instances.
/**
* Create adapter for custom framework integration
* @param instance - Object implementing MDCRippleCapableSurface
* @returns Configured MDCRippleAdapter instance
*/
static createAdapter(instance: MDCRippleCapableSurface): MDCRippleAdapter;Usage Example:
import { MDCRipple, MDCRippleFoundation } from "@material/ripple";
class MyCustomComponent {
constructor(element) {
this.root = element;
this.unbounded = false;
this.disabled = false;
// Create custom foundation with mixed adapter
const foundation = new MDCRippleFoundation({
...MDCRipple.createAdapter(this),
// Override specific methods for custom behavior
isSurfaceActive: () => this.isActive,
});
this.ripple = new MDCRipple(this.root, foundation);
}
}Controls whether the ripple is bounded by the element's dimensions.
/**
* Whether ripple extends beyond element bounds
* - Bounded ripples (false): Clipped by element overflow:hidden
* - Unbounded ripples (true): Extend beyond element bounds
*/
unbounded: boolean;Controls whether the ripple responds to interactions.
/**
* Whether ripple is disabled
* When true, ripple will not activate on user interactions
*/
disabled: boolean;Programmatically triggers ripple activation animation.
/**
* Programmatically activate the ripple
* Triggers the same animation as user interaction
*/
activate(): void;Programmatically triggers ripple deactivation animation.
/**
* Programmatically deactivate the ripple
* Completes the ripple animation cycle
*/
deactivate(): void;Recomputes ripple dimensions and positions.
/**
* Recompute ripple dimensions and positions
* Call this when element size or position changes dynamically
*/
layout(): void;import { MDCRipple } from "@material/ripple";
// HTML: <button class="mdc-button">Click me</button>
const button = document.querySelector('.mdc-button');
const ripple = new MDCRipple(button);import { MDCRipple } from "@material/ripple";
// HTML: <div class="mdc-checkbox__ripple"></div>
const checkboxRipple = document.querySelector('.mdc-checkbox__ripple');
const ripple = MDCRipple.attachTo(checkboxRipple, { isUnbounded: true });import { MDCRipple, MDCRippleFoundation } from "@material/ripple";
class MyInteractiveCard {
constructor(element) {
this.root = element;
this.disabled = false;
this.active = false;
// Custom activation logic
this.root.addEventListener('keydown', evt => {
if (evt.key === ' ' || evt.key === 'Enter') {
this.active = true;
}
});
this.root.addEventListener('keyup', evt => {
if (evt.key === ' ' || evt.key === 'Enter') {
this.active = false;
}
});
// Create ripple with custom adapter
const foundation = new MDCRippleFoundation({
...MDCRipple.createAdapter(this),
isSurfaceActive: () => this.active
});
this.ripple = new MDCRipple(this.root, foundation);
}
}<!-- Use data attribute for unbounded ripples -->
<div class="my-surface" data-mdc-ripple-is-unbounded>
<p>Surface with unbounded ripple</p>
</div>import { MDCRipple } from "@material/ripple";
// Ripple automatically detects data-mdc-ripple-is-unbounded
const ripple = new MDCRipple(document.querySelector('.my-surface'));
console.log(ripple.unbounded); // true