Navigation
Glass Dock
A row of app icons on a glass shelf that name themselves on hover.
pnpm dlx shadcn@4.14.1 add @glassyui/glass-dockPreview
Open an app.
Demos ready. Update 0.
Installation
First add the exact @glassyui mapping to components.json as shown in Getting Started. Then run the pinned item command:
pnpm dlx shadcn@4.14.1 add @glassyui/glass-dockWhat this installs10 files, 2 packages
Direct registry declarations
These values belong to @glassyui/glass-dock itself in registry.json.
Package dependencies
@radix-ui/react-slotclsx
Registry dependencies
@glassyui/glass-surface
File targets
components/glassyui/glass-dock.tsx
Complete installed closure
This follows every namespaced registry dependency recursively and de-duplicates the packages and target files installed with this item.
Package dependencies
@radix-ui/react-slotclsx
Installed files
components/glassyui/glass-dock.tsxcomponents/glassyui/glass-surface.tsxcomponents/glassyui/lib/merge-refs.tscomponents/glassyui/lib/refraction-map.tscomponents/glassyui/lib/use-refraction-filter.tsxcomponents/glassyui/lib/scene-context.tscomponents/glassyui/glass-provider.tsxcomponents/glassyui/liquid-filters.tsxcomponents/glassyui/lib/preferences.tscomponents/glassyui/styles/liquid.css
Usage
Save this as dock-example.tsx. It is the complete example shown above, including its artwork.
'use client';
import { useState, type CSSProperties } from 'react';
import { GlassDock, GlassDockItem } from '@/components/glassyui/glass-dock';
const apps = [
{ label: 'Inbox', color: '#2f6fd8', path: 'M14 18h36v28H14z M14 19l18 14 18-14' },
{ label: 'Chat', color: '#146c3c', path: 'M14 16h36v26H30l-11 8v-8h-5z M23 26h18 M23 33h12' },
{
label: 'Gallery',
color: '#b36c13',
path: 'M15 15h34v34H15z M15 40l10-10 9 9 6-6 9 10 M38 23h.1',
},
{ label: 'Player', color: '#c9361a', path: 'M25 18v28l23-14z' },
{ label: 'Docs', color: '#756c66', path: 'M17 13h30v38H17z M24 23h16 M24 31h16 M24 39h11' },
];
const dockStyle: CSSProperties & { '--lg-dock-size': string; '--lg-dock-gap': string } = {
'--lg-dock-size': 'clamp(24px, 12cqi, 44px)',
'--lg-dock-gap': '6px',
};
type DockExampleProps = { onAction?: (message: string) => void };
export function DockExample({ onAction }: DockExampleProps) {
const [running, setRunning] = useState(['Chat']);
const [message, setMessage] = useState('Open an app.');
return (
<div
style={{
containerType: 'inline-size',
display: 'grid',
alignContent: 'center',
justifyItems: 'center',
gap: 26,
width: '100%',
minHeight: 220,
borderRadius: 22,
background:
'radial-gradient(ellipse at 20% 120%, #a53722, transparent 65%), linear-gradient(135deg, #211c1a, #5c291c)',
}}
>
<GlassDock aria-label="Dock" role="group" style={dockStyle}>
{apps.map((app) => (
<GlassDockItem
active={running.includes(app.label)}
key={app.label}
label={app.label}
onClick={() => {
setRunning((current) =>
current.includes(app.label) ? current : [...current, app.label],
);
const next = `${app.label} opened.`;
setMessage(next);
onAction?.(next);
}}
>
<svg aria-hidden="true" viewBox="0 0 64 64">
<rect fill={app.color} height="64" rx="14" width="64" />
<path
d={app.path}
fill="none"
stroke="#fff"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="3"
/>
</svg>
</GlassDockItem>
))}
</GlassDock>
<p
role={onAction ? undefined : 'status'}
style={{ margin: 0, color: '#fff8f2', fontSize: 13 }}
>
{message}
</p>
</div>
);
}
After configuring the registry, install every component this example uses:
pnpm dlx shadcn@4.14.1 add @glassyui/glass-dockExamples
import { DockExample } from "./dock-example";
export default function Page() {
return <DockExample />;
}API
GlassDockGlass shelf under a row of items.
GlassDockItemIcon button with a hover label and a running indicator.
labelRequired accessible name, also shown above the icon on hover.
activeShows the running dot under the icon.
asChildRenders the single child, such as a link, as the item.
GlassDockSeparatorVertical divider between item groups.
Notes
Input
Icons keep their size wherever the pointer is. Hover or keyboard focus shows the label, and focus also enlarges the icon.
Accessibility
Keep the Radix-backed semantics intact and preserve visible labels, focus states, and keyboard operation when copying the source.
Performance
Use provider quality preferences for dense app screens. Reserve strong refraction for hero or showcase surfaces.