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

sass.mddocs/

Sass API

The Sass API provides comprehensive mixin and function systems for styling ripple effects with CSS-only fallbacks. It supports both basic and advanced configuration patterns for different design requirements.

Capabilities

Core Mixins

These mixins are required for any ripple implementation.

/**
 * Base ripple surface styles - MANDATORY
 * Adds fundamental styles required for ripple effects
 */
@mixin surface();

/**
 * Bounded ripple radius styles
 * For ripples clipped by element boundaries (most common)
 * @param $radius - Border radius for the ripple bounds (default: 100%)
 */
@mixin radius-bounded($radius: 100%);

/**
 * Unbounded ripple radius styles  
 * For ripples extending beyond element boundaries (checkboxes, radio buttons)
 * @param $radius - Border radius for the ripple effect (default: 100%)
 */
@mixin radius-unbounded($radius: 100%);

Usage Example:

@use "@material/ripple";

.my-button {
  @include ripple.surface;
  @include ripple.radius-bounded;
  @include ripple.states;
}

.my-checkbox-ripple {
  @include ripple.surface;
  @include ripple.radius-unbounded;
  @include ripple.states;
}

Basic State Mixins

Simple approach using automatic opacity calculations based on color lightness.

/**
 * Basic state styles with automatic opacity - MANDATORY when using basic approach
 * Adds hover, focus, and press state styles using calculated opacities
 * @param $color - Base color for the ripple effect
 * @param $has-nested-focusable-element - Whether element contains focusable children (default: false)
 */ 
@mixin states($color, $has-nested-focusable-element: false);

/**
 * Activated state styles for toggleable elements
 * @param $color - Base color for activated states
 * @param $has-nested-focusable-element - Whether element contains focusable children (default: false)
 */
@mixin states-activated($color, $has-nested-focusable-element: false);

/**
 * Selected state styles for selectable elements
 * @param $color - Base color for selected states  
 * @param $has-nested-focusable-element - Whether element contains focusable children (default: false)
 */
@mixin states-selected($color, $has-nested-focusable-element: false);

Usage Examples:

@use "@material/ripple";
@use "@material/theme";

// Basic button with primary theme color
.my-button {
  @include ripple.surface;
  @include ripple.radius-bounded;
  @include ripple.states(theme.prop-value(primary));
}

// Toggleable element with activated states
.my-toggle {
  @include ripple.surface;
  @include ripple.radius-bounded;
  @include ripple.states(theme.prop-value(on-surface));
  
  &--activated {
    @include ripple.states-activated(theme.prop-value(primary));
  }
}

// Form field with nested input
.my-form-field {
  @include ripple.surface;
  @include ripple.radius-bounded;
  @include ripple.states(theme.prop-value(on-surface), $has-nested-focusable-element: true);
}

Advanced State Mixins

Granular control over individual state opacities.

/**
 * Base color setup for advanced states - MANDATORY when using advanced approach
 * @param $color - Base color for all state calculations
 */
@mixin states-base-color($color);

/**
 * Custom opacity values for specific interaction states
 * @param $opacity-map - Map of state names to opacity values (hover, focus, press)
 * @param $has-nested-focusable-element - Whether element contains focusable children (default: false)
 */
@mixin states-opacities($opacity-map, $has-nested-focusable-element: false);

Usage Example:

@use "@material/ripple";

.my-custom-surface {
  @include ripple.surface;
  @include ripple.radius-bounded;
  @include ripple.states-base-color(#1976d2);
  @include ripple.states-opacities((
    hover: 0.04,
    focus: 0.12,
    press: 0.10
  ));
}

// Different opacities for activated state
.my-custom-surface--activated {
  @include ripple.states-base-color(#ffffff);
  @include ripple.states-opacities((
    hover: 0.08,
    focus: 0.24,
    press: 0.20
  ));
}

Deprecated Mixins

These mixins are deprecated but still supported for backward compatibility.

/**
 * DEPRECATED: Use states-opacities instead
 * Set hover state opacity
 * @param $opacity - Hover opacity value
 */
@mixin states-hover-opacity($opacity);

/**
 * DEPRECATED: Use states-opacities instead  
 * Set focus state opacity
 * @param $opacity - Focus opacity value
 * @param $has-nested-focusable-element - Whether element contains focusable children (default: false)
 */
@mixin states-focus-opacity($opacity, $has-nested-focusable-element: false);

/**
 * DEPRECATED: Use states-opacities instead
 * Set press state opacity
 * @param $opacity - Press opacity value
 */
@mixin states-press-opacity($opacity);

Sass Functions

Utility functions for opacity calculations and color manipulation.

/**
 * Calculate appropriate opacity for a color in a given state
 * @param $color - Base color value
 * @param $state - State name (hover, focus, press, selected, activated)
 * @returns Calculated opacity value for the color and state combination
 */
@function states-opacity($color, $state);

Usage Example:

@use "@material/ripple";

$primary-color: #1976d2;

.my-element {
  @include ripple.surface;
  @include ripple.radius-bounded;
  @include ripple.states-base-color($primary-color);
  @include ripple.states-opacities((
    hover: ripple.states-opacity($primary-color, hover),
    focus: ripple.states-opacity($primary-color, focus),
    press: ripple.states-opacity($primary-color, press)
  ));
}

CSS Classes

When JavaScript is not available, these CSS classes provide basic ripple styling.

Surface Classes

/**
 * Basic ripple surface class
 * Apply to elements that should have ripple effects
 */
.mdc-ripple-surface {}

/**
 * Primary theme color ripple
 * Uses the theme's primary color for ripple effects
 */
.mdc-ripple-surface--primary {}

/**
 * Secondary theme color ripple  
 * Uses the theme's secondary (accent) color for ripple effects
 */
.mdc-ripple-surface--accent {}

State Classes (Applied by JavaScript)

/**
 * Applied when ripple is upgraded with JavaScript
 * Enables CSS variable-based ripple animations
 */
.mdc-ripple-upgraded {}

/**
 * Applied to unbounded ripples
 * Allows ripple to extend beyond element boundaries
 */
.mdc-ripple-upgraded--unbounded {}

/**
 * Applied during focus state
 * Shows background highlighting for focused elements
 */
.mdc-ripple-upgraded--background-focused {}

/**
 * Applied during ripple activation animation
 * Triggers the expanding ripple effect
 */
.mdc-ripple-upgraded--foreground-activation {}

/**
 * Applied during ripple deactivation animation
 * Triggers the fade-out ripple effect
 */
.mdc-ripple-upgraded--foreground-deactivation {}

Implementation Patterns

Basic Button Implementation

@use "@material/ripple";
@use "@material/theme";

.custom-button {
  // Base button styles
  padding: 8px 16px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  
  // Ripple integration
  @include ripple.surface;
  @include ripple.radius-bounded;
  @include ripple.states(theme.prop-value(primary));
  
  // Ensure proper stacking context
  position: relative;
  overflow: hidden;
}

Icon Button (Unbounded)

@use "@material/ripple";
@use "@material/theme";

.icon-button {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: none;
  background: transparent;
  cursor: pointer;
  
  // Unbounded ripple for circular button
  @include ripple.surface;
  @include ripple.radius-unbounded;
  @include ripple.states(theme.prop-value(on-surface));
  
  // Ensure ripple visibility
  position: relative;
  overflow: visible;
}

Form Field with Nested Input

@use "@material/ripple";
@use "@material/theme";

.form-field {
  padding: 16px;
  border: 1px solid;
  border-radius: 4px;
  cursor: pointer;
  
  // Ripple with nested focusable element
  @include ripple.surface;
  @include ripple.radius-bounded;
  @include ripple.states(
    theme.prop-value(on-surface), 
    $has-nested-focusable-element: true
  );
  
  position: relative;
  overflow: hidden;
  
  input {
    // Input styling
    border: none;
    background: transparent;
    outline: none;
  }
}

Advanced Custom Ripple

@use "@material/ripple";

.premium-surface {
  @include ripple.surface;
  @include ripple.radius-bounded(8px);
  
  // Custom color and opacity configuration
  @include ripple.states-base-color(#9c27b0);
  @include ripple.states-opacities((
    hover: 0.06,
    focus: 0.18,
    press: 0.14
  ));
  
  // Premium activated state
  &--premium {
    @include ripple.states-base-color(#ffd700);
    @include ripple.states-opacities((
      hover: 0.08,
      focus: 0.20,
      press: 0.16
    ));
  }
}

CSS-Only Fallback Pattern

@use "@material/ripple";
@use "@material/theme";

.fallback-button {
  @include ripple.surface;
  @include ripple.radius-bounded;
  @include ripple.states(theme.prop-value(primary));
  
  // CSS-only states using pseudo-classes
  // These work when JavaScript is disabled
  &:hover {
    // Hover styles applied via CSS
  }
  
  &:focus {
    // Focus styles applied via CSS
  }
  
  &:active {
    // Active/press styles applied via CSS
  }
}

CSS Variables

The Sass system generates and manages these CSS custom properties:

Size and Position Variables

--mdc-ripple-fg-size: /* Foreground ripple size */
--mdc-ripple-left: /* Left position for unbounded ripples */
--mdc-ripple-top: /* Top position for unbounded ripples */

Animation Variables

--mdc-ripple-fg-scale: /* Scale factor for ripple animation */
--mdc-ripple-fg-translate-start: /* Animation start position */
--mdc-ripple-fg-translate-end: /* Animation end position */

These variables are automatically managed by the JavaScript foundation and should not be set manually in most cases.

docs

adapter.md

component.md

foundation.md

index.md

sass.md

utilities.md

tile.json