Components
Live components, not drawings. Everything below is the same code the platform imports from src/components/system/ui.tsx — so the manual cannot drift from the build. Every state ships pre-tested against the contrast law.
The CTA law applies to every state — no component ships below AA.
Buttons
One primary per view.
<Button>Book a scan</Button>
<Button variant="secondary">Learn how it works</Button>
<Button variant="tertiary">Watch a demo →</Button>
<Button variant="destructive">Cancel scan</Button>
<Button disabled>Unavailable</Button>Form fields
Errors speak in words, not colour.
We only use this to schedule your scan.
This ID is 14 digits. Check the last two.
<Field label="Property address" placeholder="Apartment 1104, Marina Gate 2"
help="We only use this to schedule your scan." />
<Field label="Emirates ID" defaultValue="784-1973-73291"
error="This ID is 14 digits. Check the last two." />The verified row
Earned — it appears only after sealing.
<VerifiedRow>Move-in scan sealed · 27·07·2026 · 14:32 GST</VerifiedRow>Record states
Green is earned; disputed is neutral, never alarmed.
{['draft','scanned','sealed','verified','disputed']
.map(s => <StatusChip state={s} />)}Record card
The composed unit dashboards are built from.
Marina Gate 2 · Apt 1104
RV-2026-00417
<Card title="Marina Gate 2 · Apt 1104" meta="RV-2026-00417"
footer={<><Button size="sm">Open record</Button>
<Button variant="tertiary" size="sm">Share →</Button></>}>
<VerifiedRow>Sealed · hash 9F4A…C21D</VerifiedRow>
</Card>Modal
Focus trapped, ESC closes, scroll locked, one at a time.
<Modal open={open} onClose={close} title="Cancel this scan?"
actions={<><Button variant="secondary" size="sm">Keep booking</Button>
<Button variant="destructive" size="sm">Cancel scan</Button></>}>
The record stays in draft. Your payment is refunded in full within 5 days.
</Modal>Hand-off
The SoW words this deliverable as “coded HTML/CSS components”. These are React + Tailwind, which compiles to exactly that: the production CSS bundle ships alongside the build, and each component's rendered markup is available above. Any consumer that can't run React can lift the classes and markup directly.