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

ios-liquid-glass-style

v0.1.0

Published

Apple-style iOS Liquid Glass UI component library for React — real backdrop refraction, TypeScript, tree-shakeable, ESM + CJS.

Downloads

157

Readme

ios-liquid-glass-style

Apple-style Liquid Glass UI components for React. A translucent material that visibly bends the content behind it at the rim — with a faint prism fringe — while the interior stays legible. Real backdrop refraction in Chromium (Chrome, Edge, Arc, Brave); an automatic frosted-blur fallback everywhere else.

This is a faithful React port of the original liquid-glass vanilla implementation — the optics engine, the glass material, and the Card / Input / Button styling are preserved pixel-for-pixel. The rest of the component set (Modal, Navbar, Select, Alert, Checkbox, Radio, Switch, …) is built in the exact same design language.

  • 🧊 Real refraction — the SVG-displacement engine, ported byte-for-byte.
  • ⚛️ Idiomatic React — hooks, refs, controlled/uncontrolled, no manual DOM.
  • 🌲 Tree-shakeable — ESM + CJS, side-effect-free JS, per-component imports.
  • 🔡 Typed — written in TypeScript, ships .d.ts declarations.
  • Accessible — roles, aria-*, focus management, keyboard support.

Install

npm install ios-liquid-glass-style

react and react-dom (>= 17) are peer dependencies.

Setup

Import the stylesheet once, at your app root:

import "ios-liquid-glass-style/styles.css";

Then use the components. Two import styles are supported:

// 1) Namespace — great for discoverability
import { Liq } from "ios-liquid-glass-style";

<Liq.Card title="Liquid glass">
  <Liq.Input placeholder="Enter your name" />
  <Liq.Button>Submit</Liq.Button>
</Liq.Card>

<Liq.Alert type="success" message="Successfully saved!" />
// 2) Named — best for tree-shaking
import { Button, Card, Input, Alert } from "ios-liquid-glass-style";

Both resolve to the same components. Named imports let your bundler drop any component you don't use.

Give the glass something to refract

Refraction only shows when there's colorful content behind the glass. Drop the included Background behind your app (it's the exact mesh from the original demo), or use your own imagery:

import { Background, Card } from "ios-liquid-glass-style";

<>
  <Background />
  <Card title="Liquid glass" style={{ position: "relative" }}>…</Card>
</>

The Liquid Glass engine

Any element can wear the material via the useLiquidGlass hook (every surface component uses it internally):

import { useRef } from "react";
import { useLiquidGlass } from "ios-liquid-glass-style";

function Panel() {
  const ref = useRef<HTMLDivElement>(null);
  const { supported, refresh } = useLiquidGlass(ref);
  return <div ref={ref} className="liq-surface">…</div>;
}

Engine options

Passed via the glassOptions prop on Glass/Card/Modal/Navbar/Button (variant="glass"), or as the second argument to useLiquidGlass. Defaults are identical to the original module:

| Option | Default | Meaning | |---|---|---| | scale | -112 | displacement strength; negative = magnifying bulge (−60 subtle … −180 dramatic) | | chroma | 6 | per-channel scale stagger (prism fringe); 0 disables | | border | 0.07 | neutral interior inset, fraction of the smaller side | | mapBlur | 12 | bulge curvature: small = hard rim, large = dome | | blur | 3 | backdrop blur inside the glass | | saturate | 1.5 | backdrop saturation boost | | radius | null | corner-radius override (px); defaults to the element's border-radius | | fallbackBlur | 16 | frosted blur on Safari/Firefox |

useLiquidGlass(ref, options, enabled?) returns { supported, refresh }supported is false on Safari/Firefox (frosted fallback applied); refresh() regenerates the displacement map (also runs automatically on element resize).

Browser support. Real refraction is Chromium-only. On Safari and Firefox the components automatically fall back to a frosted blur — never let the refraction carry meaning, only delight.

Performance

SVG-displacement backdrops are GPU-heavy, and a page with many live glass surfaces can get janky. The library keeps things smooth without changing how anything looks:

  • Viewport-gated refraction (lazy, on by default) — a surface only runs its backdrop filter while it's near the viewport, so scrolling a long, glass-dense page doesn't composite every off-screen filter each frame. Visible surfaces are pixel-identical. Disable per surface with lazy={false}, or tune how early it kicks in with rootMargin.
  • Cached displacement maps — identical-size surfaces share one generated map instead of each running a canvas toDataURL(), so re-activating on scroll (and first paint of many same-size cards) is nearly free.
  • rAF-batched dragginguseDraggable writes one update per frame.

If a view is still heavy, the cheapest lever is fewer simultaneously visible refracting surfaces — set refract={false} on secondary panels (they keep the exact glass tint + shadow, just without the live backdrop bend), or lower glassOptions={{ blur, chroma }}. None of these change the resting look of the surfaces you leave refracting.

Theming

Every value is a CSS custom property (see tokens.css). Override any of them on :root (or a scope) to re-theme the whole library without touching components:

:root {
  --liq-accent: #7c5cff;      /* checkboxes, radios, switches, focus accents */
  --liq-radius: 24px;         /* surface corner radius */
  --liq-radius-control: 12px; /* inputs / buttons */
}

Key tokens: --liq-bg, --liq-fg, --liq-fg-muted, --liq-surface-bg, --liq-surface-shadow, --liq-control-bg, --liq-control-border, --liq-control-border-focus, --liq-accent, --liq-success, --liq-warning, --liq-danger.

Per-component styling & color

Every component forwards className and style to its root element, so you can style — or recolor — a single instance without any global CSS. The cleanest way to recolor one instance is to override the CSS variable it reads, right in style:

// just these instances — no global theme change
<Checkbox style={{ "--liq-accent": "#ff5e7e" } as React.CSSProperties} />
<Switch   style={{ "--liq-accent": "#2fd4a7" } as React.CSSProperties} />
<Button   style={{ "--liq-btn-bg": "#ff5e7e", "--liq-btn-fg": "#0a0a12" } as React.CSSProperties}>Pink</Button>
<Input label="Tinted" style={{ "--liq-control-bg": "rgba(157,92,255,.18)" } as React.CSSProperties} />

(The as React.CSSProperties cast is only needed to satisfy TypeScript for the custom -- properties.) Which variable each component reads to recolor:

| Component(s) | Override to recolor | |---|---| | Card, Glass, Modal, Navbar, Alert | --liq-surface-bg, --liq-surface-shadow | | Button (primary) | --liq-btn-bg, --liq-btn-fg | | Input, Textarea, Select | --liq-control-bg, --liq-control-border, --liq-control-border-focus | | Checkbox, Radio, Switch | --liq-accent | | Alert (per type) | --liq-alert-accent (or --liq-success / --liq-warning / --liq-danger / --liq-accent) |

Use plain inline styles for one-off layout (style={{ marginTop: 12 }}), a className for reusable rules, and the CSS-variable overrides above for color. For labelled fields (Input/Textarea/Select) className/style land on the field root; target the control itself via its .liq-input / .liq-textarea / .liq-select__trigger class.

Components

All components forward refs, accept className + style, and spread native props. See docs/ for a page per component, and run the playground for a live sandbox:

npm run dev   # opens the playground

| Component | Import | Description | |---|---|---| | Glass | Glass | The material primitive — build custom glass surfaces. | | Card | Card (.Title .Description .Row) | The flagship draggable glass panel. | | Button | Button | primary (exact demo) / secondary / ghost / glass. | | Input | Input | Text field with optional label / hint / error. | | Textarea | Textarea | Multiline field with auto-resize. | | Select | Select | Accessible listbox with a glass popover + typeahead. | | Checkbox | Checkbox | Glass checkbox with indeterminate state. | | Radio | Radio, RadioGroup | Radio group via context. | | Switch | Switch | Toggle with role="switch". | | Alert | Alert | Status banner (info/success/warning/error). | | Modal | Modal / Dialog (.Header .Body .Footer) | Portalled dialog with focus trap. | | Navbar | Navbar (.Brand .Section .Item) | Glass navigation bar. | | Kbd | Kbd, Keyboard | Keyboard key caps + layouts. | | Background | Background | The demo's mesh + type backdrop to refract against. | | Hooks | useLiquidGlass, useDraggable, isSupported | The engine + drag, as hooks. |

Development

npm install
npm run dev        # playground (Vite)
npm run build      # dist/ — ESM + CJS + d.ts + styles.css
npm run typecheck  # tsc --noEmit

Authors

  • Amandeep — author
  • Pankaj — supporter

Credits

Technique informed by Aave's "Building glass for the web" and rizroze/liquid-glass. Ported from the original liquid-glass vanilla module.

License

MIT #� �L�i�q�u�i�d�e�-�g�l�a�s�s� � �