CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-material--ripple

Material Design ink ripple effect component for web element interactions with JavaScript and CSS-only implementations

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

foundation.mddocs/

Foundation API

The MDCRippleFoundation handles the core ripple logic, including activation/deactivation animations, event coordination, and CSS variable management. It follows the Material Components architecture pattern of separating business logic from DOM interactions.

Capabilities

MDCRippleFoundation Class

Core ripple logic and state management foundation.

/**
 * Core ripple logic and state management
 * Handles activation/deactivation animations, event coordination, and CSS variable updates
 */
class MDCRippleFoundation extends MDCFoundation<MDCRippleAdapter> {
  /** CSS class constants used by the foundation */
  static readonly cssClasses: {
    BG_FOCUSED: 'mdc-ripple-upgraded--background-focused';
    FG_ACTIVATION: 'mdc-ripple-upgraded--foreground-activation';
    FG_DEACTIVATION: 'mdc-ripple-upgraded--foreground-deactivation';
    ROOT: 'mdc-ripple-upgraded';
    UNBOUNDED: 'mdc-ripple-upgraded--unbounded';
  };
  
  /** CSS custom property name constants */
  static readonly strings: {
    VAR_FG_SCALE: '--mdc-ripple-fg-scale';
    VAR_FG_SIZE: '--mdc-ripple-fg-size';
    VAR_FG_TRANSLATE_END: '--mdc-ripple-fg-translate-end';
    VAR_FG_TRANSLATE_START: '--mdc-ripple-fg-translate-start';
    VAR_LEFT: '--mdc-ripple-left';
    VAR_TOP: '--mdc-ripple-top';
  };
  
  /** Timing and dimension constants */
  static readonly numbers: {
    DEACTIVATION_TIMEOUT_MS: 225;
    FG_DEACTIVATION_MS: 150;
    INITIAL_ORIGIN_SCALE: 0.6;
    PADDING: 10;
    TAP_DELAY_MS: 300;
  };
  
  /** Default adapter implementation for testing */
  static readonly defaultAdapter: MDCRippleAdapter;
  
  /** Trigger ripple activation with optional event context */
  activate(evt?: Event): void;
  
  /** Trigger ripple deactivation */
  deactivate(): void;
  
  /** Recompute layout properties and CSS variables */
  layout(): void;
  
  /** Set whether ripple is bounded or unbounded */
  setUnbounded(unbounded: boolean): void;
  
  /** Handle focus events by adding focus state styles */
  handleFocus(): void;
  
  /** Handle blur events by removing focus state styles */
  handleBlur(): void;
}

Usage Examples:

import { MDCRippleFoundation, MDCRippleAdapter } from "@material/ripple";

// Create custom adapter
const adapter: MDCRippleAdapter = {
  addClass: (className) => element.classList.add(className),
  removeClass: (className) => element.classList.remove(className),
  browserSupportsCssVars: () => CSS.supports('--css-vars', 'yes'),
  // ... implement all required methods
};

// Create foundation with custom adapter
const foundation = new MDCRippleFoundation(adapter);

// Initialize ripple system
foundation.init();

// Programmatic control
foundation.activate(); // Trigger activation animation
foundation.deactivate(); // Trigger deactivation animation
foundation.layout(); // Recompute dimensions

// Configuration
foundation.setUnbounded(true); // Make ripple unbounded

// Event handling
foundation.handleFocus(); // Add focus styles
foundation.handleBlur(); // Remove focus styles

// Cleanup
foundation.destroy();

Static Properties

cssClasses

CSS class constants used throughout the ripple system.

/**
 * CSS class constants used by the foundation
 */
static readonly cssClasses: {
  /** Background focus state class */
  BG_FOCUSED: 'mdc-ripple-upgraded--background-focused';
  /** Foreground activation animation class */
  FG_ACTIVATION: 'mdc-ripple-upgraded--foreground-activation';
  /** Foreground deactivation animation class */
  FG_DEACTIVATION: 'mdc-ripple-upgraded--foreground-deactivation';
  /** Root ripple upgrade class */
  ROOT: 'mdc-ripple-upgraded';
  /** Unbounded ripple class */
  UNBOUNDED: 'mdc-ripple-upgraded--unbounded';
};

strings

CSS custom property name constants.

/**
 * CSS custom property name constants
 */
static readonly strings: {
  /** Foreground scale CSS variable */
  VAR_FG_SCALE: '--mdc-ripple-fg-scale';
  /** Foreground size CSS variable */
  VAR_FG_SIZE: '--mdc-ripple-fg-size';
  /** Translation end position CSS variable */
  VAR_FG_TRANSLATE_END: '--mdc-ripple-fg-translate-end';
  /** Translation start position CSS variable */
  VAR_FG_TRANSLATE_START: '--mdc-ripple-fg-translate-start';
  /** Left position CSS variable */
  VAR_LEFT: '--mdc-ripple-left';
  /** Top position CSS variable */
  VAR_TOP: '--mdc-ripple-top';
};

numbers

Timing and dimension constants used for animations.

/**
 * Timing and dimension constants
 */
static readonly numbers: {
  /** Activation animation duration in milliseconds */
  DEACTIVATION_TIMEOUT_MS: 225;
  /** Deactivation animation duration in milliseconds */
  FG_DEACTIVATION_MS: 150;
  /** Initial ripple scale factor */
  INITIAL_ORIGIN_SCALE: 0.6;
  /** Bounded ripple padding in pixels */
  PADDING: 10;
  /** Touch to mouse event delay in milliseconds */
  TAP_DELAY_MS: 300;
};

defaultAdapter

Default adapter implementation for testing and reference.

/**
 * Default adapter implementation for testing
 * All methods return safe default values
 */
static readonly defaultAdapter: MDCRippleAdapter;

Instance Methods

activate

Triggers ripple activation animation, optionally using event coordinates.

/**
 * Trigger ripple activation with optional event context
 * @param evt - Optional event containing position information for ripple origin
 */
activate(evt?: Event): void;

deactivate

Triggers ripple deactivation animation.

/**
 * Trigger ripple deactivation
 * Completes the ripple animation cycle
 */
deactivate(): void;

layout

Recomputes all layout properties and updates CSS variables.

/**
 * Recompute layout properties and CSS variables
 * Call this when element dimensions change
 */
layout(): void;

setUnbounded

Configures whether the ripple is bounded by element dimensions.

/**
 * Set whether ripple is bounded or unbounded
 * @param unbounded - True for unbounded ripples (extend beyond element)
 */
setUnbounded(unbounded: boolean): void;

handleFocus

Handles focus events by applying focus state styling.

/**
 * Handle focus events by adding focus state styles
 * Adds background focus highlighting
 */
handleFocus(): void;

handleBlur

Handles blur events by removing focus state styling.

/**
 * Handle blur events by removing focus state styles  
 * Removes background focus highlighting
 */
handleBlur(): void;

Advanced Usage

Custom Foundation with Mixed Adapter

import { MDCRippleFoundation, MDCRipple } from "@material/ripple";

class CustomRippleComponent {
  constructor(element) {
    this.root = element;
    this.unbounded = false;
    this.disabled = false;
    this.isPressed = false;
    
    // Create foundation with custom behavior
    const foundation = new MDCRippleFoundation({
      ...MDCRipple.createAdapter(this),
      // Override for custom active state detection
      isSurfaceActive: () => this.isPressed,
      // Custom CSS variable updates
      updateCssVariable: (varName, value) => {
        this.root.style.setProperty(varName, value);
        console.log(`Updated ${varName} to ${value}`);
      }
    });
    
    this.foundation = foundation;
    this.foundation.init();
  }
  
  // Custom press handling
  onPress() {
    this.isPressed = true;
    this.foundation.activate();
  }
  
  onRelease() {
    this.isPressed = false;
    this.foundation.deactivate();
  }
}

Event-Driven Activation

import { MDCRippleFoundation } from "@material/ripple";

// Foundation automatically handles standard activation events:
// - touchstart, pointerdown, mousedown, keydown
// - touchend, pointerup, mouseup, contextmenu, keyup

const foundation = new MDCRippleFoundation(adapter);
foundation.init(); // Registers event handlers automatically

// The foundation will:
// 1. Listen for activation events (touchstart, mousedown, etc.)
// 2. Calculate ripple origin from event coordinates
// 3. Trigger activation animation
// 4. Listen for deactivation events (touchend, mouseup, etc.)
// 5. Trigger deactivation animation

CSS Variable Management

import { MDCRippleFoundation } from "@material/ripple";

// The foundation manages these CSS variables automatically:
const { strings } = MDCRippleFoundation;

// Size and positioning
console.log(strings.VAR_FG_SIZE);    // '--mdc-ripple-fg-size'
console.log(strings.VAR_LEFT);       // '--mdc-ripple-left'  
console.log(strings.VAR_TOP);        // '--mdc-ripple-top'

// Animation properties
console.log(strings.VAR_FG_SCALE);   // '--mdc-ripple-fg-scale'
console.log(strings.VAR_FG_TRANSLATE_START); // '--mdc-ripple-fg-translate-start'
console.log(strings.VAR_FG_TRANSLATE_END);   // '--mdc-ripple-fg-translate-end'

// Variables are updated automatically during:
// - layout() calls
// - activate() calls  
// - Animation state changes

State Management

// The foundation tracks several internal states:
// - isActivated: Whether ripple is currently active
// - wasActivatedByPointer: Whether activation came from touch/mouse
// - isProgrammatic: Whether activation was called programmatically
// - hasDeactivationUXRun: Whether deactivation animation has started

// These states ensure:
// - Proper animation sequencing
// - Avoiding duplicate activations
// - Coordinating with nested interactive elements
// - Managing focus and keyboard interactions

docs

adapter.md

component.md

foundation.md

index.md

sass.md

utilities.md

tile.json