
Installs all 34 components. Without our CLI, run instead.
liquefy-ui publishes a shadcn registry at liquefy-ui.com, with 34 components installable through the shadcn CLI.
Copy a prompt for your agent, copy the install command, or open the docs that ship it.
A content card with eyebrow, title, description, body and footer slots on the liquid surface.
A macOS-style dock: a glass rail of icon buttons that magnify under the pointer.
Stacked disclosure panels with real headings and a height-measured open animation.
An inline status message in four severities, with an optional dismiss button.
A circular avatar with image, initials and status dot, plus an overlapping group.
A small count or status pill for hanging off icons and labels.
A trail of links with glyph separators and a current-page marker.
The primary action control: WebGL rim light, jelly press spring and a loading state.
A checkbox with a springy tick, indeterminate state and label support.
A compact tag that can be selected, tinted and dismissed.
A modal on Base UI: trapped focus, inert background and wired-up title and description.
A hairline rule, horizontal or vertical, with optional inline content.
A side panel that slides from the left, right or bottom edge, on Base UI Dialog.
A square icon-only button that takes its accessible name from a label prop.
A glass list with items, descriptions, leading icons, trailing slots and subheaders.
A dropdown action menu on Base UI: arrow keys, typeahead and collision-aware placement.
A page strip with ellipsis truncation and previous/next controls.
A determinate progress bar and an indeterminate spinner sharing one accent.
A radio group with a springy dot and keyboard-driven selection.
A star rating that reads and writes a numeric value.
A segmented control whose glass indicator slides between options.
A listbox dropdown on Base UI: typeahead, focus return and a glass popover.
A shimmering placeholder block for content that has not arrived.
A range input with a luminous track and a dimensional thumb.
The base material every glass component is built on: rim light, refraction and springs.
A toggle whose thumb squashes as it travels.
A composable data table on a glass container, with row hover and selection.
Composable tabs on Base UI, with a glowing underline that springs between them.
A multi-line text input that keeps the field styling of LiquidTextField.
A single-line text input with label, hint and invalid state.
A toast provider and a useLiquidToast hook for transient messages.
A glass bubble on hover and focus, positioned by Base UI so it stays on screen.
A TypeScript UI library that delivers highly transparent Liquid Glass through WebGL optics, physical springs, and accessible React primitives.
This is an independent open-source project and is not affiliated with Apple Inc. It references public design principles while providing an original implementation for the web.
The capture above comes from the live playground: that is a displacement map
applied to the real backdrop through backdrop-filter, while the shape stretches
and overshoots from springs reading pointer velocity. Both are on by default.
Scroll it yourself at liquefy-ui.com, which also hosts the
component reference and the shadcn registry.
| Package | Purpose |
|---|---|
@liquefy-ui/react | React components, themes, and provider |
@liquefy-ui/core | Dependency-free WebGL, springs, and motion |
@liquefy-ui/icons | Tree-shakeable React SVG icons |
@liquefy-ui/mcp | MCP server that answers component questions from the real API |
pnpm add @liquefy-ui/react @liquefy-ui/core @liquefy-ui/icons
import { LiquefyProvider, LiquidButton } from '@liquefy-ui/react'
import { SparklesIcon } from '@liquefy-ui/icons'
import '@liquefy-ui/react/styles.css'
export function App() {
return (
}>
Create magic
)
}
Every component needs state, refs or the WebGL lens, so the whole package sits on
the client side of an RSC boundary. The published bundles carry a 'use client'
directive, so importing them straight into a server component works — no wrapper
file needed. Only event handlers have to move: a function cannot cross from a
server component into a client one, so anything with onClick or local state
belongs in its own 'use client' component.
apps/next-example is a working Next.js 16 App Router app whose page is a server
component, and its build runs in CI. If the client boundary ever regresses, that
build fails rather than yours.
Import tailwind.css instead of styles.css, before Tailwind itself:
@import '@liquefy-ui/react/tailwind.css';
@import 'tailwindcss';
That declares the cascade layer order — so className="rounded-full" on a
LiquidButton actually wins — and bridges the --lq-* tokens into Tailwind's
theme as bg-liquid-accent, text-liquid-muted, rounded-liquid,
shadow-liquid, ease-liquid and friends. The bridge uses @theme inline, which
is what keeps those utilities resolving per-theme at use time.
| What | Where |
|---|---|
| MCP server | claude mcp add liquefy-ui -- npx -y @liquefy-ui/mcp — eight tools answering from the real exports, no network, no dependencies |
llms.txt | /llms.txt and /llms-full.txt, generated from source |
| One page per component | /llms/liquid-button.md, plus icons.md, core.md and mcp.md — plain Markdown, because the docs site is a hash-routed SPA that a fetcher without JavaScript cannot read |
| shadcn registry | npx shadcn@latest add @liquefy-ui/liquid-button — the namespace is in shadcn's registry directory, so it needs no components.json entry |
The MCP tools are get_conventions, list_components, get_component,
search_components, get_component_source, get_tokens, list_icons and
get_core_api. The catalog behind them is generated from source at build time, and
lists only names the package entry point re-exports — so an agent is never told to
import something that does not resolve.
The registry copies real component source into your project rather than a
re-export, with imports rewritten to @/components/ui, @/lib and @/hooks. The
copied tree keeps @liquefy-ui/core and @base-ui/react from npm but not
@liquefy-ui/react, so a copied LiquefyProvider never ends up competing with the
packaged one. Every copied file is written with its own 'use client' directive, so an
RSC app needs no follow-up edit.
Everything is on liquefy-ui.com:
| Route | Contents |
|---|---|
#/ | The playground first, then framework and agent-tooling compatibility, then component samples |
#/playground | Every LiquefyProvider prop as a live control, applied to the whole site |
#/components | Index of every component, each with live demos and a full prop table |
#/docs | Introduction, installation, provider, theming, the styles prop, motion |
#/docs/frameworks · #/docs/tailwind · #/docs/ai-tooling | Integration |
#/docs/accessibility · #/docs/performance · #/docs/troubleshooting | Practices |
Old #/guides/* links redirect to their #/docs/* equivalents.
styles propEvery component takes a styles prop for one-off overrides, so reaching for a
stylesheet is optional. It is a superset of style:
Create magic
| Feature | Notes |
|---|---|
| CSS properties | Every camelCase property, plus --custom-properties. Numbers become px, matching style. |
| Spacing shorthands | p, px, py, pt/pr/pb/pl, and the m equivalents. Numbers count --lq-space units (4px by default, set spacing on the provider). gap and friends use the same scale. |
| Other shorthands | w, h, size, minW/maxW/minH/maxH, bg, radius. radius drives --lq-radius, so the press-squish keeps animating the corners. |
| Tokens | $name anywhere in a string resolves to var(--lq-name). Colour properties also accept the bare words accent, tint, foreground, muted, placeholder, text, line. |
| Responsive | { base, sm, md, lg, xl }, ordered ascending no matter how you write it. Override the widths with breakpoints on LiquefyProvider. |
| States | _hover, _focus, _focusVisible, _active, _disabled, _checked, _selected, _expanded, _open, _invalid, _readOnly, _placeholder, _first, _last, _odd, _even, and _dark / _light (which cover both the explicit theme and theme="system"). |
Static values ride the style attribute, so the common case adds no stylesheet
and no hydration concerns. As soon as a state or breakpoint appears, the whole
object moves into a generated class instead — otherwise the inline declarations
would outrank the very rules meant to override them. That class is inserted
unlayered, and the component stylesheet lives in @layer liquefy-ui, so
overrides win on cascade order rather than on !important or specificity.
Precedence is styles over the component's own custom properties, and style
over everything — style stays the last-resort escape hatch.
transform and backdrop-filter are written inline by the jelly springs every
frame and cannot be overridden through styles; development builds warn if you
try. Wrap the component and style the wrapper instead.
Building your own component on the same system:
import { useLiquidStyles, type LiquidStyleProps } from '@liquefy-ui/react'
export const Panel = ({ className, style, styles, ...props }: LiquidStyleProps & JSX.IntrinsicElements['div']) => {
const root = useLiquidStyles('my-panel', { className, style, styles })
return
}
Server rendering: useInsertionEffect does not run on the server, so flush the
collected rules into the document head yourself with getLiquefyStyleSheet().
Static-only styles need nothing — they are already inline.
LiquefyProvider takes className and style but not styles — it owns the
config that styles reads. LiquidToastProvider takes none of the three: it
renders no root element of its own, only the toast viewport. slotStyles is reserved for per-part styling
({ header, body, footer }) and is not implemented yet.
The full version of this — every shorthand, token reference, breakpoint and state
key, plus custom components and server rendering — is at #/docs/styles-prop,
with the token system itself at #/docs/theming.
35 components and 50 icons, each with live demos and a full prop table at liquefy-ui.com/#/components.
| Category | Components |
|---|---|
| Inputs | LiquidButton, LiquidIconButton, LiquidCheckbox, LiquidRadioGroup / LiquidRadio, LiquidSwitch, LiquidSlider, LiquidTextField, LiquidTextArea, LiquidSelect, LiquidDatePicker, LiquidSegmented, LiquidRating |
| Data display | LiquidAvatar / LiquidAvatarGroup, LiquidBadge, LiquidChip, LiquidTooltip, LiquidTable family, LiquidList family, LiquidDivider |
| Feedback | LiquidAlert, LiquidProgress, LiquidSpinner, LiquidSkeleton, LiquidToastProvider / useLiquidToast, LiquidDialog |
| Surfaces | LiquidSurface, LiquidGlass, GlassCard, LiquidAccordion / LiquidAccordionItem |
| Navigation | LiquidTabs family, LiquidBreadcrumbs, LiquidPagination, LiquidMenu, LiquidDrawer, GlassDock / DockItem |
| Foundation | LiquefyProvider, useLiquefyConfig, useLiquidGlass, useLiquidStyles, getLiquefyStyleSheet, defaultBreakpoints |
When WebGL is unavailable, components automatically fall back to the transparent CSS material. Lens, WebGL, motion, transparency, glow and shimmer are on by default; ripple and sparkle are off. Use the provider props to tune them across a subtree.
Use theme="dark", theme="light", or theme="system" on LiquefyProvider to control appearance.
feDisplacementMap inside backdrop-filter. Its fold-safe curve keeps the sampled backdrop one-to-one even at control sizes. Chromium renders it fully; WebKit and Gecko gracefully fall back to the blurred CSS material.u_wobble and wiggles the rim in sync.@base-ui/react, which supplies focus trapping and restoration, scroll locking, Escape handling, roving tabindex, typeahead, and collision-aware positioning. liquefy-ui keeps the optics and the springs and stops re-implementing the parts that are easy to get subtly wrong. The keyboard behaviour is asserted in packages/react/test/keyboard.test.tsx rather than assumed.motion={false} / transparency={false} on LiquefyProvider; apps that want to honor the OS can pass e.g. motion={!matchMedia('(prefers-reduced-motion: reduce)').matches} or use the core-level respectReducedMotion / respectReducedTransparency options.Issues and pull requests are welcome. rc is the development branch — branch from
it and open the pull request back into it. CONTRIBUTING.md has
the local setup, the test suites, the CI jobs and the commit convention.
GitHub Sponsors funds the maintenance of this
library — the shader work, the browser matrix, and the release plumbing that keeps
pnpm add @liquefy-ui/react boring. Sponsorship goes to the maintainer rather than
to an organisation; there is one of us.
GitHub takes no cut, so the whole amount arrives. One-off is as welcome as monthly.
MIT
The packages and primitives its components pull in, counted across the registry.
Every appearance and removal our crawl has seen in the registry index.