GlassIcons
Icons made glass objects: each line drawn as a round glass tube, each fill extruded into a slab with a rounded lip — smoked glass under studio light, bobbing and rocking a little.
Example
Wrap any icons marked data-glass-icon — ChannelIcon marks itself. One WebGL canvas draws them all, laid over the flat icons, which stay underneath for layout and as the fallback. At size-8 and up the glass reads.
import { ChannelIcon } from "@/components/shared/channel-icon";
import { GlassIcons } from "@/components/shared/glass-icons";
<GlassIcons>
<ChannelIcon channel="instagram" className="size-8" />
…
</GlassIcons>Palette
Smoked glass by default — the DotMark's black glass. palette="color" casts the row in the brand instead: the studio's two colours by turns, the first first, the way the logo's lobes alternate. Each is cast from its deep token a step deeper, as the DotMark's glass reads, so a thin tube holds on white. palette="clear" casts fully see-through glass: colourless, read only by its edges and the light it catches, and refracting the first opaque surface under it.
import { ChannelIcon } from "@/components/shared/channel-icon";
import { GlassIcons } from "@/components/shared/glass-icons";
<GlassIcons palette="color">
<ChannelIcon channel="instagram" className="size-8" />
…
</GlassIcons>Tints
An icon can name its own colour with data-glass-tint: studio or studio-2, from the mix around it (a MixScope) — whatever the palette would give it. FeatureCard sets it from its tint. Each is cast from its deep token a step deeper and richer; butter only as rich as sRGB holds, so its gold never turns.
import { HugeiconsIcon } from "@hugeicons/react";
import { GlassIcons } from "@/components/shared/glass-icons";
<GlassIcons>
<HugeiconsIcon icon={StarIcon} data-glass-icon="" data-glass-tint="studio-2" className="size-16" />
…
</GlassIcons>Clear, tinted
In clear glass a data-glass-tint stays translucent: the glass takes the deep token as it is, and refracts the card it stands on — read from the page, so it needs an opaque surface under it. On the landing pillars, each object stands in its card's wash.
<GlassIcons palette="clear" motion="spin">
<div className="bg-wash-studio-glass squircle-3xl p-6">
<HugeiconsIcon icon={RepeatIcon} data-glass-icon="" data-glass-tint="studio-2" className="size-16" />
</div>
…
</GlassIcons>Motion
By default each slab rocks a little either way and bobs. motion="spin" turns them slowly round instead — a full turn every twelve seconds, each from its own angle — for big objects that earn a whole turn, like the landing pillars. Under prefers-reduced-motion a spinning slab stands still, facing front.
<GlassIcons palette="color" motion="spin">
<ChannelIcon channel="instagram" className="size-16" />
…
</GlassIcons>API reference
| Prop | Type | Default | Description |
|---|---|---|---|
| palette | "black" | "color" | "clear" | "black" | Smoked glass, the studio's two colours by turns along the row, or fully see-through glass that refracts the opaque surface under it. An icon's own data-glass-tint wins — translucent in clear glass. |
| motion | "rock" | "spin" | "rock" | A small rock and bob, or a slow full turn every twelve seconds. Still under reduced motion. |
| children | ReactNode | — | Any layout holding SVG icons marked data-glass-icon (and, optionally, data-glass-tint); each becomes glass over its own place — lines as tubes, fills as slabs. |
| className | string | — | Layout only; the box is positioned for the glass. |
Guidelines
- Line icons (Hugeicons) become tubes and keep every detail; a filled glyph becomes a slab, and its cut-outs can fill in.
- For a brand moment, not chrome: a row of channels, a hero mark. Never on buttons or inline with body text.
- Decorative: always beside a label. Still under
prefers-reduced-motion; flat where WebGL is missing.