Centralize shared WebUI structural primitives

This commit is contained in:
2026-08-18 13:17:31 +02:00
parent ee5c881df9
commit 7685a103e8
26 changed files with 767 additions and 81 deletions
+62 -1
View File
@@ -5,16 +5,25 @@ function assert(condition: unknown, message = "assertion failed"): void {
import { renderToStaticMarkup } from "react-dom/server";
import ActionToolbar, { ToolbarGroup, ToolbarSpacer } from "../src/components/ActionToolbar";
import ContentGrid, { FormGrid, FormLayout, GridItem } from "../src/components/ContentGrid";
import ContentSection from "../src/components/ContentSection";
import Dialog from "../src/components/Dialog";
import { DialogForm, DialogSection } from "../src/components/DialogAnatomy";
import DescriptionList, { DescriptionItem } from "../src/components/DescriptionList";
import DefinitionNodeIcon from "../src/components/DefinitionNodeIcon";
import DefinitionPalette, { DefinitionPaletteGroup, DefinitionPaletteItem } from "../src/components/DefinitionPalette";
import FilterBar from "../src/components/FilterBar";
import FloatingStatus from "../src/components/FloatingStatus";
import FormSection from "../src/components/FormSection";
import { PlatformLanguageProvider } from "../src/i18n/LanguageContext";
import MetricGrid from "../src/components/MetricGrid";
import SelectionList, { SelectionListItem, SelectionListItemContent } from "../src/components/SelectionList";
import StatePanel from "../src/components/StatePanel";
import WorkspaceLayout from "../src/components/WorkspaceLayout";
import WorkspaceFrame from "../src/components/WorkspaceFrame";
const toolbarMarkup = renderToStaticMarkup(
<PlatformLanguageProvider>
<ActionToolbar label="Object actions" density="compact" surface="subtle" interfaceId="object.toolbar">
<ActionToolbar label="Object actions" density="compact" justify="between" surface="subtle" interfaceId="object.toolbar">
<ToolbarGroup grow>Filters</ToolbarGroup>
<ToolbarSpacer />
<ToolbarGroup align="end">Actions</ToolbarGroup>
@@ -27,6 +36,7 @@ assert(toolbarMarkup.includes('role="toolbar"'), "named toolbars expose toolbar
assert(toolbarMarkup.includes('aria-label="Object actions"'), "named toolbars expose their accessible name");
assert(toolbarMarkup.includes('data-help-scope="toolbar"'), "toolbar help scope is centralized");
assert(toolbarMarkup.includes("action-toolbar-group-grow"), "toolbar groups can own flexible space");
assert(toolbarMarkup.includes("action-toolbar-justify-between"), "toolbar distribution is centrally controlled");
assert(toolbarMarkup.includes("action-toolbar-spacer"), "the standard action spacer is available");
const gridMarkup = renderToStaticMarkup(
@@ -41,6 +51,11 @@ assert(gridMarkup.includes("content-grid-columns-3"), "content grids expose expl
assert(gridMarkup.includes("content-grid-collapse-wide"), "content grids expose explicit collapse ownership");
assert(gridMarkup.includes("content-grid-item-full"), "grid items can span the complete layout");
const sectionMarkup = renderToStaticMarkup(<ContentSection density="compact" layout="stack" surface="subtle">Section</ContentSection>);
assert(sectionMarkup.includes("content-section-spacing-block"), "content sections own standard block rhythm");
assert(sectionMarkup.includes("content-section-surface-subtle"), "content sections expose central surface variants");
assert(sectionMarkup.includes("content-section-layout-stack"), "content sections can own compact stacked evidence anatomy");
const metricMarkup = renderToStaticMarkup(
<MetricGrid columns="auto" density="compact" spacing="inset" minimum="compact" collapseAt="standard">
<div>Open</div><div>Closed</div>
@@ -67,6 +82,52 @@ const inlineDescriptionMarkup = renderToStaticMarkup(
assert(inlineDescriptionMarkup.includes("description-list-columns-1"), "inline description lists default to one list column");
assert(inlineDescriptionMarkup.includes("description-list-term-compact"), "inline description lists centralize term sizing");
const workspaceMarkup = renderToStaticMarkup(
<PlatformLanguageProvider>
<WorkspaceLayout
variant="split"
surface="contained"
primaryLabel="Objects"
primary={<SelectionList variant="navigation" label="Objects"><SelectionListItem selected><SelectionListItemContent title="Object" description="Draft" /></SelectionListItem></SelectionList>}
>
<StatePanel size="fill" title="No object selected" actions={<button type="button">Create</button>} />
</WorkspaceLayout>
</PlatformLanguageProvider>
);
assert(workspaceMarkup.includes("workspace-layout-surface-contained"), "bounded list-detail workspaces share their surface anatomy");
assert(workspaceMarkup.includes("selection-list-navigation"), "resource navigation lists share selection geometry");
assert(workspaceMarkup.includes("selection-list-item-content"), "selection-list copy owns title and description typography");
assert(workspaceMarkup.includes("state-panel-size-fill"), "whole-surface states share sizing and action anatomy");
const frameMarkup = renderToStaticMarkup(
<PlatformLanguageProvider><WorkspaceFrame as="main" height="viewport" label="Planning workspace" surface="panel"><span>Body</span></WorkspaceFrame></PlatformLanguageProvider>
);
assert(frameMarkup.includes("workspace-frame-surface-panel"), "full-height module frames share overflow and surface anatomy");
assert(frameMarkup.startsWith("<main"), "workspace frames preserve the owning page landmark");
assert(frameMarkup.includes("workspace-frame-height-viewport"), "workspace frames centralize application viewport sizing");
assert(frameMarkup.includes('aria-label="Planning workspace"'), "workspace frames expose their accessible name");
const definitionMarkup = renderToStaticMarkup(
<PlatformLanguageProvider>
<DefinitionPalette label="Nodes" description="Drag onto the canvas">
<DefinitionPaletteGroup label="Sources">
<DefinitionPaletteItem icon={<DefinitionNodeIcon>DB</DefinitionNodeIcon>} label="Database" />
</DefinitionPaletteGroup>
</DefinitionPalette>
<FloatingStatus>Working...</FloatingStatus>
</PlatformLanguageProvider>
);
assert(definitionMarkup.includes("definition-palette-items"), "definition editors share bounded palette anatomy");
assert(definitionMarkup.includes("definition-node-icon"), "definition nodes share icon geometry");
assert(definitionMarkup.includes("floating-status"), "floating activity state uses the central overlay");
const filterMarkup = renderToStaticMarkup(
<FilterBar as="form" surface="panel" width="compact"><input aria-label="Search" /><button type="submit">Find</button></FilterBar>
);
assert(filterMarkup.startsWith('<form class="filter-bar'), "filter bars can preserve native form semantics");
assert(filterMarkup.includes("filter-bar-surface-panel"), "filter placement and surface are centralized");
const formMarkup = renderToStaticMarkup(
<PlatformLanguageProvider>
<FormSection title="Identity" description="Stable identifying values" actions={<button type="button">Reset</button>}>