Theme — Asteroid Design System

Asteroid Design System

Component kitchen sink and token reference

Colors

Semantic tokens — OKLCH color space, light & dark mode

Surfaces

Brand

Status

Typography

Two voices — InterVariable for UI, Freight Big Pro for brand & editorial. IBM Plex Mono for coordinates.

Voice 1 · UI · Inter

The operator's console.

Dense UI — tables, forms, buttons, labels. ~95% of the platform and all landing supporting copy.

The quick brown fox jumps over the lazy dog. 1,284 executions completed in 3m 42s average.

Voice 2 · Brand & Editorial · Freight Big Pro

Build agents that run the web.

Landing hero & section titles. In-product hero moments, empty states, onboarding, quotes. One expressive voice across both surfaces.

“A polished power tool that doesn't intimidate.”

Coordinate · IBM Plex Mono

Not a voice — a coordinate system. Identifiers, versions, model slugs, metadata k:v pairs, cron expressions, URLs & paths, raw enum values, and tabular numerics. Where precision beats emotion. Use <Mono> from @workspace/ui/components/mono outside of DataTable (which has meta.mono).

Mono

92890146v3gpt-5claude-opus-4-7-thinking*/5

Not mono

Platform type scale — Inter

Editorial tier — Freight Big Pro (use sparingly)

In-context example — empty state

Executions

Nothing to see here — yet.

Kick off your first agent run and this page will fill up with the interesting stuff.

Start an agent

Serif headline + Inter supporting copy + mono overline. The three voices playing together.

Buttons

Button face is lifted from flow, shadow at flow position — sinks on hover, presses on active.

Variants × Sizes

variant \ size sm default lg
default default default default
destructive destructive destructive destructive
outline outline outline outline
ghost ghost ghost ghost
link link link link

With Icons

Icon Only

States

Common Patterns

My Agents

Iconography

Icons are a supporting voice — they reinforce an affordance or classify a type. Four working sizes, six semantic colors, and a strict anti-pattern list. See DESIGN.md §Iconography for the canon.

Size scale

Four working sizes carry 99% of the system. size-3 is not canonical — it survives as drift. size-6 is reserved for rare page-header chrome.

In buttons

Button hands every nested icon size-3.5 and gap-1.5. Never pass size-* or mr-* class overrides.

Create Download Refresh Delete Small Large

In tabs

TabsTrigger size="default" and ChromeTab use size-3.5. size="lg" steps up to size-4 because the tab IS the page title.

size default
lg Profiles

In entity and stat cards

Entity full-tile (size-9) holds size-4; compact (size-7) holds size-3.5. Stat card header icon is size-3.5, right-aligned in the muted label row.

Do

Don't

Color canon

Icons inherit currentColor. Use semantic tokens. Never text-green-600, text-red-500, and friends.

Empty state hero

EmptyMedia variant="icon" renders a size-10 muted tile around a size-8 icon. Do not pass a size class on the icon itself.

No agents yet.

Create your first agent to start running workloads.

Create agent

Inputs with a leading icon

No built-in SearchInput primitive yet — use an absolute size-3.5 Search icon with muted foreground and pad the input to match.

Anti-patterns

Button Groups

Grouped actions with shared offset shadow.

Horizontal — outline

Left Center Right

Horizontal — alignment

Vertical

Top Middle Bottom

With Text & Separator

Page 1 of 10

Save

Cancel

Variant groups

Default Group

Destructive Group

Badges

Tinted backgrounds with colored text — quiet labels, not loud fills.

Variants

Status — filled, distinct from brand colors

Admin Indicators

The affordance IS the signal — admin elements paint themselves amber. Badge stays as the page-header chip and the fallback for elements that already carry color. See DESIGN.md → Admin Indicators.

Token

--admin

Solid amber. Use on raised admin buttons; rarely as a surface.

Agents

My org All orgs

Cross-org agents visible — internal toolbar above

Toggle Admin mode for this preview Admin mode

Admin PageGate (toggle-off interstitial)

Admin mode is off

You turned Admin mode off — internal tools are hidden so it's safe to demo. Re-enable to view this page.

Enable Admin mode

Tabs

Chrome-style tabs — active tab uses bg-background against a muted bar surface, with inverted SVG corners.

One Chrome-tab visual

Two component APIs for different semantic models. Both render identically — pick based on what the tabs represent, not how they should look.

Default framed look — Tabs / ChromeTabs

The canonical chrome-tab visual: transparent strip, active tab with border + stroked inverted corners, content panel with full border +rounded-b-lg, and one shared drop-shadow over the whole tongue-card silhouette. Both Tabs and ChromeTabs default to framed; the panel border auto-paints so consumers don't repeatborder border-t-0 rounded-b-lg. Suppress the drop-shadow when the strip and workspace can't share a DOM subtree (agent header pattern) via framedShadow={false}.

Tabs framed (sub-navigation, on bg-light-muted)

ChromeTabs framed (one shared drop-shadow)

To pick up a draggable item, press the space bar. While dragging, use the arrow keys to move the item. Press space again to drop the item in its new position, or press escape to cancel.

Modals

One shell, four sizes (sm / md / lg / full), five fixed slots: header → optional persistent identity strip → optional tab strip → body → footer. Tabbed modals share the chrome-strip + chrome-tab pattern with §Page shell — a modal-with-tabs is structurally a tiny chrome page. See DESIGN.md §Modals for the canon.

Confirm

sm · 448

One question, one answer. Destructive footer: outline-Cancel + destructive primary with the verb spelled out.

Open confirm

Form

md · 672

Single-purpose form. Header description carries the intent; FieldGroup runs the body; Cancel + Save in the footer.

Open form

Tabbed

lg · 896

The canonical shape: header → persistent identity strip → chrome tabs → body → footer. Mirrors §Page shell tabbed pages.

Open tabbed modal

List-pick

md · 672

Search + scroll + multi-select inside a DialogBody. The toolbar pins to the top, the list scrolls, the count summary lives in the footer.

Open list-pick

Loading + error

md · 672

Same shell, two states. Loading uses skeleton inside the body. Blocking errors are an in-body banner — never a toast.

Open states

Right-action + split footer

lg · 896

The Run Agent shape: Pre-fill Select sits in the header right-action slot; Schedule and Advanced cluster left in the footer; Cancel + Run cluster right.

The four sizes

Form Elements

Text Inputs

Agent Name

Search

Disabled

Input + Button combinations

Go

Send Invite

Cards

Content containers with header, body, footer

Agent Performance

Success Rate

Active Agents

New Agent

Stat cards

Compact metric tiles — label + icon, value, helper. Used on /overview and /executions and reserved for future summary strips (billing, usage, scheduled). One row, 3 or 4 tiles, top of page.

Anatomy

Strip — 4 tiles · /overview

In progress

Agents

Strip — 3 tiles · /executions

In progress

Loading — full strip skeleton

Future use — billing strip (same shell, different content)

Entity cards

How a domain entity (Agent Profile, Integration, Notification, API Key, Schedule, …) renders anywhere in the platform. The same identity — icon, name, type, meta — at three densities: full on index pages, compact in side panels and drawers, and chip as an inline reference with a popover. Detail lives in a vertical stack of named body sections — and only those sections — so two cards for different entity types still read as members of the same family.

Anatomy — full variant

Webhook

Edited 2m ago · Created 15m ago

Variants — full / compact / chip (hover the chip)

Full

My Webhook

Edited 2m ago · Created 15m ago

Compact

My Webhook

Chip + popover

Body grammar & footer — six body sections plus the audit footer

Every full or popover body is a stack of named sections. Picking from this set is mandatory; ad-hoc divs in an entity body are out. Two densities of PropertyList for key/value, four cluster sections for everything else.

PropertyList density="grid"

PropertyList density="inline"

PillRow

DividedList

REPLY

DividedList (editable, with actionSlot)

REPLY

Monitoring: Execution Completed Execution Failed Execution Started +4 more

EmptyRow

EntityCardFooter (default)

EntityCardFooter (showCreated)

Composed example — three sections in one body

The same shell with a stacked body. Sections sit at space-y-4; headers and content within a section sit at space-y-2.

Production webhook

Chip references — hover or click to expand

Chips are entity references inside other content (table cells, log lines, toasts, breadcrumbs). Identity only — icon, type, name. The popover shows the entity's compact card plus an allow-listed subset of body sections, and a footer link that opens the entity in a new tab.

## Page shells

Two underlying surface modes — canvas (used by Plain, Hero, and Start) and chrome (used by Tabbed and Detail) — produce the platform page shapes. Canvas pages get a bg-light-muted well with bg-card surfaces lifting off it. Chrome pages drop the canvas and let a bg-sidebar strip + tabs sit directly above a single bg-background content panel — the active tab is the only seam between chrome and content. Sidebar carries the page label; the title slot is reserved for the active tab (Tabbed/Detail), the editorial composition (Hero/Start), or nothing at all (Plain).

Anatomy — canvas mode vs chrome mode

Chrome mode · Tabbed & Detail

The core shell shapes

Page has… Title slot Subtitle slot Examples
Tabs Drop. Tabs are the identity. Drop. Use InfoCard inside tab content if needed. Agent Profiles, Admin → Models / Usage
Editorial hero Drop. Hero replaces it. Drop. Hero supporting copy carries it. Overview
Start composition Drop. Split editorial prompt replaces it. Drop. Primary composer and rail copy carry the context. Create / get started
Custom resource header Resource name · dynamic content Drop. Agent, Execution, Batch detail pages
Plain top-level route, no tabs Optional. Prefer dropping — sidebar already says it. Optional. Treat as a smell. API Keys, Integrations, Manage Users

Tabs — pick the API by semantic, not by look

Both render the same chrome-tab visual — same surface, same shoulder, same inverted corners on the active tab. The split is about what the tabs mean, not how they look.

Create / Start Surface

The Start page shape: a canvas-first decision surface for creating an agent, onboarding a user, or choosing a first workflow. One editorial composition may span the primary composer and the supporting template rail, but everything below returns to compact Inter UI.