Glass components for React and React Native.
Add them with the shadcn CLI and own the source.
Docs · Components · Guides · React Native · Templates
Glassy UI needs React 19 and Tailwind CSS 4. If your app has no
components.json, set up shadcn first:
npx shadcn@4.14.1 initAdd a component by its registry URL:
npx shadcn@4.14.1 add https://glassyui.com/r/glass-button.jsonThe CLI copies the component, the shared files it imports and its package dependencies into your app. There is no Glassy UI runtime package.
import { GlassButton } from '@/components/glassyui/glass-button';
export function SaveButton() {
return <GlassButton variant="prominent">Save changes</GlassButton>;
}Set data-lg-theme="light" or data-lg-theme="dark" on the root element and
keep it in sync with your theme switch. Every
component page also has pnpm, Yarn and bun
commands, and a manual install that lists every file.
Install by name instead of URL
Map the namespace in components.json:
{
"registries": {
"@glassyui": "https://glassyui.com/r/{name}.json"
}
}Then add items by name: npx shadcn@4.14.1 add @glassyui/glass-button.
| Group | Components |
|---|---|
| Core | Provider |
| Surfaces | Surface · Panel · Avatar · Kbd · Scroll Area |
| Controls | Button · Input · Checkbox · Radio Group · Textarea · Select · Switch · Slider · Segmented Control |
| Overlays | Dialog · Popover · Sheet · Menu · Command |
| Navigation | Header · Tabs · Accordion · Dock · Breadcrumb · Pagination |
| Feedback | Tooltip · Toast · Badge · Progress · Spinner · Skeleton · Alert |
| Effects | Lens · Scene · Logo Reveal |
| Mockups | Laptop · Phone Duo |
Each component is one registry item, named after its page:
https://glassyui.com/r/glass-segmented-control.json.
glassy-theme restyles stock shadcn/ui components as glass, with CSS only:
npx shadcn@4.14.1 add https://glassyui.com/r/glassy-theme.jsonTo replace them with Glassy UI's own components behind the same exports, props
and data attributes, install the drop-in set for your style instead:
glassy-ui-new-york (Radix) or glassy-ui-base-nova (Base UI), with
--overwrite. The theme guide
covers both.
The @glassyui-native registry has the components for Expo apps, with the web
names and React Native props.
npx shadcn@4.14.1 add https://glassyui.com/r/native/glass-button.json && npx expo install --fix| Where | How the glass is drawn |
|---|---|
| iOS 26 and later | The system's own glass, through expo-glass-effect |
| Earlier iOS, Android and the web | A blur of what lies behind, through expo-blur |
| Reduce Transparency on | An opaque fill |
- Shared components need Expo SDK 55 or later. Picker, Swipe Row and Card Stack, which are React Native only, need SDK 57.
- Android blurs only what sits inside a
GlassBackdrop. Put the content behind your glass in itsbackdrop. - Scene, Lens, Header, Tooltip, Kbd, Breadcrumb, Pagination, Command, Laptop and Phone Duo are web only.
shadcn initdoes not set up Expo apps. Use the Expo guide'scomponents.json, withcssVariablesenabled, and keep an@/*path mapping (./*, or./src/*for asrcapp). The guide also covers the optional@glassyui-nativeshorthand.- To install by hand, run
npx expo installfor the listed packages and copy every file in the item. Rebuild your development build after adding native packages.
The source lives in registry/glassyui-native, and
fixtures/expo-consumer renders every component.
Every surface is CSS glass: a backdrop blur and saturation, with a lit rim and a sheen along the top. Where the browser allows it, a lens bends the page at the rim.
| Chromium | Safari | Firefox | |
|---|---|---|---|
| Frost, rim light and sheen | ✓ | ✓ | ✓ |
| Lens: the rim bends the page and splits its colours | ✓ | Frost | Frost |
Refraction of a supplied refractionBackground |
✓ | ✓ | ✓ |
GlassScene: WebGL2 glass over a supplied backdrop |
✓ | ✓ | ✓ |
- The lens is on by default for the
controlandshowcasepresets and for dialogs, popovers, sheets and menus. Low quality, Reduce Transparency and surfaces over 720,000 px² keep the frost. GlassScenerefracts the backdrop image you give it, not the page behind it. Serve the image from the same origin or with CORS. Without WebGL2, every piece keeps its CSS glass.
- Reduce Transparency, Increase Contrast, forced colours and Reduce Motion are
!importantguards: noclassNamebrings transparency back. Restyle those states through--lg-opaque-surface,--lg-control-surfaceand--lg-control-surface-hover. - The prominent button tints what lies behind it and caps its brightness, so its white label keeps 4.5:1 contrast over any backdrop.
GlassSceneturns its canvas off under Reduce Transparency, Increase Contrast and forced colours. Reduce Motion stops its flow.
Style components with className. Library defaults sit in the components
cascade layer, below Tailwind's utilities, so rounded-xl or bg-sky-500/20
wins without ! or tailwind-merge. Each part also carries an lg-* class,
and --lg-* tokens tune the material:
<GlassButton className="[--lg-button-fill:rgb(14_165_233/0.4)]">
Tinted
</GlassButton>Components render without a provider, because the installed provider module
imports the shared CSS. Mount GlassProvider when the app needs synchronized,
persisted theme, quality, motion or transparency preferences, and match its
defaultTheme to the app's initial theme.
Customizing lists every class and
token.
- llms.txt indexes the documentation, and llms-full.txt holds it in one file.
- The registries are plain JSON:
/r/registry.jsonlists every web item, and/r/native/registry.jsonevery React Native item.
This repository holds the free library, its documentation site and the public Pro teaser. Glassy UI Pro's templates and application live in a separate private repository.
Use Node 22 and the pnpm version pinned in package.json:
pnpm install --frozen-lockfile
pnpm devThe docs serve on loopback only, at http://127.0.0.1:3000.
CONTRIBUTING.md lists the checks each kind of change needs,
and docs/ covers the
library boundary,
components,
registry installation,
registry components and
release verification.
Test unpublished registry changes
The editable catalogue is registry.json, its source files
live in registry/glassyui, and generated install payloads
live in public/r.
Keep this repository running and temporarily map the namespace to its loopback server:
{
"registries": {
"@glassyui": "http://127.0.0.1:3000/r/{name}.json"
}
}Then add an item through that namespace:
pnpm dlx shadcn@4.14.1 add @glassyui/glass-buttonCopy the source without the CLI
The registry is the recommended path, because it resolves every required file. To copy source directly, start with a React 19+ and Tailwind CSS 4 app.
-
Install only the package dependencies the components you copy need. The complete set uses:
pnpm add clsx cmdk \ @radix-ui/react-accordion \ @radix-ui/react-avatar \ @radix-ui/react-checkbox \ @radix-ui/react-dialog \ @radix-ui/react-dropdown-menu \ @radix-ui/react-popover \ @radix-ui/react-radio-group \ @radix-ui/react-scroll-area \ @radix-ui/react-select \ @radix-ui/react-slider \ @radix-ui/react-slot \ @radix-ui/react-switch \ @radix-ui/react-tabs \ @radix-ui/react-toast \ @radix-ui/react-tooltip
-
Import a copy of
src/styles/liquid.cssonce as a global stylesheet. It declares its own cascade layers, so do not wrap it in another@layer. -
Copy the component files you need from
src/components/liquid, then recursively copy every local relative-import dependency those files use, including the provider, preference and internal helper modules. -
Mount
GlassProvideronly when the app needs synchronized or persisted preferences. Setdata-lg-themeon the root element as above. -
Mount
src/components/liquid/liquid-filters.tsxonly for legacy CSS that referencesurl(#lg-liquid-refraction). Refraction of a supplied background creates its own filter for each surface.
Repository layout
| Path | Contents |
|---|---|
src/app |
Next.js App Router pages for the docs and playground |
src/components/liquid |
The library's components |
src/components/site, src/components/docs |
The site and docs shell, built from the library |
src/components |
Development-only diagnostics: gallery, preference controls, debug and performance overlays |
src/lib/liquid |
Preference persistence helpers |
src/styles/liquid.css |
Tokens, noise layer, specular and rim utilities |
registry.json, registry/glassyui |
The web registry's catalogue and source |
registry-native.json, registry/glassyui-native |
The React Native components and their catalogue |
public/r |
Generated install payloads |
fixtures/expo-consumer |
An Expo app that renders every React Native component |
Scripts
Development and formatting
pnpm dev– start the docs site on127.0.0.1pnpm build– production buildpnpm start– serve the built site on0.0.0.0pnpm lint– Oxlint anti-slop rules and ESLint with Next.js core web vitals rulespnpm format:check <changed-files>– check touched files with the pinned repository formatter
Registry and consumer installs
pnpm check:registry– verify registry metadata, source files, targets, dependencies, and blocked importspnpm registry:build– regenerate the static item payloads inpublic/rpnpm registry:check-generated– compare generated registry output withpublic/rpnpm smoke:registry-routes– check/r/registry.jsonand/r/glass-button.jsonagainst a running local serverpnpm check:native-registry– verify the Expo catalogue's import closures, declared packages andpublic/r/nativepayloadspnpm smoke:expo-consumer http://127.0.0.1:3100– install every Expo item into a clean copy of the Expo fixture, then type-check and bundle it for iOS, Android and the webpnpm smoke:registry-install http://127.0.0.1:3100– install a transitive item into a clean temporary consumer from a running local production server
Browser and release checks
pnpm smoke:docs-routes– check the landing, component index, and component docs routes against a running local serverpnpm smoke:release-ui http://127.0.0.1:3100– exercise every public demo across the release viewport and preference matrixnode scripts/smoke-header.mjs http://127.0.0.1:3100 .artifacts/header– verify the header across sizes, themes and browsers, with screenshotspnpm smoke:launch http://127.0.0.1:3100 .artifacts/prelaunch/launch– verify demo copying, guides, share cards and the retired template redirects in Chromenode scripts/capture-launch-previews.mjs http://127.0.0.1:3000– refresh the three launch screenshotsnode scripts/build-readme-art.mjs http://127.0.0.1:3000– redraw this README's lockup, desk and phones in.github/readme, light and darknode scripts/capture-share-cards.mjs http://127.0.0.1:3000 [card ...]– photograph every page's link-preview card intopublic/share; the home and React Native loops are rendered bylink-previews/(public/share/README.md)pnpm check:refraction-visuals http://127.0.0.1:3100– capture deterministic active/plain refraction evidence, enforce edge-focused distortion in Chromium, Firefox and WebKit, read every frame of a Chromium scroll to prove the GlassSurface docs' fixed-wallpaper example never trails its wallpaper, and prove the home page's WebGL pane bends the wallpaper pinned behind it in all three enginespnpm check:glass-material http://127.0.0.1:3100– prove every frosted component blurs a striped backdrop in Chromium, the lens activates, WebKit and Firefox keep the CSS frost, floating text keeps 4.5:1 contrast, and Reduce Transparency beats a consumer tintpnpm check:glass-scene http://127.0.0.1:3100– prove in Chromium, WebKit and Firefox thatGlassScenedraws glass that lines up with the DOM, bends the backdrop at the rim, merges nearby glass, ignores where the pointer is and steps aside for accessibility settings and a missing or lost WebGL2 context, and that the controls' liquid motion stretches and settles
Read CONTRIBUTING.md, and open an issue for a bug or a request.
MIT. Copied upstream code and package dependencies keep their notices in THIRD_PARTY_NOTICES.md.