Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

@specy/liquid-glass-react

Specy1.1kMIT1.0.2TypeScript support: included

React component for @specy/liquid-glass - A Three.js powered library to make apple's liquid with glass effect

react, three.js, glass-effect, morphing, animation, webgl, ui-component, liquid-glass, react-component

readme

@specy/liquid-glass-react

React wrapper for @specy/liquid-glass - A Three.js powered glass effect component that recreates apple's liquid glass .

Installation

npm install @specy/liquid-glass-react

Basic Usage

Initialization is expensive, try to minimize re-renders and unnecessary unmouts.

The component does it's best to track the position of the target element in the page and update the effect, but it cannot track the top or left etc.. position changes, if you update them, you should call the forceUpdate method on the ref to re-render the effect, or use the renderKey prop to force a re-render when needed.

import React, { useMemo } from 'react';
import { LiquidGlass } from '@specy/liquid-glass-react';

function App() {
  // ⚠️ IMPORTANT: Memoize the glassStyle object to prevent unnecessary re-renders
  const glassStyle = useMemo(() => ({
    depth: 0.5,
    segments: 32,
    radius: 0.2,
    roughness: 0.1,
    transmission: 1,
    reflectivity: 0.5,
    ior: 1.5,
    dispersion: 0.1,
    thickness: 0.5
  }), []);

  return (
    <LiquidGlass
      glassStyle={glassStyle}
      wrapperStyle={{
        position: 'fixed',
        bottom: 0,
        left: 0,
        right: 0,
        width: 'fit-content',\
        margin: '0 auto',
      }}
      style={`padding: 1rem;`}
    >
      <div>
        <h1>Hello World!</h1>
        <p>This content is rendered inside the liquid glass effect.</p>
      </div>
    </LiquidGlass>
  );
}

Advanced Usage with Ref

import React, { useRef, useMemo, useCallback } from "react"
import { LiquidGlass, type LiquidGlassRef } from "@specy/liquid-glass-react"

function AdvancedExample() {
    const glassRef = useRef<LiquidGlassRef>(null)

    // ⚠️ IMPORTANT: Memoize all objects and callbacks
    const glassStyle = useMemo(
        () => ({
            depth: 0.8,
            segments: 64,
            radius: 0.3,
            transmission: 0.95,
            roughness: 0.05,
        }),
        []
    )

    const onReady = useCallback((instance) => {
        console.log("LiquidGlass instance ready:", instance)
    }, [])

    const handleUpdateScreenshot = useCallback(async () => {
        await glassRef.current?.updateScreenshot()
    }, [])

    const handleUpdateStyle = useCallback(() => {
        glassRef.current?.updateGlassStyle({
            depth: Math.random(),
            transmission: 0.8 + Math.random() * 0.2,
        })
    }, [])

    return (
        <div>
            <LiquidGlass ref={glassRef} glassStyle={glassStyle} onReady={onReady}>
                <div style={{ padding: "30px" }}>
                    <h2>Interactive Glass Effect</h2>
                    <button onClick={handleUpdateScreenshot}>Update Screenshot</button>
                    <button onClick={handleUpdateStyle}>Randomize Style</button>
                </div>
            </LiquidGlass>
        </div>
    )
}

Props

Prop Type Default Description
style string '' Custom CSS styles to apply to the glass container
wrapperStyle React.CSSProperties {} React CSS properties to apply to the wrapper div
glassStyle GlassStyle {} Glass material properties (see GlassStyle interface)
children React.ReactNode undefined Content to render inside the glass container
onReady (instance: LiquidGlass) => void undefined Callback when the liquid glass instance is ready
targetElement HTMLElement document.body The target element to capture for the glass background effect
renderKey `string number` Unique key to force re-render the component when changed (manually)

GlassStyle Interface

interface GlassStyle {
    depth?: number // Depth of the glass effect (0-1)
    segments?: number // Number of geometry segments for smoothness
    radius?: number // Border radius (0-1)
    tint?: number | null // Color tint (hex number or null)
    roughness?: number // Surface roughness (0-1)
    transmission?: number // Light transmission (0-1)
    reflectivity?: number // Surface reflectivity (0-1)
    ior?: number // Index of refraction
    dispersion?: number // Chromatic dispersion effect
    thickness?: number // Glass thickness
}

Ref Methods

The component exposes several methods through the ref:

interface LiquidGlassRef {
    getInstance(): LiquidGlass | null
    updateScreenshot(): Promise<void>
    forceUpdate(): Promise<void>
    updateGlassStyle(style: Partial<GlassStyle>): void
    getGlassStyle(): Required<GlassStyle> | null
    getElement(): HTMLElement | null
    getContent(): HTMLDivElement | null
  forcePositionUpdate(): void
  forceSizeUpdate(): void
}

Contributing

Issues and pull requests are welcome at the main repository.