import * as React from 'react'; import { Alert, AlertTitle } from '@/components/alert'; import { FilterField, narrow } from '~/chrome/ui/axis-filter'; import { GalleryPage } from '~/chrome/ui/gallery-page'; import { PACKAGE } from '~/chrome/lib/package-name'; import { MatrixGrid } from '~/chrome/ui/matrix'; import { useMessages } from '../i18n'; import { ALERT_SIZES as SIZES, ALERT_VARIANTS as VARIANTS } from '../registry/alert'; import { PALETTES, type Palette } from '../registry/axis-values'; import { useParam } from '../router'; import { FigmaLayoutView } from './alerts-figma'; /** * Every Alert the kit can draw, on one page, in two shapes — the same split * `/buttons` uses. * * **Gallery** is the kit's own shape: a grid per variant, palettes across, * sizes down. Unlike Button, Alert has only three axes and none of them are * pinned or icon-only, so there is exactly one section here. * * **Figma layout** is CBAR's shape — one band per status, variant down, size * across — read off the Alert set's own canvas geometry. It lives in * `./alerts-figma`. * * Copying is one cell at a time on both tabs, same reasoning as Buttons: a * grid here is a whole sweep, and nobody pastes a sweep. */ type Variant = (typeof VARIANTS)[number]; type Size = (typeof SIZES)[number]; const EVERY_TOKEN: readonly string[] = [...VARIANTS, ...PALETTES, ...SIZES]; const TABS = ['gallery', 'figma'] as const; export function AlertsPage() { const m = useMessages(); return ( m.alerts.tabs[name]} views={{ gallery: , figma: }} /> ); } function GalleryView() { const m = useMessages(); const [query, setQuery] = useParam('q', ''); const [palette, setPalette] = useParam('palette', 'all'); const [size, setSize] = useParam('size', 'all'); const needle = query.trim().toLowerCase(); const nothingMatches = needle.length > 0 && !EVERY_TOKEN.some((token) => token.includes(needle)); const variants = React.useMemo(() => narrow(VARIANTS, needle), [needle]); const palettes = React.useMemo(() => { const chosen = palette === 'all' ? PALETTES : PALETTES.filter((p) => p === palette); return narrow(chosen, needle); }, [palette, needle]); const sizes = React.useMemo(() => { const chosen = size === 'all' ? SIZES : SIZES.filter((s) => s === size); return narrow(chosen, needle); }, [size, needle]); const cell = (variant: Variant, colorPalette: Palette, cellSize: Size) => ( {m.alerts.cellTitle} ); return (
{/* Native controls on purpose: a page documenting the kit must not document it with itself, or a broken component hides its own bug. */} setQuery(e.target.value)} placeholder={m.alerts.searchPlaceholder} className="h-9 min-w-52 flex-1 rounded-md border border-input bg-background px-2 text-sm" />
{nothingMatches ? (

{m.alerts.empty(query)}

) : ( variants.map((variant) => ( cell(variant, col as Palette, row as Size)} cellTitle={(row, col) => `variant=${variant}, size=${String(row)}, colorPalette=${String(col)}` } copyAll={false} /> )) )}
); }