Primitives
Copy for LLM
Icon
Wraps a stroke-only line-icon SVG and applies the two-tier luminance rule: inert = near-white, active = the accent with a faint glow, or an iOS-style gradient plate via `plate`. Token sizes, no inline style.
Installation
npx @glasskit-ui/cli add iconInstall the SDK (it provides GlassViewport, useDpad and the stylesheet), then copy these files into your project:
npm install @glasskit-ui/react// components/lib/utils.tsimport { clsx, type ClassValue } from "clsx";import { twMerge } from "tailwind-merge";export type { ClassValue };/** * Merge class names the shadcn way: clsx joins conditionals, tailwind-merge * de-dupes conflicting Tailwind utilities so a consumer's `className` override * wins (e.g. passing `px-2` beats the component's `px-6`). Lens components are * Tailwind utilities + `--gk-*` tokens, so this de-dupe matters. */export function cn(...inputs: ClassValue[]): string { return twMerge(clsx(inputs));}/** * Accessible name from a free-form `label` prop: the label itself when it's a * plain string, otherwise undefined (a ReactNode can't become an aria-label). */export function stringLabel(label: unknown): string | undefined { return typeof label === "string" ? label : undefined;}// components/glasskit/icon.tsximport type { ReactNode } from "react";import { cn } from "../lib/utils";/** Tasteful gradient tones for icon plates (see styles.css `.gk-grad-*`). */export type IconTone = "blue" | "green" | "peach" | "violet" | "cyan" | "amber";/** * <Icon> — wraps any icon provider's SVG (Lucide, Tabler, or your own) and * applies the lens icon styling. Two modes: * - default: a 2-tier luminance glyph (inert near-white, `active` = accent). * - `plate`: an iOS/Meta-style gradient app-icon squircle holding a white glyph * (pass `tone` for the gradient). * * Decorative by default; pass `label` to expose it to assistive tech. */export function Icon({ children, active = false, size = "md", plate = false, tone = "blue", label, className,}: { /** A stroke-based SVG element. */ children: ReactNode; active?: boolean; /** sm 16 · md 20 · lg 28 (px @ 600×600). */ size?: "sm" | "md" | "lg"; /** Render as a gradient app-icon plate. */ plate?: boolean; /** Plate gradient tone. */ tone?: IconTone; label?: string; className?: string;}) { const a11y = { role: label ? ("img" as const) : undefined, "aria-label": label, "aria-hidden": label ? undefined : true, }; // Plate (squircle) and inner-glyph sizes, in px @ 600×600. const plateSize = { sm: "size-[46px]", md: "size-[66px]", lg: "size-[132px]" }; const plateGlyph = { sm: "size-6", md: "size-[34px]", lg: "size-16" }; const glyphSize = { sm: "size-4", md: "size-5", lg: "size-7" }; if (plate) { return ( <span className={cn( "gk-plate", `gk-grad-${tone}`, plateSize[size], className, )} {...a11y} > <span className={cn("gk-icon", plateGlyph[size])}>{children}</span> </span> ); } return ( <span className={cn( "gk-icon", glyphSize[size], active && "gk-icon--active", className, )} {...a11y} > {children} </span> );}Usage
<Icon active size="lg" label="Heart rate"> <HeartIcon /></Icon>Props
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | A stroke-based SVG. |
active | boolean | false | Accent + glow tier. |
size | "sm" | "md" | "lg" | "md" | 16 / 20 / 28px. |
plate | boolean | false | Render as a gradient app-icon plate. |
tone | "blue" | "green" | "peach" | "violet" | "cyan" | "amber" | "blue" | Plate gradient tone (plate mode only). |
label | string | — | a11y label; omit for decorative. |
Badge
A small count or status pill. Pure display: a subtle surface by default, the accent gradient for the one thing that should draw the eye, or a quiet hairline outline.
Button
A D-pad-focusable action. Renders a real <button> with the focusable class, so useDpad walks it and activates it on Enter/Space. Primary wears the accent fill; positive and danger carry the semantic accept and destroy fills; ghost is chrome-less.