GlassKit UI
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.

Showing the map view

600 × 600 · live

Installation

npx @glasskit-ui/cli add segmented

Install 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