liquid-flow
v0.0.2
Published
Liquid glass UI components for React
Readme
liquid-flow
Liquid glass UI components for React. Every surface reacts to the cursor — specular highlights shift as the mouse moves, edges distort organically when elements are dragged, and a slow shimmer keeps things alive at rest.
Installation
npm install liquid-flowRequires React 18 or later as a peer dependency.
Components
LiquidGlass
The core primitive. A transparent glass surface that wraps any content.
import { LiquidGlass } from "liquid-flow";
<LiquidGlass radius={28} style={{ padding: "32px" }}>
<h2>Hello</h2>
<p>Any content goes here.</p>
</LiquidGlass>Props
| Prop | Type | Default | Description |
|------------|----------|---------|------------------------------------|
| radius | number | 28 | Border radius in pixels |
| children | ReactNode | — | Content rendered inside the glass |
| style | CSSProperties | — | Passed to the outermost wrapper |
| ...rest | HTMLDivElement attributes | — | Forwarded to the wrapper div |
LiquidButton
A glass button with hover, press, and cursor-tracking specular effects.
import { LiquidButton } from "liquid-flow";
<LiquidButton onClick={() => console.log("clicked")}>
Click me
</LiquidButton>
<LiquidButton variant="primary" size="lg">
Primary action
</LiquidButton>
<LiquidButton variant="danger" disabled>
Delete
</LiquidButton>Props
| Prop | Type | Default | Description |
|-------------|--------------------------------|-------------|------------------------------------------|
| variant | "default" \| "primary" \| "danger" | "default" | Color tint of the glass surface |
| size | "sm" \| "md" \| "lg" | "md" | Controls padding, font size, and radius |
| textColor | string | white | CSS color for the label text |
| disabled | boolean | false | Dims the button and disables interaction |
| ...rest | ButtonHTMLAttributes | — | Forwarded to the <button> element |
LiquidCard
A glass card panel with optional header and footer slots separated by hairline dividers.
import { LiquidCard } from "liquid-flow";
<LiquidCard
radius={24}
header={<h3>Title</h3>}
footer={<small>Last updated just now</small>}
style={{ padding: "20px", width: "360px" }}
>
<p>Card body content.</p>
</LiquidCard>Props
| Prop | Type | Default | Description |
|------------|-----------------|---------|-------------------------------------------------------|
| radius | number | 24 | Border radius in pixels |
| header | ReactNode | — | Rendered above the body with a divider below |
| footer | ReactNode | — | Rendered below the body with a divider above |
| children | ReactNode | — | Main body content |
| style | CSSProperties | — | Passed to the outermost wrapper |
| ...rest | HTMLDivElement attributes | — | Forwarded to the wrapper div |
LiquidInput
A glass text input with a focus ring and optional label and error message.
import { LiquidInput } from "liquid-flow";
<LiquidInput
label="Email"
type="email"
placeholder="[email protected]"
/>
<LiquidInput
label="Username"
error="Username is already taken"
defaultValue="hidden_umah"
/>Props
| Prop | Type | Default | Description |
|-------------|----------|---------|------------------------------------------------|
| label | string | — | Label text rendered above the input |
| error | string | — | Error message shown below; also turns the ring red |
| radius | number | 14 | Border radius in pixels |
| textColor | string | white | CSS color for the input text and label |
| ...rest | InputHTMLAttributes | — | Forwarded to the <input> element |
LiquidBadge
A compact glass pill for status labels, tags, or counts.
import { LiquidBadge } from "liquid-flow";
<LiquidBadge>Default</LiquidBadge>
<LiquidBadge variant="blue">New</LiquidBadge>
<LiquidBadge variant="green">Active</LiquidBadge>
<LiquidBadge variant="red">Error</LiquidBadge>
<LiquidBadge variant="yellow">Warning</LiquidBadge>Props
| Prop | Type | Default | Description |
|-------------|-------------------------------------------------|-------------|----------------------------------|
| variant | "default" \| "blue" \| "green" \| "red" \| "yellow" | "default" | Color tint and glow |
| textColor | string | white | CSS color for the label text |
| children | ReactNode | — | Badge label |
| ...rest | HTMLSpanElement attributes | — | Forwarded to the <span> |
LiquidToggle
A glass toggle switch with a spring-animated thumb.
import { LiquidToggle } from "liquid-flow";
import { useState } from "react";
function Demo() {
const [on, setOn] = useState(false);
return (
<LiquidToggle
checked={on}
onChange={setOn}
label="Enable notifications"
/>
);
}Props
| Prop | Type | Default | Description |
|-------------|-----------------------------|---------|-------------------------------------------------|
| checked | boolean | false | Controlled on/off state |
| onChange | (checked: boolean) => void| — | Called with the next state when toggled |
| label | string | — | Text label rendered beside the track |
| textColor | string | white | CSS color for the label text |
| disabled | boolean | false | Dims the toggle and disables interaction |
| style | CSSProperties | — | Applied to the outer flex wrapper |
How the glass effect works
Each component layers eight stacked div elements inside a single wrapper:
- Glass body —
backdrop-filter: blur(4px) saturate(160%)creates the frosted-clear look without going grey. - Outer chromatic ring — a cool blue border mimics chromatic aberration at the glass edge.
- Liquid edge band — a gradient ring distorted by an animated SVG
feTurbulence + feDisplacementMapfilter, making the perimeter look organic and alive. - Border + inner depth shadow — a bright top inset highlight and a dark bottom inset give the glass physical thickness.
- Primary specular — the main light hotspot. Updated every
pointermovevia a ref (no re-renders), so it follows the cursor. - Secondary specular — a dimmer highlight on the opposite side, giving the impression of a 3-D curved surface.
- Shimmer sweep — a faint diagonal light band that drifts continuously so the glass looks alive when idle.
- Inner warm fringe — a warm-tinted inner border complements the cool outer ring.
When an element is physically dragged, the turbulence displacement scale spikes proportionally to movement speed, then eases back — the edge looks like liquid sloshing.
Background requirement
The glass effect is transparent by design. It looks best placed over colourful or photographic backgrounds where backdrop-filter has something to refract. On a plain white or black background the effect will be subtle.
<div style={{
minHeight: "100vh",
background: "linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%)",
}}>
<LiquidGlass style={{ padding: "48px" }}>
<h1>Content</h1>
</LiquidGlass>
</div>Legacy export
Glass is the original component from v1 and is kept for backwards compatibility. Prefer LiquidGlass for new code.
import { Glass } from "liquid-flow";