Components
Segmented
Pick one of a few options (a watchOS-style segmented control). Each segment is a D-pad-focusable radio; the selected one lifts with the accent. Keep it to 2–4 options.
Installation
npx @glasskit-ui/cli add segmentedInstall the SDK (it provides GlassViewport, useDpad and the stylesheet), then copy these files into your project:
npm install @glasskit-ui/react// components/lib/utils.tsexport type ClassValue = string | number | null | undefined | false;/** * Join truthy class names. Dependency-free on purpose: the lens components * style via bespoke semantic classes (no conflicting Tailwind utilities to * de-dupe), so this needs no clsx/tailwind-merge and resolves from anywhere * the registry is vendored. */export function cn(...inputs: ClassValue[]): string { return inputs.filter(Boolean).join(" ");}/** * 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/segmented.tsximport type { ReactNode } from "react";import { cn } from "../lib/utils";export type SegmentedOption<T extends string | number> = { value: T; label: ReactNode;};/** * <Segmented> — pick one of a few options (a watchOS-style segmented control). * Each segment is a D-pad-focusable radio; the selected one lifts with the * accent. Controlled: pass `value` + `onChange`. Keep it to 2–4 options on * the lens. */export function Segmented<T extends string | number>({ options, value, onChange, label, className,}: { options: SegmentedOption<T>[]; value: T; onChange?: (next: T) => void; /** Accessible name for the group (e.g. "View mode"). */ label?: string; className?: string;}) { return ( <div role="radiogroup" aria-label={label} className={cn("gk-segmented", className)} > {options.map((o) => ( <button key={String(o.value)} type="button" role="radio" aria-checked={o.value === value} onClick={onChange ? () => onChange(o.value) : undefined} className={cn( "focusable gk-segmented__seg t-body", o.value === value && "gk-segmented__seg--on", )} > {o.label} </button> ))} </div> );}Usage
<Segmented value={mode} onChange={setMode} options={[ { value: "map", label: "Map" }, { value: "list", label: "List" }, ]}/>Props
Prop
Type
QuickReplyChips
Tappable canned replies (the comms job — there is no keyboard on the lens, text is voice). Each chip is D-pad-focusable. Keep the set short and glanceable.
Slider
A continuous level control (volume, brightness — the quick controls). A native range tinted with accent-color; arrow keys / Neural-Band pinch-twist adjust it. Controlled via value + onChange.