Glass & elevation
Floating surface treatments for UI that needs to feel separate from the page beneath it. Three families: glass, solid overlay, and standalone shadow. Pick by intent; not all elevated UI wants the same look.
npx shadcn@latest add @ai2/glass| Token | Bg | Shadow | When |
|---|---|---|---|
| glass.solid | solid | shadow-md | Dense menus / popovers, maximum legibility |
| glass.overlay | translucent + blur | inset highlight | Tooltips, dropdowns, light command bars |
| glass.frosted | heavier + blur | deep layered | Modals, emphasized overlays |
| shadow.default | none (solid bg) | inset + light depth | Cards on a page |
| shadow.max | none (solid bg) | deep layered | Prompt inputs, sticky action bars |
Glass
Semi-transparent surfaces with a backdrop blur. The blur is doing real work - it neutralizes the content beneath while keeping a sense of layering. Reach for glass when an overlay sits over varied content and what is beneath should stay a hint, not a distraction.
glass.overlay
The default glass treatment. Light translucency (60%) plus a subtle inset highlight for depth. Use on tooltips, dropdowns and light command bars.
Glass overlay
Translucent + light depth
import { glass } from "@/components/ui/glass"
import { cn } from "@/lib/utils"
<div className={cn(glass.overlay, "rounded-lg px-6 py-4")}>
<p className="font-medium">Glass overlay</p>
<p className="text-sm text-muted-foreground">Translucent + light depth</p>
</div>glass.frosted
Heavier translucency (70% light / 80% dark) plus a deeper layered shadow. For emphasized overlays that need to feel more present: dialogs, notification surfaces, modal-like panels.
Glass frosted
Heavier opacity + deep layered shadow
import { glass } from "@/components/ui/glass"
import { cn } from "@/lib/utils"
<div className={cn(glass.frosted, "rounded-2xl px-6 py-4")}>
<p className="font-medium">Glass frosted</p>
<p className="text-sm text-muted-foreground">Heavier opacity + deep layered shadow</p>
</div>Depth scale
The recipes above are picked by intent (what is this surface for?). glassDepth is picked by depth(how far does it float?). Both carry the same signature, so a decorative styled component and a base overlay read as one language. This is what the free styled layer's glass themes derive from; glassDepth.md is the same 8px as glass.overlay, so the two axes meet at the default.
glassDepth.sm
4px blur
glassDepth.md
8px blur
glassDepth.lg
16px blur
glassDepth.xl
24px blur
| Step | Blur | Surface | When |
|---|---|---|---|
| glassDepth.sm | 4px | background/50 | Chips, inline badges, dense chrome |
| glassDepth.md | 8px | background/60 | The default. Dropdowns, popovers, tooltips |
| glassDepth.lg | 16px | background/70 | Panels and sheets; content beneath becomes texture |
| glassDepth.xl | 24px | background/80 | Full-bleed overlays over busy imagery |
import { glassDepth } from "@/components/ui/glass"
import { cn } from "@/lib/utils"
// The step supplies the surface; you supply the character.
<div className={cn(glassDepth.lg, "rounded-xl border border-border px-6 py-4")}>
Panel
</div>
// A tint replaces the step's background and keeps its blur + signature.
<div
className={cn(
glassDepth.md,
"bg-[color-mix(in_oklab,var(--color-info)_12%,transparent)] rounded-xl px-6 py-4"
)}
>
Tinted panel
</div>Two things will silently undo the glass. A step's signature is a box-shadow, so adding shadow-lg, your own box-shadow, or a ring-* (Tailwind composes rings through box-shadow too) replaces it and leaves a generic blur. Express extra depth inside one combined box-shadow that keeps the inset parts, or reach for a border. And do not stack glass on glass: give the container the surface and let rows and active items be colour-only layers, or it turns to mud.
Solid overlay
The simplest floating surface: an opaque background and a shadow, no blur. Use when glass would impair legibility (dense menus, long lists), the content beneath is neutral, or you need maximum performance (no backdrop-filter).
Solid overlay
Opaque surface, no glass effect
<div className={cn(glass.solid, "rounded-lg px-6 py-4")}>
<p className="font-medium">Solid overlay</p>
<p className="text-sm text-muted-foreground">Opaque surface, no glass effect</p>
</div>Shadow
Elevation without translucency. Use when a surface should feel lifted but keep its solid background: cards, sticky bars, prompt inputs.
shadow.default
Subtle inset highlight plus light layered depth. The right shadow for content cards.
Default shadow
Inset highlight + layered depth. The default for elevated surfaces.
import { shadow } from "@/components/ui/glass"
import { cn } from "@/lib/utils"
<div className={cn(shadow.default, "w-72 rounded-2xl p-6")}>
<p className="font-medium">Default shadow</p>
<p className="mt-1 text-sm text-muted-foreground">Inset highlight + layered depth.</p>
</div>shadow.max
Deeper layered shadow with stronger inset highlights. Reserve it for the primary prompt input or sticky action bar - its weight loses meaning if applied to multiple surfaces on the same page.
Ask anything…
<div className={cn(shadow.max, "w-80 rounded-2xl p-4")}>
<p className="text-sm text-muted-foreground">Ask anything…</p>
</div>Guidelines
- Use
glass.*when floating UI sits over varied content - the blur reduces visual noise without hiding what is beneath. - Use
shadow.defaulton cards. The inset highlight and light depth give weight without dominating the page. - Use
shadow.maxonly on the one primary prompt input or sticky bar - its depth loses meaning if repeated. - Pair
glass.solidwith a visible shadow when you opt out of glass - a solid floating surface still needs elevation. - Do not stack glass on glass. Translucency over translucency turns to mud; use
shadow.default+glass.solidfor the lower layer.