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
Material Ripple provides Material Design ink ripple interaction effects for web components. It implements the official Material Design specifications for touch feedback animations, offering both JavaScript-enabled and CSS-only fallback implementations for maximum compatibility.
npm install @material/rippleimport { MDCRipple, MDCRippleFoundation } from "@material/ripple";For individual imports:
import { MDCRipple } from "@material/ripple/component";
import { MDCRippleFoundation } from "@material/ripple/foundation";
import { MDCRippleAdapter } from "@material/ripple/adapter";
import * as util from "@material/ripple/util";
import { cssClasses, strings, numbers } from "@material/ripple/constants";CommonJS:
const { MDCRipple, MDCRippleFoundation } = require("@material/ripple");Sass imports:
@use "@material/ripple";import { MDCRipple } from "@material/ripple";
// Basic ripple attachment
const surface = document.querySelector('.my-surface');
const ripple = new MDCRipple(surface);
// Using static attachTo method
MDCRipple.attachTo(document.querySelector('.my-surface'));
// Unbounded ripple (like checkboxes/radio buttons)
const unboundedRipple = MDCRipple.attachTo(surface, { isUnbounded: true });
// Programmatic activation
ripple.activate();
ripple.deactivate();CSS setup:
@use "@material/ripple";
.my-surface {
@include ripple.surface;
@include ripple.radius-bounded;
@include ripple.states;
}Material Ripple is built around several key components:
Primary JavaScript interface for attaching and controlling ripples programmatically. Provides methods for activation, deactivation, and configuration.
class MDCRipple extends MDCComponent<MDCRippleFoundation> {
static attachTo(root: Element, opts?: MDCRippleAttachOpts): MDCRipple;
static createAdapter(instance: MDCRippleCapableSurface): MDCRippleAdapter;
unbounded: boolean;
disabled: boolean;
activate(): void;
deactivate(): void;
layout(): void;
}Core ripple logic and state management. Handles activation/deactivation animations, event coordination, and CSS variable updates.
class MDCRippleFoundation extends MDCFoundation<MDCRippleAdapter> {
static readonly cssClasses: typeof cssClasses;
static readonly strings: typeof strings;
static readonly numbers: typeof numbers;
static readonly defaultAdapter: MDCRippleAdapter;
activate(evt?: Event): void;
deactivate(): void;
layout(): void;
setUnbounded(unbounded: boolean): void;
handleFocus(): void;
handleBlur(): void;
}Integration interface for custom frameworks and components. Defines required methods for DOM manipulation, event handling, and CSS updates.
interface MDCRippleAdapter {
browserSupportsCssVars(): boolean;
isUnbounded(): boolean;
isSurfaceActive(): boolean;
isSurfaceDisabled(): boolean;
addClass(className: string): void;
removeClass(className: string): void;
containsEventTarget(target: EventTarget | null): boolean;
updateCssVariable(varName: string, value: string | null): void;
computeBoundingRect(): DOMRect;
getWindowPageOffset(): MDCRipplePoint;
}Comprehensive mixin system for styling different ripple configurations, including bounded/unbounded ripples and various interaction states.
@mixin surface();
@mixin radius-bounded($radius: 100%);
@mixin radius-unbounded($radius: 100%);
@mixin states($color, $has-nested-focusable-element: false);
@mixin states-base-color($color);
@mixin states-opacities($opacity-map, $has-nested-focusable-element: false);
@function states-opacity($color, $state);Helper functions for CSS variable support detection and event coordinate normalization across different input types.
function supportsCssVariables(windowObj: typeof globalThis, forceRefresh?: boolean): boolean;
function getNormalizedEventCoords(evt: Event | undefined, pageOffset: MDCRipplePoint, clientRect: DOMRect): MDCRipplePoint;interface MDCRippleAttachOpts {
isUnbounded?: boolean;
}
interface MDCRippleCapableSurface {
root: Element;
unbounded?: boolean;
disabled?: boolean;
}
interface MDCRipplePoint {
x: number;
y: number;
}
type MDCRippleFactory = (el: Element, foundation?: MDCRippleFoundation) => MDCRipple;From @material/base:
abstract class MDCComponent<FoundationType extends MDCFoundation> {
readonly root: Element;
destroy(): void;
static attachTo(root: Element): MDCComponent<any>;
}
abstract class MDCFoundation<AdapterType> {
protected adapter: AdapterType;
init(): void;
destroy(): void;
}From @material/base/types:
type EventType = keyof HTMLElementEventMap;
type SpecificEventListener<K extends EventType> = (event: HTMLElementEventMap[K]) => void;