Type to search pages and rules.

Browse pages

Web UI

This page states how the TypeScript web stacks realize the frontend UI rules (Frontend UI).

Markdown14 provisions

Intent#

This page states how the TypeScript web stacks realize the frontend UI rules (Frontend UI). It states the toolchain, registry, tokens, and suites one web frontend requires. A provision here cites the neutral rule it realizes.

Concepts#

The web baseline#

The React baseline is the manifest uiBaseline entry. The Svelte baseline is the manifest uiBaselineSvelte entry. The registry build runs shadcn build on React and shadcn-svelte build on Svelte.

The browser route suite#

The browser suite discovers its routes from the generated route tree rather than from a list. A new route is therefore checked without a specification written for it. A dynamic segment resolves to a record the deployment holds. It falls back to an absent record when the deployment holds none.

CheckThe route passes when
FloorplanExactly one element carries data-floorplan
ReferenceEach route names its registry item or is a recorded freestyle route
Accessibilityaxe reports zero WCAG 2.2 AA violations
HeadingThe page carries exactly one visible h1
LandmarkThe page carries one main landmark
ReflowAt 320 CSS pixels the page has no horizontal overflow; a data table may scroll inside its own region
Text spacingThe reflow check still passes under the WCAG 1.4.12 text-spacing override
KeyboardEvery interactive element is reachable and shows a visible focus indicator
Target sizeEvery pointer target meets the minimum size or spacing
AnnouncementsAsynchronous status changes announce through a live region

Standards#

Pin the baseline in the shared package#

rulecheckable

Requirement A workspace MUST install the pinned baseline from litespec.manifest.json once, into its shared UI package, using the uiBaseline or uiBaselineSvelte entry.

Rationale The committed files are the CLI's configuration, the registry source, the token stylesheet, and the source lock beside them. Installing per application made a fourth copy. Drift in that copy was invisible. An additional registry is permitted under an exception recorded against this provision. The React baseline is the manifest uiBaseline entry and the Svelte baseline is the uiBaselineSvelte entry. This realizes litespec/frontend/ui#pin-the-baseline-in-the-shared-package.

litespec/frontend/web/ui#pin-the-baseline-in-the-shared-package

Publish one registry item per floorplan#

rulecheckable

Requirement The shared package MUST publish a registry whose build exits zero and which lists one item per floorplan the design contract declares.

Rationale Without an installable page, an author invents one from primitives. One item per floorplan gives every page type a reference the author installs before writing. The registry build runs shadcn build on React and shadcn-svelte build on Svelte.

litespec/frontend/web/ui#publish-one-registry-item-per-floorplan

Compose each route from one floorplan#

rulecheckable

Requirement A route MUST render exactly one floorplan from the declared set, unless it is a recorded freestyle route.

Rationale The floorplan fixes the layout, the heading position, and the slots. A reviewer reads which floorplan a route composes. The slots take domain values: the business record state, the use cases that state permits, and the refusal results of the called use case. This realizes litespec/frontend/ui#compose-each-route-from-one-floorplan.

Example An order route composes the entity floorplan and fills each slot from the order.

React:

TSX
<EntityPage
  title={order.number}
  status={<OrderStatus state={order.state} />}
  actions={<OrderActions permitted={order.permittedActions} />}
  facts={<OrderFacts order={order} />}
  related={<OrderPayments orderId={order.id} />}
/>

Svelte:

Svelte
<EntityPage title={order.number}>
  {#snippet status()}
    <OrderStatus state={order.state} />
  {/snippet}
  {#snippet actions()}
    <OrderActions permitted={order.permittedActions} />
  {/snippet}
  {#snippet facts()}
    <OrderFacts {order} />
  {/snippet}
  {#snippet related()}
    <OrderPayments orderId={order.id} />
  {/snippet}
</EntityPage>
litespec/frontend/web/ui#compose-each-route-from-one-floorplan

Keep layout inside floorplans#

ruleguidance

Requirement Route code MUST NOT carry a layout utility such as grid, flex, gap-*, space-*, or col-span-*.

Rationale A layout utility in a route file is a second layout beside the floorplan. The next route copies it. Floorplan and display composites own layout. One change reaches every route composing them. This realizes litespec/frontend/ui#keep-layout-inside-floorplans.

litespec/frontend/web/ui#keep-layout-inside-floorplans

Derive each page type from a named reference#

rulecheckable

Requirement Every route MUST carry a data-registry-item attribute naming its page type's registry item, with a freestyle route carrying no attribute and naming its decision record.

Rationale An author with no named reference invents a page from primitives, and the next author invents another. An attribute that resolves keeps every page of one type on one reference. This realizes litespec/frontend/ui#derive-each-page-type-from-a-named-reference.

litespec/frontend/web/ui#derive-each-page-type-from-a-named-reference

Select a tone from the closed set#

rulecheckable

Requirement A state indicator MUST take one tone from the closed set, each application declaring its state-to-tone mapping once as an exhaustive table of language terms.

Rationale A page that picks a color picks a meaning nobody agreed to. One mapping means the same state reads the same way on every screen. A new state then fails to compile until its tone and its word exist. The table lives in src/app/states.tsx on React and src/lib/app/states.ts on Svelte. This realizes litespec/frontend/ui#select-a-tone-from-the-closed-set.

litespec/frontend/web/ui#select-a-tone-from-the-closed-set

Keep tokens in one stylesheet#

rulecheckable

Requirement An application stylesheet MUST import the shared package's token stylesheet and declare no rule, with no literal color in any stylesheet the shared package ships.

Rationale One token sheet makes two applications look like one product. An application stylesheet imports it and declares no rule. A second sheet never introduces a value the first has no opinion about. A stylesheet the shared package ships beside the token sheet declares no literal color. This realizes litespec/frontend/ui#keep-tokens-in-one-definition.

litespec/frontend/web/ui#keep-tokens-in-one-stylesheet

Hold the declared base color#

ruleguidance

Requirement A token stylesheet MUST carry the values the manifest baseline baseColor ramp publishes, and no value outside them except under a recorded exception.

Rationale A token value outside the published ramp is a second palette beside the declared one, and the next author copies it. A recorded exception keeps the deliberate departure visible in the design contract. The React baseline is the manifest uiBaseline entry and the Svelte baseline is the uiBaselineSvelte entry. This realizes litespec/frontend/ui#hold-the-declared-base-color.

litespec/frontend/web/ui#hold-the-declared-base-color

Check every route in a browser#

rulecheckable

Requirement Every route MUST pass each route suite check in a browser.

Rationale The Concepts section names the checks. They cover the floorplan, the registry reference, axe WCAG 2.2 AA, the heading, the landmark, reflow, text spacing, keyboard use, target size, and status announcements. One suite visits every route, so a new route is checked without a specification written for it. This realizes litespec/frontend/ui#check-every-route.

litespec/frontend/web/ui#check-every-route-in-a-browser

Prove every result a route calls#

ruleguidance

Requirement Every result a called use case returns MUST be proved by a passing test or a known-gap record with owner and end date.

Rationale A refusal a reader can reach and no test provokes is a refusal nobody has seen render. The calls come from the route code, so the obligation follows the code rather than a declaration. This realizes litespec/frontend/ui#prove-every-result-a-route-calls.

Example A browser test calls the use case and asserts one refusal result.

TypeScript
test('shows the changed total before payment', async ({ page }) => {
  // Steps call place-order and assert the expected-total-mismatch refusal.
});
litespec/frontend/web/ui#prove-every-result-a-route-calls

Restrict CSS decisions#

rulecheckable

Requirement A Tailwind class MUST use a semantic token rather than an arbitrary value, a raw palette value, or an important modifier.

Rationale The approved CSS surface is the shared package's stylesheet, holding the Tailwind import, the tokens, the fonts, and the documented resets. The source scan skips build output and reports authored feature CSS. This realizes litespec/frontend/ui#restrict-styling-to-semantic-tokens.

litespec/frontend/web/ui#restrict-css-decisions

Track source changes#

rulecheckable

Requirement The shared package's source lock MUST record the pinned CLI, the registry address, the paths, the normalized digest, and the dependencies for each primitive.

Rationale The lock normalizes source before hashing, so two workspaces compute the same digest for identical source. One lock beside one copy is what makes a changed primitive report a fork rather than pass unreported.

litespec/frontend/web/ui#track-source-changes

Prove UI behavior and appearance#

rulecheckable

Requirement A primitive, composite, token, source, floorplan, or route change MUST name the evidence in the matrix in this section.

Rationale The matrix maps each change class to the narrowest evidence that represents its risk. This realizes litespec/frontend/ui#prove-ui-behavior-and-appearance.

Change classNarrowest evidence
Primitive source or variantThe component test for that primitive
Floorplan or display compositeThe route suite on one route that composes it
Token or global CSSThe route suite on one route in each profile
RouteThe route suite on that route, and every test proving a result it calls
Pattern decisionThe catalog entry changes with its implementation
ForkThe source lock digest and the component test
Behavior packageThe accessibility check for the capability it supplies
litespec/frontend/web/ui#prove-ui-behavior-and-appearance

Conventions#

Use the source update procedure#

conventionguidance

Default Update the primitive source on a branch that pins the CLI, starts clean, and reviews the regenerated files and the local composites separately.

Replacement A consumer replaces this default by recording an exception with its reason and review date.

Rationale Running view, --dry-run, and --diff first shows what the update changes before it is written. The regenerated files and the local composites change for different reasons. One review cannot cover both.

litespec/frontend/web/ui#use-the-source-update-procedure

Verification#

IDMarkEvidence
litespec/frontend/web/ui#pin-the-baseline-in-the-shared-packagecheckablelitespec ui compares the committed configuration against the manifest baseline fields.
litespec/frontend/web/ui#publish-one-registry-item-per-floorplancheckableshadcn build (React) or shadcn-svelte build (Svelte) exits zero, and review confirms registry.json lists one item per declared floorplan.
litespec/frontend/web/ui#compose-each-route-from-one-floorplancheckabletests/routes/every-route.spec.ts asserts page.locator("[data-floorplan]") has count 1.
litespec/frontend/web/ui#keep-layout-inside-floorplansguidanceDoes any route file carry a layout utility outside its floorplan and display composites?
litespec/frontend/web/ui#derive-each-page-type-from-a-named-referencecheckabletests/routes/every-route.spec.ts asserts data-registry-item resolves to a published registry item on every non-freestyle route.
litespec/frontend/web/ui#select-a-tone-from-the-closed-setcheckablepnpm type-check fails on a state with no tone; review confirms each tone is a term.
litespec/frontend/web/ui#keep-tokens-in-one-stylesheetcheckablelitespec ui reports an application stylesheet declaring a rule and a shared stylesheet declaring a literal color.
litespec/frontend/web/ui#hold-the-declared-base-colorguidanceDoes the token stylesheet carry only values from the declared base color ramp, with each departure recorded?
litespec/frontend/web/ui#check-every-route-in-a-browsercheckabletests/routes/every-route.spec.ts runs axe and the Concepts checks on each discovered route.
litespec/frontend/web/ui#prove-every-result-a-route-callsguidanceIs every result the route calls proved by a passing test or named by a known-gap record?
litespec/frontend/web/ui#restrict-css-decisionscheckablelitespec ui rejects an arbitrary value, a raw palette value, or an important modifier.
litespec/frontend/web/ui#track-source-changescheckablelitespec ui recomputes each digest and reports changed primitive source.
litespec/frontend/web/ui#prove-ui-behavior-and-appearancecheckabletests/routes/every-route.spec.ts runs on the changed route, and review confirms the change named the matrix evidence.
litespec/frontend/web/ui#use-the-source-update-procedureguidanceDoes the update branch record the pinned CLI, the dry-run output, and separate review of both file sets?