From c299aea18cc82ec5df23ef2298843b26961b41b2 Mon Sep 17 00:00:00 2001 From: Thomas Joise Date: Fri, 17 Jul 2026 02:02:19 +0530 Subject: [PATCH] feat(ui): Skeleton, ErrorState, FilterChips, Tabs Co-Authored-By: Claude Opus 4.8 (1M context) --- packages/ui/src/chips.tsx | 27 +++++++++++++++++++++++++++ packages/ui/src/index.ts | 3 +++ packages/ui/src/states.tsx | 25 +++++++++++++++++++++++++ packages/ui/src/tabs.tsx | 27 +++++++++++++++++++++++++++ 4 files changed, 82 insertions(+) create mode 100644 packages/ui/src/chips.tsx create mode 100644 packages/ui/src/states.tsx create mode 100644 packages/ui/src/tabs.tsx diff --git a/packages/ui/src/chips.tsx b/packages/ui/src/chips.tsx new file mode 100644 index 0000000..88156fe --- /dev/null +++ b/packages/ui/src/chips.tsx @@ -0,0 +1,27 @@ +/** Saved-views-lite: a pill row that filters a list by one dimension. */ + +export interface ChipDef { key: string; label: string; count?: number } + +export function FilterChips(props: { + chips: ChipDef[] + active: string + onChange: (key: string) => void +}) { + return ( +
+ {props.chips.map((c) => ( + + ))} +
+ ) +} diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts index 53bec6d..1d8139e 100644 --- a/packages/ui/src/index.ts +++ b/packages/ui/src/index.ts @@ -2,3 +2,6 @@ export * from './avatar' export * from './components' export * from './theme' export * from './ThemeSwitcher' +export * from './states' +export * from './chips' +export * from './tabs' diff --git a/packages/ui/src/states.tsx b/packages/ui/src/states.tsx new file mode 100644 index 0000000..093ef24 --- /dev/null +++ b/packages/ui/src/states.tsx @@ -0,0 +1,25 @@ +/** Loading + error surfaces — every page swaps its "Loading…" text for these. */ + +const WIDTHS = ['92%', '70%', '84%', '55%', '78%'] + +export function Skeleton(props: { rows?: number }) { + const rows = props.rows ?? 3 + return ( +
+ {Array.from({ length: rows }, (_x, i) => ( +
+ ))} +
+ ) +} + +export function ErrorState(props: { message: string; onRetry?: () => void }) { + return ( +
+ {props.message} + {props.onRetry !== undefined && ( + + )} +
+ ) +} diff --git a/packages/ui/src/tabs.tsx b/packages/ui/src/tabs.tsx new file mode 100644 index 0000000..9576eb8 --- /dev/null +++ b/packages/ui/src/tabs.tsx @@ -0,0 +1,27 @@ +/** Underline tabs with optional mono counts (Direction A v2 pattern). */ + +export interface TabDef { key: string; label: string; count?: number } + +export function Tabs(props: { + tabs: TabDef[] + active: string + onChange: (key: string) => void +}) { + return ( +
+ {props.tabs.map((t) => ( + + ))} +
+ ) +}