npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

liquid-glass-web-react

v0.1.1

Published

Apple-style liquid glass refraction for React. Cross-browser (Chrome, Safari, Firefox) — real SVG displacement over live DOM, no backdrop-filter hacks.

Readme

liquid-glass-web-react

Apple-style liquid glass for React — a lens that refracts live DOM.

CI npm license

Demo

https://agpallav.com/liquid-glass

Universal

Most liquid-glass libraries lean on an SVG backdrop-filter, which only works in Chromium. liquid-glass-web-react generates a displacement map on the fly and feeds it to an SVG feDisplacementMap filter applied to the content itself, so it works in Chrome, Safari, and Firefox, desktop and mobile, with no flags and no fallbacks.

  • Live content — the lens bends pixels the browser already painted. Text stays selectable, links stay clickable, video keeps playing.
  • Fast to animate — moving the lens only shifts the filter region. The map regenerates only when the lens changes shape, never when it changes place.
  • Tiny — zero dependencies, tree-shakeable, ~5 kB min+gzip.
  • Implementation - inspired by Aave's excellent writeup.

Installation

npm install liquid-glass-web-react

Quick start

import { LiquidGlass } from "liquid-glass-web-react";

<LiquidGlass draggable>
  <img src="https://picsum.photos/id/1015/1200/700" />
</LiquidGlass>;

That's it — a draggable glass lens over your content. Everything is customizable:

<LiquidGlass
  x={0.3}                    // lens center, fraction of the container
  y={0.5}
  width={200}                // lens size in px
  height={140}
  radius={48}                // corner radius ("auto" = pill)
  strength={0.12}            // refraction strength
  chromaticAberration={0.3}  // color fringing at the edges
  curvature={0.8}            // 0 = flat profile, 1 = spherical dome
  glow={0.15}                // inner specular glow
  edgeHighlight={0.3}        // bright rim
>
  <Dashboard />
</LiquidGlass>

As a selection indicator

The lens makes a great moving highlight — drive x from state (or animate it through the imperative handle for zero re-renders):

const lens = useRef<LiquidGlassHandle>(null);

<LiquidGlass ref={lens} x={(selected + 0.5) / options.length} width={104} height={46}>
  <ToggleGroup options={options} onSelect={setSelected} />
</LiquidGlass>;

// per-frame, bypassing React:
lens.current?.setPosition(x, 0.5);

Without React

The React component is a thin wrapper over LiquidGlassEngine, which is plain DOM:

import { LiquidGlassEngine } from "liquid-glass-web-react";

const engine = new LiquidGlassEngine({ container, filtered, defsHost });
engine.setPosition(0.5, 0.5);
engine.setOptions({ width: 200, strength: 0.12 });

API

<LiquidGlass> props

All props are optional.

| Prop | Type | Default | Description | | --- | --- | --- | --- | | x, y | number | 0.5 | Lens center as a fraction of the container (0–1). | | width, height | number | 160, 120 | Lens size in px. | | radius | number \| "auto" | "auto" | Corner radius in px; "auto" is a full pill. | | strength | number | 0.1 | Refraction strength (fraction of container size). | | chromaticAberration | number | 0.2 | Per-channel scale offset, 0–1. | | blur | number | 0 | Blur of the refracted content, px. | | depth | number | 10 | Width of the refracting edge band, px. | | curvature | number | 0.65 | Lens profile: 0 linear → 1 spherical dome. | | splay | number | 1 | Keeps edge refraction perpendicular to the edge, 0–1. | | glow | number | 0.1 | Inner specular glow, 0–1. | | edgeHighlight | number | 0.25 | Bright rim along the lens edge, 0–1. | | specular | number | 1 | Master intensity of the specular pass. | | specularAngle | number | 45 | Light direction, degrees. | | draggable | boolean | false | Let the user drag the lens. | | shadow | boolean \| string | true | Lens drop shadow; pass a box-shadow string to customize. | | quality | number | 512 | Displacement map resolution. | | onMove | (x, y) => void | — | Fires as the lens moves. | | onMapGenerated | (url) => void | — | Fires with the map PNG data URL on regeneration. |

Plus any <div> prop (className, style, …). The component renders a position: relative wrapper around your children.

Imperative handle

ref exposes { element, engine, setPosition(x, y) }. setPosition is safe to call once per frame; it never regenerates the map and never re-renders React.

Low-level exports

LiquidGlassEngine, computeDisplacementMap, renderDisplacementMap, DEFAULT_OPTIONS — for custom renderers (e.g. WebGL) or non-React use.

How it works

  1. A small PNG displacement map is computed from the lens geometry: red/green channels encode how far each pixel bends, blue carries a baked specular highlight, and alpha is the exact lens shape (used to clip the result, so blur and refraction follow the rounded geometry). Outside the lens the map is neutral, so those pixels don't move. The map has four-fold symmetry, so only a quarter of it is actually computed.
  2. An SVG filter built around feDisplacementMap reads that map and bends the element's own painted pixels — three displacement taps at slightly different scales produce the chromatic fringe, a composite lifts the blue channel into a highlight, and the lens shape is composited over the untouched original.
  3. Moving the lens only updates the filter's subregion attributes in place, which is why dragging holds a steady frame rate. On Safari/WebKit the filter also gets a fresh ID per update — Safari caches filter output by ID and would otherwise serve stale frames.

The technique follows Aave's excellent write-up, Building Glass for the Web.

Notes & limitations

  • SSR: safe with Next.js/Remix — all DOM work happens in effects. The bundle is marked "use client".
  • Safari caps the size of the source an SVG filter can process. Very large refracted containers (several thousand px) may degrade; keep the glass on reasonably sized regions. The engine logs a one-time console warning on Safari when an element is big enough to risk it.
  • iOS misplaces filter subregions expressed in objectBoundingBox units, so the engine automatically switches to userSpaceOnUse units there. No configuration needed; strength means the same thing on every platform.
  • <video> in Safari never reaches the SVG filter pipeline (a WebKit limitation). Refracting live video there requires a WebGL renderer — computeDisplacementMap is exported so you can feed the same map to your own shader.
  • A lens that needs to look right over moving content benefits from more edgeHighlight and glow to stay legible.

Development

npm install
npm run dev    # playground at localhost:5173
npm test       # unit tests for the map math
npm run build  # esm + cjs + d.ts to dist/

License

MIT