The Developer Style Guide.
The canonical style guide for every Open Claw prototype — locked from the Purchase Order page rebuild (proto-multi-supplier-po). Orange · purple · blue button hierarchy, document-page patterns, tables, chrome, and widgets. Copy-paste the snippets; demos render in the actual styles they teach.
Prefer plain text? Same content as styling-guide.md — paste into any AI context, drop into a repo, or read offline.
Structure
Every FieldInsight page is the same three parts: a dark purple top bar with global controls, a dark purple left sidebar with module nav, and a cream content area where the work happens. Container max-width is 1180 px. Page shapes (list, detail, dashboard) are inherent in the product — this guide focuses on style and affordance, not wireframes.
Page skeleton
Three CSS Grid areas: top bar (48 px row), sidebar (220 px column), everything else. Sidebar collapses at < 900 px.
HTML code
CSS code
Spacing rhythm
| Use | Px | When |
|---|---|---|
| Page padding (X) | 36 | Side gutters in .app-content |
| Page padding (top) | 32 | From top bar to first heading |
| Section gap | 52 | Between top-level sections |
| Subsection gap | 28 | Between h3 groups inside a section |
| Component gap | 14 | Between buttons in a row, cards in a grid |
| Tight gap | 8 | Inside a button (icon ↔ label), chip clusters |
Text formatting
Two font families, both from Google Fonts. Bricolage Grotesque for display (page titles, section heads, big numerals). Plus Jakarta Sans for everything else. JetBrains Mono only for code, IDs, URLs.
Font stack
CSS code
Type scale
Page title — Bricolage 32 / 700 / -0.025em
Section heading — Bricolage 22 / 700
Subsection — Bricolage 17 / 600
Body — Plus Jakarta Sans 14 / 400. The default. Use for everything except headings, code, and small captions.
Body soft — 13 / 400, var(--fi-text-soft). For supporting text inside cards.
Caption / Eyebrow — 11.5 / 700 / 0.12em tracking
// inline code — JetBrains 12.5
| Role | Font | Size | Weight | Tracking | Color token |
|---|---|---|---|---|---|
| Page title (H1) | Display | 32 | 700 | -0.025em | --fi-text |
| Section (H2) | Display | 22 | 700 | -0.02em | --fi-text |
| Subsection (H3) | Display | 17 | 600 | -0.01em | --fi-text |
| Body | Body | 14 | 400 | — | --fi-text |
| Body soft | Body | 13 | 400 | — | --fi-text-soft |
| Caption / eyebrow | Body | 11.5 | 700 | 0.12em UPPERCASE | --fi-text-muted |
| Button label | Body | 12–13 | 700 | — | varies |
| Code / IDs | Mono | 12–12.5 | 500 | — | --fi-text |
Text colours
| Token | Hex | Use |
|---|---|---|
--fi-text | #1A1230 | Primary body text, headings, table cells |
--fi-text-soft | #4A3D6B | Supporting text, descriptions, sub-labels |
--fi-text-muted | #6F6489 | Captions, table headers, breadcrumbs, "last updated" |
--fi-primary | #FF6A13 | Links, focus states, dates that need emphasis |
var(--fi-primary). "Today", selected days, active month chips, and date input focus rings render in the primary colour — never an accent. This makes date state instantly recognisable across every palette.
Buttons & hierarchy
The PO page defines the canonical button stack for every Open Claw prototype. Four action colours on document pages — green (lifecycle hero: Submit · Approve · Finalise), orange (attention / confirm), purple (workflow event), blue (working tools). Green is the one permitted filled-button exception on white document pages — not a free pass for every verb. At most two filled buttons per visible region — typically one green lifecycle hero + one purple workflow event.
--fi-chrome-bg · #39006B); active nav uses orange (--fi-primary). Lifecycle buttons on the white document use status green (#1E7A3A) so navigation never competes with the hero action. Orange on buttons = attention moments (Confirm goods received) and general app CTAs (+ Book Job) — not the default lifecycle fill.
The seven levels
| Level | Class / token | Size | Colour | Use on document pages |
|---|---|---|---|---|
| L1 Lifecycle hero | po-btn-status-green · BTN_STATUS_GREEN | 32 px | Status green #1E7A3A · hover #166030 | Approve · Submit · Finalise — ONE per region |
| L1 Attention | po-btn-attention · BTN_STATUS_ORANGE | 32 px | Orange #FF6A13 | Confirm goods received (hold banner) |
| L2 Workflow | po-btn-purple · BTN_PURPLE | 28 px | Purple #6C5AC4 · hover #513FAD | Reconcile Supplier Invoice · Create Credit |
| L3 Standard | po-btn-standard · BTN_STANDARD | 28 px | Blue tint | Close · + Find Bill · Receive all · Approve & Email · companions |
| L3b Ghost doc | po-btn-ghost-doc · BTN_GHOST_DOC | 28 px | White + blue border | Preview · Download · Email · Copy · Create job ▾ · Export to Xero |
| L4 Inline link | po-btn-link · LINK_BLUE | text | #2563EB | + Add from library · + Add line item |
| L5 Destructive | po-btn-danger · BTN_GHOST_DANGER | 28 px | Red ghost | Delete (Draft only, far right) |
Live stack — all levels
Drag files here · not imported into the document
Drag files here · AI imports line items to the document
Per-region button map
| Region | Button | Level |
|---|---|---|
| Footer lifecycle | Submit · Approve · Finalise | L1 Lifecycle hero (green) |
| Approve & Email · Receive all | L3 Standard (blue) | |
| Close | L3 Standard — left-isolated | |
| Preview · Download · Email · Copy | L3b Ghost doc | |
| Create job ▾ · Export to Xero | L3b Ghost doc | |
| Delete | L5 Destructive — far right, Draft only | |
| Bills (expanded) | Reconcile Supplier Invoice | L2 Workflow (purple) |
| + Find Bill · + Generate Bill from PO · + Generate Blank Bill | L3 Standard | |
| Create Credit | L2 Workflow (purple) | |
| Use Credit | L3 Standard | |
| Credit Notes | Create Credit · Use Credit | L2 + L3 |
| Line items | + Add from library · + Add line item | L4 Inline link |
| Import preview modal | Auto-create codes & add to PO | L1 Hero |
| Add as-is · All new → service · Cancel | L3 Standard · muted · text | |
| Hold banner | Confirm goods received | L1 Attention (orange) |
| Import zones | Attach Choose file · AI Choose file | L3 Standard · L2 Workflow + sparkle |
Click-? hints
Workflow buttons carry a hover-revealed ? glyph (see Bills demo above). Click opens a dialog: Description (business meaning) + Example (real PO data). One dictionary per page (FOOTER_BTN_INFO). Hover-only tooltips are banned on workflow verbs. Labels are verb-led: "Reconcile Supplier Invoice" not "Supplier Invoice Received".
The wall of buttons
Do
- One green L1 lifecycle hero per visible region (Submit · Approve · Finalise).
- Orange for attention confirmations — not the default lifecycle fill.
- Purple for workflow events that aren't the lifecycle verb.
- Blue tint for companions and mid-page tools; ghost-doc for footer utilities.
- Click-
?on every workflow button — no hover-only tooltips. - Map onto
poButtonTokens.ts— never invent per-repo colours.
Don't
- Multiple green fills in one region — green is ONE lifecycle hero only; not every verb.
- Three or more filled buttons in one row — budget is max 2 fills per region.
- Duplicate affordances (+ File when Attach zone exists; View/Edit when chevron exists).
- Deep purple
#39006Bon workflow buttons — that's AI-only (§7).
Tables
The default data table pattern: white card on cream surface, uppercase-tracking header row, subtle hover, status pills in the right-side column. Use for any list-of-things page (jobs, customers, invoices, assets).
Data table
| Job # | Customer | Type | Scheduled | Status | Actions |
|---|---|---|---|---|---|
JOB-14517 |
ACME Heating & Cooling | HVAC service | Mon 1 Jun, 09:00 | Scheduled | |
JOB-14516 |
Bayside Apartments | Coil replacement | Tue 2 Jun, 13:00 | Draft | |
JOB-14515 |
Hutton St Body Corp | Quarterly PPM | Fri 29 May, 11:30 | Complete | |
JOB-14514 |
Trade Tools AU | Switchboard fault | Wed 27 May, 08:00 | Overdue |
HTML code
Status pill semantics
| Pill | Meaning | Background | Text |
|---|---|---|---|
| Draft | Unfinished record | --fi-surface-2 | --fi-text-muted |
| Scheduled | Committed, future | info tint | --fi-info |
| Complete | Done, no action needed | success tint | --fi-success |
| Overdue | Needs attention | danger tint | --fi-danger |
Do
- Action column right-aligned, with tertiary-tier
Open →per row. - IDs in mono font (
JOB-14517) for scannability. - Status as a pill, never a free-text word.
- Hover state on rows for affordance — links to the detail page.
Don't
- Striped rows (zebra). The hover state is enough.
- Heavy borders between every cell — only between rows.
- Put primary-tier buttons inside row actions. Use tertiary.
- Wrap status text in a coloured div — use the pill class so the shape is consistent.
Chrome & in-page controls
Five surfaces wrap every page: top bar, primary sidebar, secondary mini-nav, page header, and the breadcrumb. Each one contains multiple sub-components — documented below as cards so a developer can drop just the piece they need into a screen.
5.1 Top bar
One bar with five sub-components, left to right: brand, trial banner, spacer, action cluster (search + clock-in/log-time + icon buttons). The bar at the very top of this page is the live render — these cards isolate each piece so you can copy just one.
Brand chip .brand
Wordmark + filled orange mark square. Always the leftmost element. Click returns to the default landing page (usually /schedule).
HTML code
Trial / system banner .trial-banner
Inline status line in the top bar — trial countdown, "demo data", deploy-state warnings, the "Switch to live" toggle. Always inline (never a separate row) so the chrome stays one bar. The CTA at the end uses --fi-primary so it pops against the dark purple chrome.
HTML code
Search mini-app .cmp-search
A pill that combines a scope chip (Jobs / Customers / Invoices / etc.) with a text input and an orange go button. Scope chip is its own dropdown — picks which entity the query searches. Open shortcut: ⌘ K. Submit returns the user to the matching list view, pre-filtered.
HTML code
Clock-in / Log-time cluster soft-action
Two soft-action buttons (per Section 3). Low-emphasis CTAs that don't compete with the page's primary orange action. Used for time tracking — the user clocks in once at the start of a shift; Log time records discretionary entries to a job.
HTML code
Top-bar icon cluster .top-icon ×N
Right-edge cluster of square icon buttons: notifications, mobile-app pairing, settings, chat. All are icon tier (26 × 26 px) so they line up vertically with the soft-action cluster's height. A red dot indicates unread / attention state.
HTML code
5.2 Left primary sidebar
The module nav. Profile chip pinned at top, 14 module links below, Help anchored at the bottom. Collapses to an icons-only 56 px rail on narrower viewports (or on user preference) — every label hides, the active accent stays. Active state uses --fi-chrome-active (orange · --fi-primary) with a white left border — dark purple chrome, orange wayfinding. Lifecycle green stays on document buttons only (§3).
Profile / account chip .cmp-profile
Pinned to the top of the sidebar (above the module list). Three lines: user name + role chip · profile sub-label · company name. Click opens the user menu. Read-only in the collapsed state — only the avatar dot shows.
HTML code
Module nav · 14 items .app-sidebar a
Schedule · To-do · Accounts · Projects · Jobs · Map · Timesheets · Reports · Inventory · Sales · Assets · Safety · Library · Help. Each link is icon + label. Help is anchored to the bottom of the column so it's always one click away.
HTML code
Collapsed state 56 px icons-only
User-toggleable. When collapsed, the sidebar shrinks to 56 px showing only icons; labels appear as tooltips on hover. The active accent stays visible (the orange/green left border) so the user always knows where they are. Use this on narrow viewports (< 1100 px) by default; full state above that.
5.3 Secondary mini-nav
A thin vertical strip between the primary sidebar and the content area. Each icon toggles a side panel for the active module (mini-calendar picker on Schedule, unscheduled-jobs list on Schedule, customer-quick-pick on Accounts). One module owns its mini-nav — when you change module, the strip's icons change with it.
Module-specific side-panel toggles
Each icon button opens / closes a corresponding side panel. Active panel = highlighted icon (orange fill). At most one panel open at a time — clicking a second icon swaps the panel content.
HTML code
5.4 Page header
The action row that sits at the top of every page's content area, beneath any breadcrumb. Contains everything that scopes / acts-on the data shown below: period switcher, time stepper, primary CTA, quick actions, filter bar. Order is consistent left-to-right so users learn it once and recognise it on every page.
Period switcher + stepper .cmp-period
Two controls living side by side. The switcher (Month / Week / Day) and Rotate set the granularity of the schedule view. The stepper (◀ May ▶) walks backward/forward through periods at the chosen granularity. "Today" is marked with the primary-orange dot per the date-contrast rule.
HTML code
Primary CTA + quick actions + Add ⚡ 📍
The hero action for the page — + Add Job on Schedule, + Add Account on Accounts, etc. Always orange-filled primary tier per Section 3. Quick-action icons sit next to it — page-specific shortcuts like auto-allocate (⚡) and pin-to-map (📍). They're icon tier with a tooltip, no label.
HTML code
Filter bar + Add Filter · Search
Lives on the next row down (below the period/CTA row). + Add Filter is an outlined secondary-tier button that opens a filter chooser modal. Search is the primary-fill secondary-tier button that applies the current filter set and refreshes the data below. Once filters are applied they appear as chips between these two buttons.
HTML code
5.5 Breadcrumbs
Single-line back link above the page title. Use .crumb with a back-arrow prefix. For nested detail pages, list parent module → list view → detail.
AI styling addendum
This page is the master style guide. AI pattern rules live here in Section 7 — not in a separate app.
AI surfaces — canonical rules (Section 7)
Any feature where AI does work (parsing, matching, suggesting, drafting) marks the moment with the canonical Two-Star sparkle in #39006B. Three placements only: inline icon · circular badge (max one per page) · pill CTA. Approved labels: Ask AI, Re-read, Re-generate, Scan bill, Post to Xero →. Everything else on the page uses the tokens in Sections 1–6.
Full pattern spec (SVGs, CSS, provenance rules): workspace ai-styling-pattern.md.
Document pages & widgets
The PO detail page went through ~10 UX iterations — chevron disclosure, masthead card, banner removal, purple softening. These are the patterns that survived. They apply to any document page: PO, quote, invoice, bill, credit note.
6.1 Chevron disclosure
One rotating chevron (▸ / ▾) at the left of the section title. The whole header row is the click target — cursor: pointer, soft hover tint. A count chip follows the title; state persists per user in localStorage. Never ship View / Edit or Expand / Collapse button pairs — the chevron replaces them.
HTML code
6.2 The masthead card
Every document page opens with one identity card: uppercase eyebrow (document type), the counterpart name as headline, a fact grid (date · delivery · reference), and an "Edit details" disclosure that expands the edit form in place. The document number, status pill, and template selector stay in the page header above — the masthead owns who and when.
6.3 Line table
| # | Supplier Code | Internal Code | Description | Qty | Line Total |
|---|---|---|---|---|---|
| 1 | CLI264/3SMgry | QSW-SVC | Service call-out | 1 | $185.00 |
| 2 | L&CCLCM20-M20 | FIT-20 | 20mm compression fitting | 4 | $48.60 |
PO shows both codes: purple Supplier Code (what the supplier picks/packs) + orange Internal Code (your inventory). Header band #F0F0F2; supplier column purple #6a1b9a; internal column orange. Fully-received rows tint #f1f8e9 (status only — not a button colour).
6.4 Rules that survived the iterations
| Rule | Detail |
|---|---|
| Rich collapsed summaries | Money and key values bold; progress coloured by state (success green when complete, muted otherwise). If there's nothing worth saying, say nothing — don't pad. |
| Uniform section rhythm | One divider component between sections, same margin everywhere (≈10 px). Title-row → action-row gap is one fixed value in every section — per-section drift is visible at a glance. |
| Inline affordance beats banners | If the fix is available inline (highlighted picker cell in the exact problem row), do not also show an alert banner counting the problems. One affordance per problem. |
| Screen vs print split | .print-only for letterhead / address band; .no-print for chevrons, chips, action rows. On beforeprint, expand collapsed sections the document needs; restore on afterprint. |
| Verb-led labels | Buttons say what happens next, not what already happened — "Reconcile Supplier Invoice" (opens reconciliation) replaced "Supplier Invoice Received". |
6.5 Workflow palette recap
Green lifecycle hero (Approve/Submit/Finalise, one per region) → orange attention (Confirm goods received) → purple workflow (Reconcile Supplier Invoice) → blue tools (everything else). Bright green #22C55E is status pips and chips only — not a button fill. Deep purple #39006B on chrome is navigation; on buttons it is AI-only (§7).
6.6 Click-? hints
Workflow buttons (section action rows, lifecycle footer, dialog primaries) carry a hover-revealed ? glyph at the top-right corner; clicking it opens a dialog with Description (business meaning, leads with why) and Example (this customer's real data shape — real PO numbers, suppliers, dollar values). Hover tooltips disappear before users can read them and never work on touch. One shared dictionary per page (e.g. FOOTER_BTN_INFO) is the single source of truth — no key, no ship. Reference: InfoableButton, proto-multi-supplier-po v1.27.20 (12 workflow buttons documented); canonical doc: apply-tooltip-pattern.md.
CSS code
affordance-style-guide.md · tokens: poButtonTokens.ts.
Explicit by design
Where possible, make information discoverable and clear. Users should never have to guess what a control does, or open Settings to learn state that belongs on the page they are already on. Explicit, never implicit behaviour. These three rules sit above button tiers and colour — they explain why we resist clutter.
The three rules
| Rule | Stands for | Means | Instead of… | Do… |
|---|---|---|---|---|
| NAB | Not Another Button | One entry point per action class — never duplicate the same verb in a second control. | A + File button when an Attach zone exists · View/Edit pair when a chevron discloses · Select items when the grip column selects |
Use the zone, chevron, row click, inline link, or existing footer tool |
| NAT | Not Another Toggle | Don't hide behaviour behind an unlabelled or mystery switch — state and consequence must be readable at a glance. | A nameless ON/OFF pill · toggle that changes data with no inline label · "enable advanced mode" with no explanation on the page | Label the toggle (what it controls + current state) · or show read-only state inline and edit in place |
| NAS | Not Another Setting | Don't bury information in Settings (or a modal three clicks away) when it belongs where the user is working. | Visible/required flags only in System Fields admin · document status you can't see until you expand a menu · pricing rules hidden in a config screen the PO author never opens | Surface the fact on the page — count chips, disclosure summaries, masthead fields, column headers, click-? hints |
Discoverable by default
A collapsed section header should still answer "do I need to open this?" — chevron + title + count chip + inline facts (see §6.1). A document masthead should show who, when, and reference without opening Edit (see §6.2). A workflow button should explain why via click-?, not a hover tooltip that vanishes (see §3 · §6.6). If the user has to hunt, you have violated NAS. If they have to guess what a switch does, you have violated NAT. If two controls do the same job, you have violated NAB.
PO page examples
Do — explicit & discoverable
- NAB: Attach-file zone is the only file entry — no separate
+ Filebutton. - NAB: Chevron disclosure replaces View / Edit / Expand / Collapse button pairs.
- NAS: Collapsed Bills header shows 1 bill · Total billed $643.50 / $661.17 PO value — no need to open Settings or guess.
- NAS: Line Items header shows line count, total inc GST, and received count while collapsed.
- NAT: Settings toggles (Profile P) are labelled Visible / Required — never a mystery switch on a document page.
- Explicit: Every workflow verb gets click-
?with Description + Example — business meaning, not data shape alone.
Don't — implicit & cluttered
- NAB: Attach zone and a
+ Filebutton — two entry points, same action. - NAB: Grip column for row select and a
Select itemstoolbar button. - NAB: Twelve equal footer buttons — every action looks primary; nothing is discoverable by hierarchy (see §3 wall-of-buttons).
- NAS: Bill reconciliation status only visible after expanding three sections — user can't triage from the page chrome.
- NAT: Unlabelled toggle that changes line behaviour with no inline explanation.
- Implicit: Hover-only tooltips on workflow verbs — disappear before the user reads them; fail on touch.
HTML code
apply-tooltip-pattern.md (click-? for explicit workflow meaning). When in doubt: make it visible, label it, or collapse it with facts — never add another control.