Glass Dock
A liquid-glass bottom-nav dock — a refracting glass bar with a selection pill you can tap or drag between items; the pill lifts into a glass lens with velocity gel as it travels, then settles at the nearest item.
Playground
Edit the props live and copy the config.
<GlassDock
items={items}
radius={20}
strength={0.28}
frost={0.3}
showLabels={true}
search
accent="#38bdf8"
/>Install
npx shadcn@latest add https://websiteglass.com/r/glass-dock.jsonUsage
import { GlassDock } from '@/components/ui/glass-dock';
import { House, LayoutGrid, BarChart3, Settings } from 'lucide-react';
const items = [
{ value: 'home', label: 'Home', icon: <House className="size-full" /> },
{ value: 'dash', label: 'Dashboard', icon: <LayoutGrid className="size-full" /> },
{ value: 'stats', label: 'Analytics', icon: <BarChart3 className="size-full" /> },
{ value: 'settings', label: 'Settings', icon: <Settings className="size-full" /> },
];
<GlassDock items={items} value={tab} onValueChange={setTab} />Props
GlassDock
| Prop | Type | Default | Description |
|---|---|---|---|
items | DockItem[] | required | The nav items. |
value | string | — | Controlled active item value. |
defaultValue | string | first item | Initial active value when uncontrolled. |
onValueChange | (v: string) => void | — | Fires when the selection changes. |
radius | number | 20 | Bar corner radius in px. Large values (e.g. 9999) make a fully-round pill bar. |
pillRadius | number | radius - 7 | Selection-pill / item corner radius in px. |
strength | number | 0.28 | Refraction strength of the bar (0–1). |
frost | number | 0.3 | Frostiness (0 = clear, 1 = fully frosted) — drives tint + blur. |
tint | number | from frost | Override tint alpha (0–1). |
blur | number | from frost | Override backdrop blur in px. |
accent | string | #38bdf8 | Accent colour for the active item. |
showLabels | boolean | true | Show text labels under each icon; false = compact icon-only. |
search | boolean | false | Add a detached search button; tapping it wipes a clear-refraction search field over the dock (the items fade out so nothing shows through), with a × to close. |
onSearchChange | (q: string) => void | — | Fires as the search query changes. |
searchPlaceholder | string | "Search" | Placeholder for the expanded search field. |
accessory | ReactNode | — | Extra detached buttons rendered after the bar (e.g. a GlassDockButton). |
Every visual knob is a prop — radius, pillRadius, strength, frost, tint, blur, and accent — so the whole look is driven from props, nothing hardcoded.
DockItem
| Field | Type | Description |
|---|---|---|
value | string | Unique value for the item. |
label | string | Text label under the icon. |
icon | ReactNode | The icon. |
Detached buttons
Besides the built-in expanding search, the registry also exports
GlassDockButton — a standalone detached glass button that matches the dock. It
is a plain action button (fires onClick), not an expand — icon-only, and a
perfect circle at a large radius. Use it on its own, or via the dock's
accessory slot where it auto-matches the bar height:
import { GlassDock, GlassDockButton } from '@/components/ui/glass-dock';
import { Plus } from 'lucide-react';
// via the accessory slot (matches the bar height automatically)
<GlassDock
items={items}
value={tab}
onValueChange={setTab}
accessory={<GlassDockButton icon={<Plus className="size-full" />} onClick={createTask} />}
/>
// or standalone, with an explicit size
<GlassDockButton icon={<Plus className="size-full" />} size={56} radius={9999} onClick={createTask} />GlassDockButton
| Prop | Type | Default | Description |
|---|---|---|---|
icon | ReactNode | required | The icon (icon-only, no text label). |
size | number | — | Fixed square size in px. Omit to stretch to a sibling dock's height. |
radius | number | 20 | Corner radius in px. Large values (e.g. 9999) make it a circle. |
strength | number | 0.28 | Refraction strength (0–1). |
frost | number | 0.3 | Frostiness — drives tint + blur. |
tint / blur | number | from frost | Override tint alpha / backdrop blur. |
All native <button> props are forwarded. Pass matching radius/frost to keep it visually in step with a customised dock.
Interaction
The bar is a real refracting glass surface (it bends the content behind it via the lens engine on Chromium; frosted fallback elsewhere). The active item wears a soft pill. Tap another item and the pill springs to it; grab and drag the pill and it lifts into a glass lens with velocity-driven gel, tracking the item beneath it, then settles into a pill at the nearest item on release.
Glass Dialog
Modal liquid glass dialog — blurred scrim, a frosted tinted panel that scales into place, with accessible title, description, close, and footer parts.
Glass Tile
A selectable glass grid cell — cheap CSS backdrop-blur by default so it scales to hundreds of items, with an optional real-refraction mode for small grids.