Workbench · admin theme · pairs with design-admin.md
Calm structure for consequential work.
Workbench is the precise, durable
workspace theme for operators, owners, editors, and support teams. A neutral palette
keeps attention on the work; compact rhythm makes dense information easy to scan;
restrained motion makes every outcome feel immediate. Cedar appears only where it adds
meaning: links, the first data series, and Cedra's presence. This page is the theme's
preview and its brand guideline in one — read it top to bottom to decide whether
Workbench is your theme, then keep it open as the reference while you work in it. The
paired design-admin.md is the implementation standard agents follow when
styling inside the theme, and this two-file pair is the format every Cedros theme
ships.
A content library rendered entirely in Workbench: the quiet
shell, one primary action, placeholder-labeled filters, publish state at a glance,
mono identifiers, tabular numerics, and a single promoted action per row. Cedar
appears exactly where it means something — links, data, and Cedra. This is the
composition a marketplace preview captures.
Admin
Content
Users
Settings
Pages
Manage site pages with revisions, preview, and publish state.
Title
Views
Visitors
Avg session
Exit rate
Actions
Home /
1,284
918
1m 42s
34%
About /about
412
356
58s
41%
Contact /contact
96
88
32s
63%
Documentation /docs
1,893
1,204
4m 06s
18%
Updates /blog
744
602
2m 11s
29%
Everything above is live CSS — toggle dark in the header and the whole
composition holds. Hover the first row for the 800ms update flash; the first ⋯ opens a
real menu (destructive item red, last, below a separator). In the sidebar, Forms
carries a needs-attention badge and Products is capability-locked at 0.48 opacity with
its reason in the tooltip.
Theme identity
Quiet at rest. Immediate in use.
Workbench borrows shadcn's composure and translates it into a
Cedros workspace: denser, more operational, and ready for first-party or extension-owned
surfaces. Familiarity is part of the aesthetic—new capabilities should feel as though
they have always belonged.
Promise
Dense work feels clear
Alignment, compact scales, and visible state make complex operations
easy to scan without making the workspace feel compressed.
Personality
Neutral · precise · capable
Confident without being loud. Helpful without performing. Warmth
appears in language and meaningful accents, not decoration.
Signature
Hairlines, rhythm, restraint
Tabular data, concentric corners, measured elevation, and one cedar
accent create a recognizable system in either mode.
Every ambiguous design choice in Workbench resolves against
these rules. They are why the theme stays coherent as it grows — and why a page built
by an extension author is indistinguishable in kind from a page built by Cedros.
W1 · The primitive wins
One component per job. If it can't do the job,
extend the primitive — never fork a local copy.
W2 · The scale is the law
Eight type sizes, seven spacing steps, three
radii, four elevations, two role-based control heights. Off-scale values are out of character
even when they look fine alone.
W3 · Aligned at rest
Ordinary action buttons are 32px, single-line fields are 36px,
and mixed rows align their centers. Labels share one baseline and numbers one right
edge.
W4 · Dense, calm, scannable
13–14px body, 32px buttons, 36px fields, ~40px rows —
density paid for with hierarchy, never with clutter.
W5 · State over chrome
Only states that need attention may attract
it: unsaved, running, failed, needs review. Everything decorative stays
neutral.
W6 · Instant, keyboard-first, both modes
≤100ms acknowledgment, visible focus only on
keyboard, full keyboard parity, WCAG 2.2 AA in light and dark alike.
W7 · Boring by design
The workspace should look barely different
year over year. New capabilities feel like they were always here.
Foundations · 01 — tokens
A neutral foundation with one meaningful accent
The palette is shadcn's default neutral — the mapping
is exact and deliberate. Toggle dark in the header: every swatch is a live token.
Semantic status colors carry outcomes; chart/art tokens carry non-semantic series and
decoration; --cd-link is the sole cedar accent; a named z-scale keeps every
layer predictable.
--cd-bgbackground
--cd-card-bgcard
--cd-muted-bgmuted
--cd-accentaccent · surface, never text
--cd-borderborder
--cd-ringring
--cd-mutedmuted-foreground
--cd-primaryprimary
--cd-successcompleted · healthy
--cd-warningsurface tints
--cd-warning-fgreadable warning text
--cd-errorstatus error · tints
Aa
--cd-danger-bg/-fgpaired destructive button
--cd-infoinfo
--cd-linkthe only cedar here
--cd-chart-1cedar · chart/art only
--cd-chart-2gold · chart/art only
--cd-chart-3sage · chart/art only
--cd-chart-4clay · chart/art only
--cd-chart-5indigo · chart/art only
--cd-chart-6mist · chart/art only
Foundations · 02 — scales
Eight sizes, two heights, three radii
A small, deliberate scale creates Workbench's visual rhythm.
Eight type roles establish hierarchy; two role-based control heights keep like controls consistent; three
structural radii make nested surfaces feel cut from the same material.
Type — 8 sizes · uppercase only where the eye scans columns
2xs 11px 600 capsTable header · stat label · nav group
xs 12pxCaptions, chip text
sm 13px 400–500Controls, cells, form labels (sentence case), help
base 14px · 600=titlesCard & section titles
md 16px 600Emphasized values
lg 18.4px 600Page & dialog titles
xl 24px 600Stat values
2xl 32px 700 tabular12,418
SITE TITLE — uppercase form labelsSite title — sentence case, 13px/500
Control heights — 32px buttons · 36px single-line fields
Every ordinary action button uses the same 32px outer height. Single-line
fields remain 36px; mixed button-field rows align their centers.
Radius 7 derived · 8 · 12 · pill
Concentric children share the parent's curve center:
child radius = parent radius − the actual outer-edge inset, including the parent border.
Workbench chrome is guarded by npm run lint:admin-corner-radii;
authored/public previews require an explicit reviewed exception.
Elevation
e0border only
e1cards
e2menus
e3dialogs · toasts
Foundations · 03 — mono & numbers
Quantities read. Identifiers copy.
Typography follows meaning. Numbers you
read — counts, money, dates, stats — are the UI sans with
tabular-nums, right-aligned in columns, never mono. Strings you
copy or compare character-by-character — slugs, refs, keys, payloads —
are --cd-font-mono, one step smaller, muted in table cells.
Sans + tabular-nums — quantities
Metric
Value
Revenue · 7 days
$8,940.00
Orders
1,284
Conversion
3.4%
Avg session
1m 42s
Visitors
12.4k
Money is never mono. Abbreviate at five digits (12.4k) with the exact
value on hover. Locale formatters only — no hand-built number strings.
Mono — identifiers, one step smaller
Slug chip/privacy-policy
Referencereq_8f3aCopy
Secret · entry
Secret · saved••••••••••••Saved · updated Jun 12
Versionv2.4.1
Inline chipContact support with code pub_4t2c.
Identifiers earn copy buttons (hover the copy icon — tooltip);
secrets are write-only: an eye toggle while entering, then a mask
with Replace / Remove — a stored secret is never re-shown and never copied. Emails
and names stay sans; ISO timestamps in logs may be mono.
Code block — filename, language, one copy control per block
Read-only code: muted wash, hairline frame, mono 0.72–0.75rem, scrolls
inside its own frame; "Copy" flips to "Copied". Editable JSON is the code textarea with
"Format JSON" + inline validity. Logs are compact tables (status dot · time · area ·
message), never a <pre> wall.
Foundations · 04 — icons
Lucide geometry, 16px, currentColor
Stroke 2, round caps and joins, drawn on a 24 grid,
fill="none". 16px default; 13–14px inside sm controls and menu items;
nothing over 20px in chrome. Icons assist labels — icon-only controls require
aria-label + a tooltip. Extension nav icons are Lucide names from the
manifest (sections[].icon) and render identically to core items. No
fills, no emoji, no duotone, no brand glyphs in the nav.
16px · stroke 220px maxmuted 0.75 at rest → full on hover/active
Composition · 05 — template A, the list page
A dense workspace that stays quiet
The cover composition at the top of this page is Template A
rendered whole. Its grammar: a page header (title, one-sentence subtitle, one primary
action) → one toolbar row with 36px fields and 32px buttons → the table → pagination. The active
destination uses a plain accent fill; keyboard focus appears only when needed. And
when rows support bulk work, the toolbar itself becomes the selection bar:
Labels stacked above toolbar controlsRows crowded with equal-weight actionsplaceholder toolbar · Edit + ⋯ · sentence case · :focus-visible only
Selection & bulk actions — the toolbar becomes the selection bar
2 selected
Title
Views
Home
1,284
About
412
Contact
96
Header checkbox = select-all with the indeterminate state; Esc clears;
destructive bulk actions confirm with the count ("Delete 12 pages?"). Selection is a
toolbar state, not a separate visual language.
Composition · 06 — template B, the settings page
Focused forms with room to think
Segmented tabs hug their content; a
45rem column keeps fields comfortable; labels use sentence case; select
triggers stay single-line with help below; every mutable card ends in a Save footer,
disabled until dirty.
Full-bleed fields and boxed full-width tab barsUppercase form labels and multi-line triggers45rem column · sentence labels · single-line select + help · hugging tabs · Save per card
Site
Manage business info and public contact details.
Business info
The public identity used in search results, link previews, and site metadata.
Used as the homepage meta description and the public summary for this site.
Sets the schema markup for your pages. "Not specified" uses generic markup.
No image
Shown when your site is shared in search, texts, and social feeds. 1200×630px works best.
Public contact
Contact details shown on your public contact page.
HoursChoose the days and time ranges shown with your contact details.
9:00 – 17:00
9:00 – 17:00
Unavailable
Danger zone
These actions affect your live site and can't always be undone.
Delete this site and all of its content. This can't be undone.
Components · 07 — buttons
Five variants, sentence case, one primary per action cluster
Competing primary actions; tinted destructive buttonsNoun-first Title Case labelsprimary · outline · ghost · destructive · link — sentence case
Destructive is solid (shadcn) and rare — it confirms destructive work.
It uses the paired --cd-danger-bg/--cd-danger-fg button tokens;
--cd-error remains the status and tint color. Row-level deletes live in the
⋯ menu as red items, not as buttons. Disabled buttons say what unlocks them, or stay
enabled and validate on click. Page headers, dialog footers, card footers, and toolbars
each get at most one primary; independent settings cards may each own Save.
Components · 08 — tabs
One quiet segmented language
Section-specific tab shapes and heavy typeOne segmented control — 32px triggers, weight 500, hugs content
Track: 3px padding, hairline border, 4% wash. Active: background fill +
hairline inset + e1. Roving tabindex + arrow keys follow the WAI-ARIA convention.
Indicator movement 220ms.
Components · 09 — form controls
One input, one select, one switch, one checkbox
Help text sits here. Errors replace it in place — no layout jump.
Enter a valid email address, like ana@cabrillo.coffee.
Descriptions live here — never inside the trigger.
Specialized fields — dates picked, times typed, no OS popovers
Schedule publishThe trigger wears the input anatomy and opens the 280px calendar popover — keyboard grid, month/year fast-nav, Clear/Today, typed time row. Time-of-day fields are typed segments; the OS popup never appears.
Monday hours
to
retries
Enter a 3- or 6-digit hex like #0f172a.
Tags — chip strip + one add control · 18 tones
Coffee Wholesale Newsletter VIP ext Loyalty member
Tones run slate → rose (18; unknown falls back to slate). Every chip
has its ✕; extension-managed tags carry the ext badge and aren't
hand-removable. Adding goes through the standard select — never freetext typed
into the strip.
Components · 10 — toggles & selection
Five controls, chosen by rule
Switch = applies immediately, never behind Save.
Checkbox = saved with the form, or list multi-select.
Radio = 2–5 choices in a form. Segmented = 2–5 instant
views. More than five options → select or combobox. Checked state is always
--cd-primary — never cedar, never green.
Labeled switch rows — the one composition
Public siteVisitors can reach your site right now.
Search engine indexingApplies immediately — no Save needed.
Customer accountsInstall cedros-login to enable accounts.
Icon toggles — aria-pressed tool states
Pressed = accent fill + hairline inset — a standalone segmented trigger.
A working switch (0.55 opacity, wait cursor) must settle within ~1s.
Checkboxes — batched with Save · select-all indeterminate
Select-all at 2 of 3 — the indeterminate bar
Radio group — 2–5 choices in a form
Instant switches hidden behind a Save buttonone switch · labeled row · decision table
Components · 11 — menus & combobox
One menu behind every trigger
e2 surface, 4px padding, 2rem single-line items with a 16px icon
slot and a trailing kbd/state slot; checkbox and radio items for in-menu state;
destructive last, below a separator; disabled items stay focusable so a tooltip can say
why. No nested submenus — one level, or the IA wants a dialog. Max
20rem tall, then the list scrolls; at ten or more options the select becomes a combobox.
Anatomy — every item type
Page
Display
Combobox — pinned search at ≥10 options
bus|
zzz|
No matches — try a different term.
Multi-select uses checkbox items; the closed trigger summarizes
("3 selected", chips only when ≤2); selected items float to the top on reopen.
Keyboard: ↓ ↑ Home End, typeahead, Enter, Esc back to the trigger.
⌘K / Ctrl+K is the only entry — there is no topbar search. e3 panel at
~20vh, dialog entrance recipe; placeholder "Search sections, actions, and pages…";
groups Sections / Actions / Pages; ↑↓ move, Enter runs, Esc returns focus to where you
were. Empty: "No matches — Try a different search term." Extension sections appear
automatically from their manifest.
Components · 12 — cards, badges, chips
Structured surfaces, restrained depth
Default card
0.9rem 1rem padding · e1
Live
Header divider, body, optional footer. One subject per card.
Interactive
hover: −1px to e2
Draft
Fully clickable, not just the title.
Subtle well
4% wash, no shadow — secondary context.
Three jobs, three names
PublishedNeeds reviewPayment failedProcessingArchivedPublish dot — content lists only
Badge = read-only status (pill, tinted). Chip = interactive/removable
(filters, tags). Dot = compact publish state before titles in content lists —
tokenized --cd-success, never #16a34a. One status treatment per table, never two.
Setup-locked row — one labeled doorway
Status
Routine
Actions
Needs setup
Analytics reporter
A record-specific setup blocker replaces its unavailable control and
row menu with one outline CTA. Other actions disappear, blocked data mutes, and the
row keeps the neutral table surface. Page-wide blockers use one Setup notice instead.
Choice tiles — radio semantics, ring selection, no checkmark
Selected = border ring + 2px ring wash at 24% — nothing else. The
applied option wears a separate "Current" badge when applying is its own step.
2–6 options; beyond that it's a tile grid in a picker dialog.
Media tiles — the table's visual twin · same ring when selected
One button per tile (accessible name = the record's name); name
truncates, meta stays muted. Gallery / grid / list views toggle in the toolbar —
the list view is the standard table. Picker dialogs (680px) embed this same grid.
Components · 13 — dialogs & side panels
Decisions get focus without drama
One overlay (rgb(0 0 0 / .45), no blur), one panel
with a ✕ close, three widths, one animation (in 240ms, out 160ms ease-in). Long content
scrolls in the body between a sticky header and footer; a dirty form confirms discard
before closing; dialogs never stack. List-context detail uses the side panel instead.
.
Delete this form?
This deletes Contact form and its 214 responses from your site.
Removed from 3 pages that embed it
Response export becomes unavailable
This can't be undone
Three widths — nothing else
420 · confirms, short forms
560 · standard forms, uploads
680 · pickers, review
Header: title lg/600 + optional description + ✕ (icon-sm ghost,
disabled while an operation runs). Footer: ghost Cancel, then the verb button —
destructive confirms focus Cancel. Esc cancels; backdrop-click closes only when the
dialog holds no input; Enter submits single-input dialogs; type-to-confirm is
reserved for the catastrophic tier. Max height min(85dvh, 44rem).
Long content — sticky header & footer, body scrolls
maya@rodriguez.co Joined Mar 12 · 6 orders · #p_2214Last activity: form response, 2h ago. Cedra drafted a reply for review.
Slides in 220ms; Esc or backdrop closes (dirty-form guard applies);
the list keeps its scroll position. Panels never open panels — deeper work promotes
to a page.
Components · 14 — feedback & states
Status without wallpaper
Transient outcomes use the host-owned bottom-right stack —
.
Alerts are status tints; empties have three contexts and two visual weights; progress is honest — determinate
bars, step lists, one summary toast per batch, and never an indeterminate bar.
Inline alerts — status tints, --cd-warning-fg text
Import finished: 236 of 240 products added4 were skipped — see what happened.
Cedros couldn't publish this pageYour draft is safe. Try again — code pub_4t2c.
First-run empty — ambient two-tone glyph + copy + at most one action
No forms yetCreate a form to start collecting responses from your site.
The glyph is 64-viewBox stroke art:
base lines muted, one accent detail in --chart-5. It enters once
(220ms rise/scale) then drifts on the 5s ambient float — the one decorative
loop — and is simply present in reduced motion. Micro empty remains one muted
line: "No links yet."
Progress — determinate only, tabular label
62% · 148 of 240
Unknown duration = spinner or skeleton.
A bar parked at 90% is a lie, and lies are banned.
Step list — long work with live states
Validate file240 rows · 0 errors
Import products148 of 240 · you can leave this page — we'll keep going
Publish to site
Failure, expanded in place4 rows skipped — missing price. Fix the rows and retry; imported rows are safe.
Empty tables — first run vs filtered result
Theme
Version
Status
No marketplace themes yetSubmitted and published themes will appear here.
Theme
Version
Status
No themes match your filters.
First run spans every column and lets the table frame own the border;
filtered empty keeps columns and controls, but drops the icon and create action.
Toasts — one event, one transient outcome
Settings saved Applied to your live site.
Import needs review 4 of 240 products were skipped.
Page wasn't published Your draft is safe. Try again.
Bottom-right; six retained with the newest three collapsed; hover,
focus, or touch intent expands the stack. Stable ids update retries. Every tone
defaults to 4s; one optional verb action extends that to 8s; persistence is explicit.
Focus never moves here. Extensions publish through the host SDK and never mount a
toaster or ship toast CSS.
Install cedros-pay to add products,
subscriptions, and checkout.
You have view-only accessAsk an owner to make changes. Controls stay visible, disabled with this reason.
One setup notice per page, maximum. Driven by
requiredPermission / requiredExtensionId /
disabledReason — the same reasons the disabled nav shows.
Autosave chip — six states, one chip per save scope
Unsaved changesSaving…Saved just nowOffline — changes will syncConflict — review changesSave failed — retry
Text crossfades 160ms; role="status",
aria-live="polite". Failure escalates to the inline retry banner
(Retry / Discard) beside the work — never only a toast; a conflict opens its
review dialog. Explicit Save or autosave per page, never both.
Save changes before leaving?
You have unsaved changes.
The same leave guard runs everywhere a dirty surface can be abandoned —
dialog ✕/Esc, side panel, Back breadcrumb, nav, tab close (beforeunload).
Autosaving surfaces never ask; they save.
Components · 15 — furniture
The small parts, one way each
Tooltips are inverted and mandatory on icon-only controls;
pagination is one quiet row; avatars come in three sizes; disclosures hide configuration,
never status; stat cards count once and never loop.
Tooltip — inverted, 300ms hover / instant focus
Edit EAnalyticshover or tab — required on every icon-only control
Keyboard hints
⌘K palette Esc close ↵ submit ⌘↵ submit textarea
Back breadcrumb — canonical parent, one level
Above the title; use a link when People has
a route, a button only for ephemeral drill-in. Restore filters, page, and scroll;
never pair it with a multi-item trail.
Pagination — one quiet row
Showing 1–25 of 214…
Tables paginate; infinite scroll is for feeds only.
Avatars — 20 / 24 / 28 · stack −6px
MRDPSOMRDPSM+4
Disclosure — config only, never status
Advanced
Cache TTL, custom headers, and other expert knobs live here —
closed by default, chevron rotates 160ms, state persists per user per surface.
Metric tiles — neutral, attention, unknown
Visitors12,418▲ 8%vs prior 7 days
Pending review3Needs attention
Install latency—Not measured yet
Three tiles are the preferred overview
set. 0 is data; — is unknown.
Tone marks attention, not decoration. Eligible non-negative quantities count up for
500ms once; money, compliance values, reduced motion, and refreshes stay exact, and
screen readers hear only the final value.
Links
Inline links are
cedar, underline on hover; external links carry a
12px ↗; links inside table cells stay foreground with underline-on-hover so columns
read calm.
Reorder — grip drags, keyboard moves, a 2px line marks the drop
Home
Menu · picked up, e2
Contact
Space/Enter picks up, ↑↓ moves, Esc cancels — announced politely
("Picked up Menu. Position 2 of 3."). Short lists may use the ↑/↓ button pair
instead. Order persists automatically: "Changes save automatically."
Inbox & activity rows — unread is a dot + weight, never a tint
Form response · Contact"Do you offer wholesale pricing for cafés?"2h ago
Cedra drafted a replyWaiting for your review before sending.2h ago
Import finished236 of 240 products added.Yesterday
The quiet list for streams (form inbox, completed AI work) — hairline
separators, accent hover, whole row activates, relative time with absolute on hover.
Feeds are the one surface where infinite scroll is allowed; tables paginate.
Composition · 16 — dashboard contribution cards
Current state, direction, then one doorway
A polished extension contribution is an operational summary,
not a row of inventory counters. It answers one recurring question in five seconds:
what owns this space, whether anything is wrong, the primary value and window, the
direction on a like-for-like comparison, and the one place to act. One–three metrics
lead; one evidence region earns the rest of the space.
Five equal counts · repeated zeroes · no period · decorative chart1–3 decisions · explicit window · honest delta · one evidence region · one action
Polished contribution specimen · illustrative data
Fleet Manager
Fleet health and control-plane activity.
Degraded
Managed sites66Right now
Availability▲ 0.4 pp
95.5%63 of 66 · vs prior 30 days
Open incidents+11 open
2263 opened · 52 resolved
Incident movement2-day buckets · Jul 21–Aug 19
Incident movement in two-day buckets from July 21 through August 19
Bucket start
Opened
Resolved
July 21
1
0
July 23
2
1
July 25
1
2
July 27
3
1
July 29
2
3
July 31
4
2
August 2
3
4
August 4
5
3
August 6
4
5
August 8
6
4
August 10
5
6
August 12
7
5
August 14
6
7
August 16
8
5
August 18
6
4
The status is threshold-backed, not decorative. Availability is a
rate with its numerator/denominator and percentage-point comparison; open incidents
are a stock with absolute movement; the chart shows flows opened and resolved. The
production interaction gives pointer, touch, and Left/Right/Home/End access to the
same values. This specimen also includes the required screen-reader data table even
though the visible chart stays compact.
The visual chooser
Sparkline
Direction beside one KPI · 8–30 points
Line / step
Stock, rate, duration · ≤2 series · ≤60 points
Bars
Flow by bucket · 7–31 buckets
Stack
Composition · 2–4 stable categories
Rows
Next exceptions · 3 maximum
No pie/donut, gauge, radar, dual axis, 3D, map, heatmap, or
decorative area chart in a dashboard contribution. Specialized analysis belongs
on the extension page.
Configuration boundary
Card-owned
Useful preset window; rarely 2–3 series toggles
Host-owned
Reorder · show/hide · size, when the host exposes them
Chart type · color · smoothing · axis · bucket density
Every view states its window and source freshness. Range changes
are immediate view state: keep the previous plot, mark it busy, and swap without
replaying first-paint motion. Refresh failures retain last-good data, identify the
failed refresh, and become stale only after the declared maximum age.
Expression · 17 — charts
Series one is cedar. No gradients.
Hairline horizontal grid only; 2xs tabular sans
labels; direct labels beat legends; tooltips are e2; one draw-in ≤500ms, then values
crossfade; area fills are the series color at ≤12% opacity.
Decorative gradients and unrelated categorical huesseries 1 = --cd-link · status tokens for semantic series · flat fills ≤12%
Line — direct label, last-dot only
Bars — one hue, muted comparison
Empty chart = flat hairline at zero + one
micro-empty line — never an unlabeled sample. Specialized viz (the visitor globe) is
palette-exempt, but its chrome consumes tokens like everything else.
Expression · 18 — voice
A capable colleague, in sentence case
Plain, confident, warm, specific, calm. The user is "you"; the
system is "Cedros". Delete is permanent · archive is recoverable · uninstall is for
extensions · extension, never "plugin". Formulas: page subtitle = verb + object +
the capability that matters (≤60ch); card description = one sentence of
consequence; empty = what → working state → one action; errors = what happened → your
stuff is safe → next step (+ mono ref).
Weak
Standard
"Manage Your Pages Here!"
Pages — Manage site pages with revisions, preview, and publish state.
"An error occurred while fetching data."
Cedros couldn't load your pages. Try again — code pg_2f1c.
"Successfully Created New Page!"
Page created — Undo
"Are you sure?"
Delete this page? It's removed from your site and navigation. This can't be undone.
"Feature unavailable."
Install cedros-pay to enable Products. + [View extensions]
"Loading data, please wait…"
(skeleton) then, past 1s: "Importing 240 products…"
Expression · 19 — motion
Same tokens as the brand — felt, not watched
Durations 100 / 160 / 200 / 220 / 240 / 400 / 500 / 800ms, expo-out
entrances, ease-in exits at ~70%. A table may reveal its rows once per browser
document: rise 8px over 220ms with 45ms between rows. Every row takes part, and the turns
are budgeted across the rows on screen rather than the full row count — otherwise a
500-row table spends its whole cascade on rows nobody can see and the visible ones arrive
in a single flash. The cascade lands inside 500ms; rows below the fold share the last turn
and settle before you can scroll to them. Back navigation, sort, filter,
refetch, and route changes stay instant. Hover a card to replay its recipe.
Menu enter
180ms · scale .97 + y −4hover to replay
Dialog enter
240ms · scale .98 + y 8hover to replay
Toast rise (bottom-right)
400ms · y 100% + .98 · exit 200mshover to replay
Saved
Row update flash
800ms · info 22% → 0hover to replay
Order #2214Processing
Expression · 20 — access & reduced motion
Non-negotiables
Focus doctrine — visible when it helps
Style
:focus-visible, never :focus. Clicking must not leave a ring;
tabbing must always show one. Tab through this board—every control demonstrates the
same quiet ring.
ring: 0 0 0 3px ring/14%, instant
The floor
WCAG 2.2 AA both modes ·
keyboard parity (roving tabindex in tabs/menus/tables) · targets ≥24px, ≥32px in
dense rows · color never the only signal · 11 locales via catalogs, RTL-ready ·
prefers-reduced-motion collapses every duration to 1ms and stops the
shimmer and spinner — this board obeys; turn it on and reload.
Integration · 21 — extensibility
Built to grow without changing character
Extension admin pages mirror the host class + ARIA
contract on --cd-* tokens — no private component imports, no own
dark mode, no hardcoded motion, sentence case throughout. The full contract is
design-admin.md §11; registration mechanics live in
docs/extension-authoring/12 + reference/admin-ui-patterns.md.
root = my-ext-admin cedros-data + data-extension-idbridge var(--cd-x, fallback) — never re-declare host tokensself-inject one id-guarded <style>host classes first · BEM namespace · scoped selectorsmotion via --motion-* · icons via manifest Lucide nameshost toaster only · never mount an extension queue0 ≠ unknown · first-run empty ≠ filtered emptyown dark class · prefers-color-scheme · --cedros-runtime-* in admin
Root, bridge, and injection — the whole recipe
<div class="loyalty-admin cedros-data"
data-extension-id="cedros-loyalty">
…your page, built from the §11 class contract…
</div>
/* consume host tokens; never re-emit them */
.loyalty-admin {
--loyalty-accent: var(--cd-link, #2F6C7D);
}
/* self-inject once, id-guarded; ?inline must
resolve nested @imports so every rule ships. */
import css from "./admin.css?inline";
const ID = "loyalty-admin-styles";
if (typeof document !== "undefined"
&& !document.getElementById(ID)) {
const tag = document.createElement("style");
tag.id = ID;
tag.textContent = css;
document.head.appendChild(tag);
}
An extension page renders native
Loyalty
Reward repeat customers with points and perks.
Members1,082
Points issued48.2k
Redemptions312
Connected to PeopleNew customers earn points automatically.
Every element above is a host pattern — nothing custom but the data.
Dashboard cards ship the full state matrix (loading skeleton · micro empty ·
error status with retry · capability-locked with reason) or they're not done.
Reference · 22 — theme blueprint
Workbench at a glance
The complete brand signature in one scan. The order this page
follows — identity → principles → foundations → composition → components → expression →
integration → reference — is the narrative every Cedros theme overview uses, and this
pair is the format's reference implementation.
Theme facet
Workbench expression
Promise
Calm structure for consequential work
Audience
Operators · owners · editors · support teams · extension authors
Personality
Neutral · precise · quiet · durable · capable
Inspiration
shadcn restraint, translated into Cedros' dense operational workspace
Palette
Neutral surfaces · four semantic outcomes · cedar links and data only
Typography
Eight sans roles · sentence case · mono only for identifiers
A cohesive theme story, realistic specimens, both modes, concise
brand guidance, and a source-ready marketplace preview.
Marketplace boundary: today, a Cedros theme manifest's
preview points to a root-relative static image (3:2 recommended). This
HTML page is the canonical source preview for future ingestion; until that support
ships, capture the cover composition at the top of this page as the image and do not
invent an unsupported manifest key.
Page deleted
Publish 3 pages?
Home, Menu, and Contact go live on cabrillo.coffee right away. You can unpublish any of them later.