Material Design ink ripple effect component for web element interactions with JavaScript and CSS-only implementations
npx @tessl/cli install tessl/npm-material--ripple@14.0.0Material 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;