Adds the shared primitives the planner topbar redesign needs, on the design-system tokens: - IconButton — icon-only button (undo/redo), ghost/secondary variants, requires an accessible label. - SegmentedControl — generic single-select toggle (color mode Plain/Elevation/Surface), radiogroup semantics. - Avatar — colored initial circle for participants, per-user color with an accent fallback. Co-located jsdom unit tests for each (roles, aria-checked, onChange, disabled, color fallback). Extends the dev-only /dev/ui gallery with sections for all three. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
50 lines
1.3 KiB
TypeScript
50 lines
1.3 KiB
TypeScript
import type { ButtonHTMLAttributes } from "react";
|
|
import { cn } from "./cn.ts";
|
|
|
|
export type IconButtonVariant = "ghost" | "secondary";
|
|
export type IconButtonSize = "sm" | "md";
|
|
|
|
export interface IconButtonProps
|
|
extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, "aria-label"> {
|
|
/** Required accessible name — the button has no visible text. */
|
|
label: string;
|
|
variant?: IconButtonVariant;
|
|
size?: IconButtonSize;
|
|
}
|
|
|
|
const base =
|
|
"inline-flex items-center justify-center rounded-md transition-colors " +
|
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent " +
|
|
"focus-visible:ring-offset-1 focus-visible:ring-offset-bg " +
|
|
"disabled:pointer-events-none disabled:opacity-30";
|
|
|
|
const variants: Record<IconButtonVariant, string> = {
|
|
ghost: "text-text-md hover:bg-bg-subtle hover:text-text-hi",
|
|
secondary:
|
|
"border border-border bg-bg-raised text-text-hi hover:bg-bg-subtle",
|
|
};
|
|
|
|
const sizes: Record<IconButtonSize, string> = {
|
|
sm: "h-7 w-7",
|
|
md: "h-9 w-9",
|
|
};
|
|
|
|
export function IconButton({
|
|
label,
|
|
variant = "ghost",
|
|
size = "md",
|
|
className,
|
|
type = "button",
|
|
title,
|
|
...props
|
|
}: IconButtonProps) {
|
|
return (
|
|
<button
|
|
type={type}
|
|
aria-label={label}
|
|
title={title ?? label}
|
|
className={cn(base, variants[variant], sizes[size], className)}
|
|
{...props}
|
|
/>
|
|
);
|
|
}
|