diff --git a/frontend/packages/swarm-ui/src/App.tsx b/frontend/packages/swarm-ui/src/App.tsx index 87b66170..b68f4429 100644 --- a/frontend/packages/swarm-ui/src/App.tsx +++ b/frontend/packages/swarm-ui/src/App.tsx @@ -6,6 +6,7 @@ import { useEffect, useState } from 'preact/hooks'; import { Route, Switch } from 'wouter-preact'; import { Shell } from './shell/Shell.js'; +import { ComponentsPage } from './pages/ComponentsPage.js'; import { Panel } from './ui/panel/Panel.js'; import { StatusChip } from './ui/status-chip/StatusChip.js'; import { Table, type TableColumn } from './ui/table/Table.js'; @@ -69,6 +70,7 @@ export function App() { + diff --git a/frontend/packages/swarm-ui/src/pages/ComponentsPage.css b/frontend/packages/swarm-ui/src/pages/ComponentsPage.css new file mode 100644 index 00000000..49d1e44c --- /dev/null +++ b/frontend/packages/swarm-ui/src/pages/ComponentsPage.css @@ -0,0 +1,44 @@ +/* layout — a plain vertical stack of sections, each a + labelled grid of samples. No new colour vars: reuses the same + base16 slots (../theme.css) every other component draws from, so + this page can't drift from the palette it's demonstrating. */ +.components-intro { + margin: 0 0 1.5em; + color: var(--muted); +} +.components-intro code { + color: var(--fg); +} +.components-section { + margin-bottom: 2em; +} +.components-section:last-child { + margin-bottom: 0; +} +.components-section-title { + margin: 0 0 0.75em; + font-size: 0.9em; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.04em; + color: var(--muted); +} +.components-section-body { + display: flex; + flex-direction: column; + gap: 1em; +} +.components-chip-row { + display: flex; + flex-wrap: wrap; + gap: 1em; +} +.components-sample { + display: flex; + flex-direction: column; + gap: 0.4em; +} +.components-sample-label { + font-size: 0.8em; + color: var(--muted); +} diff --git a/frontend/packages/swarm-ui/src/pages/ComponentsPage.tsx b/frontend/packages/swarm-ui/src/pages/ComponentsPage.tsx new file mode 100644 index 00000000..1159b62c --- /dev/null +++ b/frontend/packages/swarm-ui/src/pages/ComponentsPage.tsx @@ -0,0 +1,87 @@ +// — living style guide for every ui primitive this +// package ships. One section per component, each mode it supports +// rendered side by side with a caption naming the mode — so a visual +// regression or a missing variant is obvious at a glance, and a new +// primitive gets a section here the same day it's added. Sample data +// only, no network calls — this page must render the same whether +// swarm-controller's API is up or not. +import type { ComponentChildren } from 'preact'; +import { Panel } from '../ui/panel/Panel.js'; +import { StatusChip, type ChipTone } from '../ui/status-chip/StatusChip.js'; +import { Table, type TableColumn } from '../ui/table/Table.js'; +import './ComponentsPage.css'; + +function Section({ title, children }: { title: string; children: ComponentChildren }) { + return ( +
+

{title}

+
{children}
+
+ ); +} + +function Sample({ label, children }: { label: string; children: ComponentChildren }) { + return ( +
+
{label}
+
{children}
+
+ ); +} + +const CHIP_TONES: ChipTone[] = ['neutral', 'positive', 'warning', 'negative']; + +interface Row { + name: string; + detail: string; +} + +const TABLE_COLUMNS: TableColumn[] = [ + { key: 'name', header: 'name', render: (r) => r.name }, + { key: 'detail', header: 'detail', render: (r) => r.detail }, + { key: 'status', header: 'status', render: () => }, +]; + +const TABLE_ROWS: Row[] = [ + { name: 'alpha', detail: 'sample row one' }, + { name: 'beta', detail: 'sample row two' }, +]; + +export function ComponentsPage() { + return ( + +

+ Every primitive in src/ui/, shown in each mode it supports. Sample data + only — nothing here calls the API. +

+ +
+ + panel body content + + + panel body content, no title + +
+ +
+
+ {CHIP_TONES.map((tone) => ( + + + + ))} +
+
+ +
+ + r.name} /> + + +
r.name} /> + + + + ); +} diff --git a/frontend/packages/swarm-ui/src/shell/Shell.tsx b/frontend/packages/swarm-ui/src/shell/Shell.tsx index 9a25878e..efdee4be 100644 --- a/frontend/packages/swarm-ui/src/shell/Shell.tsx +++ b/frontend/packages/swarm-ui/src/shell/Shell.tsx @@ -16,7 +16,10 @@ import type { ComponentChildren } from 'preact'; import { Link, useRoute } from 'wouter-preact'; import './Shell.css'; -const NAV_ITEMS: { href: string; label: string }[] = [{ href: '/', label: 'overview' }]; +const NAV_ITEMS: { href: string; label: string }[] = [ + { href: '/', label: 'overview' }, + { href: '/components', label: 'components' }, +]; function NavLink({ href, label }: { href: string; label: string }) { const [active] = useRoute(href);