Define semantic page archetypes

This commit is contained in:
2026-08-19 14:26:25 +02:00
parent c042244da8
commit 41db78c201
18 changed files with 315 additions and 87 deletions
+10 -2
View File
@@ -28,8 +28,8 @@ const layoutStyles = read("src/styles/layout.css");
const authGateStyles = read("src/styles/auth-gate.css");
assert.match(settings, /contextId: "core\.settings"/, "settings expose stable contextual documentation");
assert.match(settings, /There are no unsaved profile changes\./, "profile save explains its clean state");
assert.match(settings, /There are no unsaved interface changes\./, "preference save explains its clean state");
assert.match(settings, /archetype=\{editorSection \? "editor" : "workspace"\}/, "settings declare editor intent only for draft-owning sections");
assert.match(settings, /<PageActionBar[\s\S]*variant="editor"[\s\S]*dirty=\{editorDirty\}[\s\S]*discardAction=[\s\S]*saveAction=/, "settings use central dirty persistence actions");
assert.match(retention, /<ActionBlockerHint/, "retention renders the shared actionable blocker");
assert.match(retention, /contextId: "privacy\.retention"/, "retention exposes stable admin documentation");
@@ -52,6 +52,8 @@ assert.match(credentials, /disabledReason: writeDisabledReason/, "credential row
assert.doesNotMatch(credentials, /<textarea/, "credentials use typed controls rather than a primary JSON editor");
assert.match(pageLayout, /`page-layout-\$\{mode\}`/, "shared standalone and embedded pages use one central frame");
assert.match(pageLayout, /export type PageArchetype = "overview" \| "collection" \| "detail" \| "editor" \| "workspace"/, "page intent uses the five central archetypes");
assert.match(pageLayout, /data-page-archetype=\{archetype\}/, "shared pages expose their semantic archetype");
assert.match(pageLayout, /<PageHeader/, "shared pages use one central responsive heading");
assert.match(pageLayout, /data-help-scope="page"/, "shared pages preserve contextual-help identity");
assert.match(adminPageLayout, /<PageLayout/, "administration composes the central page layout instead of redefining it");
@@ -62,7 +64,13 @@ assert.match(actionToolbar, /data-help-scope="toolbar"/, "shared toolbars preser
assert.match(pageActionBar, /variant: "collection"/, "collection pages have a semantic action-bar contract");
assert.match(pageActionBar, /variant: "detail"/, "detail pages have a semantic action-bar contract");
assert.match(pageActionBar, /variant: "editor"/, "editors have a semantic action-bar contract");
assert.match(pageActionBar, /variant: "overview"/, "overview pages have a semantic action-bar contract");
assert.match(pageActionBar, /variant: "workspace"/, "task workspaces have a semantic action-bar contract");
assert.match(pageActionBar, /refreshable: true;\s*reloadAction: ReactNode;/, "refreshable pages require a Reload action at type level");
assert.match(pageActionBar, /dirty: boolean;/, "editors require an explicit dirty state");
assert.match(pageActionBar, /data-page-dirty-state=/, "editors announce clean, dirty, and saving states");
assert.match(pageActionBar, /<ActionSlot name="reload">/, "page action bars keep reload in a named stable slot");
assert.match(pageActionBar, /data-page-action-separation="destructive"/, "destructive page actions expose a separate semantic group");
assert.match(pageActionBar, /<ActionSlot name="discard">[\s\S]*<ActionSlot name="save">/, "editor save follows discard in the trailing group");
assert.match(contentGrid, /content-grid-collapse-\$\{collapseAt\}/, "shared grids make their collapse point explicit");
assert.match(formSection, /form-section-header/, "shared form sections own heading and action placement");