Fabrication AI

Design System

Tokens, components, and patterns for building Fabrication AI, grouped by type and searchable. Built on Coss UI (Base UI + Tailwind v4) with our design tokens and Lucide.

Foundations

Atomic design tokens from @fabrication-ai/ui/styles/tokens.css. Always consume them via Tailwind utilities (bg-primary, text-muted-foreground, font-heading, rounded-lg). Never hardcode values.

neutral-100 · neutral-950 + white
neutral-800 · neutral-100
white · background + white
white · neutral-800
neutral-800 · neutral-100
neutral-50 · neutral-800
black/4% · white/4%
black/4% · white/4%
neutral-500 + black · neutral-500 + white
black/4% · white/4%
black/10% · white/10%
black/10% · white/16%
neutral-400 · neutral-500
red-500 · red-500 + white
blue-500
emerald-500
amber-500
Colors

Headings: Geist (font-heading, auto-applied to h1-h6)

Operate with AI you can trust

Body & UI: Inter (font-sans, the document default)

The default paragraph size for prose and UI copy.

font-mono · const loop = ground(answer)

Logo only: Space Grotesk (font-display)

Fabrication AI

Typography
Radius
Shadows

Lucide icons

One icon family across the product. Outlined icons with a 2px stroke, currentColor, and existing control sizes. Import IconGlyph and named glyphs from @fabrication-ai/ui/icons.

Overview
Projects
Graph
Ontology
Settings
Sidebar
Product mappings
2px · UI default
3px · small selection indicators
Stroke width
16px18px24px
Sizes and accessible controls

Twin visual system

The animated geodesic 'digital twin' and its building blocks. GeodesicSphere is a power-aware Canvas 2D renderer that pauses while hidden or idle; TwinGlyph/TwinAnchor/ProductMock compose it; ThreadMarker/HudCallout/RevealWord/TwinPlayer are its supporting UI. From @fabrication-ai/ui/graph.

Hero

A large, expressive entrance that still auto-rests.

High density · Auto-rest · Classic orb

Section

A decorative waypoint for a marketing section.

Balanced density · Auto-rest · Classic orb

Anchor

A compact, already-drawn mark that moves only when asked.

Low density · Move on interaction · Classic orb

Agents

A resting product state that communicates connected agents.

Balanced density · Move on interaction · Connected agents

GeodesicSphere presets

Start with a use case

Choose the closest role, then refine only what the design needs.

Motion behavior

Choose when the orb spends energy drawing new frames.

Visual state

Pick the idea the orb should communicate—not merely how it should look.

Mesh density

Match complexity to the rendered size; more detail is not always better.

Experience

Decide whether people can manipulate it and how it first appears.

Fine-tune size and speed

Most designs should keep the preset values. Adjust these only to fit a specific composition.

What this configuration does

This high density orb shows the classic geodesic twin. It gently spins and automatically comes to rest. It is open to drag and tap and draws itself in when it first appears.

Balanced activity
Drag to rotate · tap to pulse
Implementation props

The labels above describe design intent; these are the corresponding component values.

<GeodesicSphere
  detail="full"
  motion="ambient"
  mode="idle"
  radiusFactor={0.36}
  spinSpeed={0.11}
/>
GeodesicSphere playground
Choose the story

The tags should name the three ideas reinforced by the neighboring section copy.

Composition

Keep the labels facing inward, toward the message they support.

Visual scale

Size the companion to the space around it, not the headline.

Company intelligence

See what the business believes.

The twin connects objectives, decisions, and evidence so every team can work from the same reality.

Desktop companion

The glyph intentionally steps aside on smaller canvases.

Keep the section copy and calls to action; reveal this decorative composition at the xl breakpoint.

Decorative section companion · three short labels · desktop only

One supporting idea

Use one glyph beside one section message, never as page furniture.

Meaning stays in the copy

TwinGlyph is aria-hidden; the neighboring text must stand alone.

Reserve horizontal space

Labels extend outside the orb, so keep the complete motif in its own column.

Implementation props

Render this inside a desktop-only column; the section owns the responsive fallback.

<TwinGlyph
  tags={["objectives", "decisions", "evidence"]}
  tagSide="left"
  className="size-40"
/>
TwinGlyph — section companion
Type
Color

Generating design options…

Exploring layouts, type pairings, and semantic color tokens.

<BorderBeam size="md" colorVariant="colorful" strength={0.86}>
  <Card>Content</Card>
</BorderBeam>
BorderBeam

Liquid Metal

The 'act here' signal: MetalFx wraps the one button or input a surface most wants the user to act on and paints an animated WebGL metal chrome over it (vendored from metal-fx). Interactive elements only, one per surface — metal drives the click, while the border beam (AiBeam) means AI is working; the two never swap roles. It normalizes the child's own border/background so the metal becomes the visible chrome, while the child keeps focus, typing, and a11y. Every instance shares one GL context — and one preset: the last-rendered instance's preset wins page-wide, so all examples below follow the playground's preset.

Variant
Preset
<MetalFx variant="button" preset="chromatic" strength={0.90} theme={theme}>
  <Button variant="secondary" className="rounded-full px-6">Upgrade to Pro</Button>
</MetalFx>
MetalFx playground
Buttons — wrap the existing Button primitive; MetalFx strips its border/background so the ring is the chrome.
Inputs — size the MetalFx wrapper (the child fills it); the field keeps focus, typing, and a11y.

Motion

How Fabrication AI moves: the principles every animation must pass, the shared easing/duration tokens, and the AI activity beam. Distilled from Emil Kowalski's design-engineering skills — see the linked repo for the source material.

1 · Motion must earn its place

Every animation answers “why?” — feedback, state, spatial continuity, or preventing a jarring change. Frequency sets the budget: actions hit 100+ times a day (keyboard shortcuts, command palettes) get no animation; occasional UI (modals, toasts) gets the standard treatment; rare moments (first-run, success) may spend delight.

2 · Easing has a decision order

Entering or exiting → (start fast — use the strong curves, not the weak built-ins). Moving/morphing on screen → . Hover/color → . Constant loops → . Never ease-in on UI — it delays the exact moment the user is watching.

3 · Product UI stays under 300ms

Press feedback (120ms) · dropdowns, toasts, panels (200ms) · modals, drawers, shell chrome (300ms). Marketing reveals may run 400–900ms (//) — product UI never borrows those tiers.

4 · Physical and interruptible

Nothing appears from — enter from 0.95–0.97 + fade. Popups scale from their trigger (); only centered modals are exempt. Anything reversible or rapidly re-triggered uses transitions (they retarget mid-flight), never keyframes; gestures use springs that keep the release velocity.

5 · Animate transform and opacity only

/// trigger layout every frame, and is never allowed. Tailwind v4 note: / set the native / properties, so transition lists must name them — , not .

6 · Reduced motion means gentler, not zero

Under , keep the opacity/color feedback and drop the movement: variants in CSS, (or ) in Motion code. Ambient loops stop; beams freeze to a static glow — the state signal survives.

Principles — every animation must pass these. Source: Emil Kowalski's skills (linked).
[0.22, 1, 0.36, 1]Signature entrance easing (easeOutExpo) — enter/exit motion
[0.165, 0.84, 0.44, 1]Gentle float/hover settles; slide-in overlays
[0.45, 0, 0.55, 1]Looping ambient motion
0.12Button/press feedback
0.2Dropdowns, toasts, panel transitions
0.3Product ceiling: modals, drawers, shell chrome
0.4 / 0.6 / 0.9Marketing reveals only — never product UI
cubic-bezier(0.23, 1, 0.32, 1)CSS utility (tokens.css) — deliberate enter/exit in class strings
cubic-bezier(0.77, 0, 0.175, 1)CSS utility (tokens.css) — on-screen movement in class strings

JS tokens from ; CSS utilities register in . returns the standard marketing reveal, opacity-only under reduced motion.

Motion tokens — from @fabrication-ai/ui/motion (JS) and styles/tokens.css (CSS). Never hand-type a curve or duration.

The border beam is the product's AI activity signal: a beam on a surface means AI is active there, right now. Declare intent with — never decorate idle UI with it, and never compose by hand in product code. When a request starts, the input's pulse hands off to the destination surface's rotating beam.

Surface

Drafting the research plan…

Streaming panels, task cards, list rows.

Input

Focus = ready pulse (“AI is listening”); send = the working beam.

Trigger

Hover arms it; click shows “AI heard you” until the destination surface takes over.

AiBeam — compose beams through AiBeam in product code, never BorderBeam by hand.

Buttons

Coss Button: the single button primitive. Navigating CTAs use the render prop: <Button render={<Link to='/x' />}>.

Variants
Sizes
With icon · loading · disabled

Form controls

Inputs, selection controls, and labels. Pair every control with a <Label> for accessibility.

Text fields

Type, or press the mic to dictate.

Search
Checkbox · Switch
Radio group · Select

Data display

Badges, avatars, cards, separators, skeletons, and progress for presenting content and state.

defaultsecondaryoutlineinfosuccesswarningdestructive
Badges
OLAK
Avatars
Grounding accuracy
Across the last 14 days of agent loops.
+2.4%

98.6%

x
Loop activity
How agents used grounded context this period.

Runs

184

Sources used

1,248

14 days

Cards should always sit on a background surface unless an exception is explicitly applied. The card edge is four stacked hairlines on the foreground token — light mode: top foreground/5, sides foreground/10, bottom foreground/15; dark mode inverts it (top foreground/25, sides foreground/15, bottom foreground/10). On interactive cards, hover doubles each line's opacity.

Card
Docs Tickets Code
x
Separator · Skeleton · Progress

Feedback

Alerts, tooltips, and spinners for communicating status.

Alerts
Tooltip · Spinner

Hover a beacon for guidance. The first mark coaches everyone; the other two are audience-gated — switch persona to see them swap.

Coach mark
Toast

Empty states

The designed absence of content, and often a feature's first impression. Every empty state orients (what belongs here), motivates (why it matters to this person's job), and activates (one obvious next step). EmptyState's required kind prop picks the right design: first-use invests, cleared celebrates, no-results recovers. Full copy rules live in docs/DESIGN.md.

Product lead

Shapes what gets built

Turns a one-line idea into a reviewed, evidence-backed spec the team can commit to.

Research that runs while you work

Give the agent a topic and each run streams in here, grounded in the twin.

Value-prop carousel: EmptyStateCarousel teaches who the tool serves and the job it does. The focused card reads; neighbors ghost. Hover for chevrons, click a ghosted card to focus it, swipe on touch; hovering pauses the auto-cycle.

See what your company believes

Connect a source and every claim your agents make gets grounded against it. Drift shows up here the moment it happens.

First-use: an onboarding moment. Outcome-led title, faded preview of the populated state (EmptyStatePreview), one strong primary action.

Review queue cleared

Every drifted claim has been re-grounded. New drift lands here the moment it's detected.

Cleared: the user finished everything. A small win, not a broken screen. The media tile takes the success tint automatically; actions stay quiet.
Enterprise churn is driven by onboarding time
EU expansion pays back within 18 months
Support tickets predict renewal risk

Type something that matches nothing to hit the no-results state. The recovery action is the way out.

No results: a dead end needs an exit. Echo the query back, suggest the likely fix, and always offer recovery. Announces via role="status".

1 · Orient, motivate, activate

Every empty state says what belongs here, why filling it is worth the effort, and gives one obvious next step. Anchor on the value the user came for, never the mechanics of the feature.

2 · Three kinds, three designs

is an onboarding moment: invest in it. is a small win: acknowledge it. is a dead end: always hand the user an exit. The prop is required so the choice always gets made.

3 · Lead with the outcome

“See which claims drift off-source” beats “Your dashboard is empty.” Write for the specific persona and the job they're accountable for, in their vocabulary; an empty state written for “the user” is written for no one. Short sentences, plain words, and never an em-dash.

4 · One primary action

Exactly one Button; everything else looks secondary ( / / ). The empty moment is when the user has the least context, so don't hand them a menu. And always give the empty state its own action, even when the page header offers the same one.

5 · Never guilt, never apologize

“You haven't added anything yet” blames the user; a gray “No data available” reads like an error. Describe the opportunity, and make the state look intentional so it's never mistaken for a bug or a loading failure.

6 · Show, don't tell

People understand a feature by seeing it filled in: use with skeleton rows or miniature real components on first-use. Match tone to the moment: warm for first-use, brisk for no-results, a quiet win for cleared.

Principles + the shipping test: does this tell a specific person what belongs here, why it matters to their job, and exactly what to do next?

Overlays

Coss Dialog (on Base UI) handles focus trapping, scroll lock, and Escape. DialogPopup is self-contained.

Dialog
Dropdown menu
Popover

Loaders

Loading indicators for async states — motion SVG spinners, pulse skeletons, terminal cursor, text shimmer, and the ThinkingOrb thought-orbs for AI/agent work (talking to the graph, fetching company knowledge, generating).

State
Size
import { ThinkingOrb } from "@fabrication-ai/ui/loaders";

<ThinkingOrb state="working" size={64} />
Thinking orb playground
Adding new context to the graphstate="working"
Searching across the graphstate="searching"
Updating a node in the graphstate="solving"
Generating nodes to build out the graphstate="composing"
Inside a pill (e.g. an AI input talking to the graph)
Working…
Searching…
Solving…
Composing…
Working…
Searching…
Solving…
Composing…
Graph activity → orb
Morphing infinity
Dash ring
Loading skeleton
LoadingLoading
Terminal

Grounding in company knowledge…

Text shimmer
Thinking orb — working
Thinking orb — searching
Thinking orb — solving
Thinking orb — listening
Thinking orb — composing
Thinking orb — shaping

Surfaces

Background treatments for pages and sections. DotGrid is a canvas-style dot grid (foreground dots, theme-aware opacity, edge fade, cursor-reactive squares) — drop it into any relative container.

<DotGrid />
Dot grid
Scroll area

Logos

Brand mark and lockups from @fabrication-ai/ui/app. LogoMark is the glyph alone; Logo composes mark + wordmark as a horizontal (default) or stacked lockup. Uses text-foreground / currentColor for light and dark. Size with sm / md / lg; stacked marks are 50% larger than horizontal. Pass compactOnMobile to hide the wordmark below md (mark-only in compact headers). Override the wordmark string for site-specific brands (e.g. design system).

The hex-nut mark is a placeholder drawn from a single path in @fabrication-ai/ui/brand, which also produces the favicons, app icons and preview tiles. The shared typography, surfaces, and components are the base system; approved brand artwork can replace the mark without changing component APIs.

Brand foundation
LogoMark
Fabrication AI
Fabrication AI
Fabrication AI
Horizontal lockup
Fabrication AI
Fabrication AI
Fabrication AI
Stacked lockup

Wordmark hides below the breakpoint — resize the viewport to see mark-only on small screens. Used in the marketing navbar.

Compact on mobile

Override the wordmark for site-specific brands. The design-system header uses this with .

Custom wordmark

App shell

Config-driven building blocks for the logged-in product shell. The WorkspaceSwitcher reads workspaces and routing from the app-shell config (or props) and stays on the current page when you switch. See every full-shell layout — live and walkable — in the App shell layouts gallery.

Preview every configuration and page template on a dedicated page — each a live, walkable, responsive instance with guidance on when and where to use it.

View app shell layouts
All app-shell layouts
Workspace switcher

Patterns & guidelines

Conventions for composing pages and the standards we hold to, so new work stays aligned with the system.

Application shell

App pages live under inside : a collapsible left sidebar (workspace switcher → Company/Workbench tab → nav → notifications → profile), a sticky frosted header, and a right help panel. The shell mounts once; pages render through the .

Page template

Build every app page with — it owns the container width, the page title, and the / slots. is the title-only placeholder built on top of it.

App headings

Headings inside the app use with no negative letter-spacing — Geist already has the right spacing, so don't add . Reserve Semibold for emphasis, not headings.

Cards

Keep the outer border, but no divider lines inside a card. Separate a card's header, body, and footer with padding and spacing — never an internal /.

Toasts

Use () for async results that aren't otherwise visible (saved, invited, deleted) and for non-blocking errors; pair reversible actions with an . Don't toast immediate UI feedback, validation (show inline), or blocking flows (use a dialog).

Empty states

Build every empty surface with and the right : invests (preview + one primary action), celebrates, and always offers recovery. Lead with the outcome, never guilt the user, and pass the test: what belongs here, why it matters to their job, what to do next.

Motion

Product UI animates with and the tiers (never over 300ms); marketing reveals use and . The shell plays its intro once on load; navigating between tabs has no transition. Full rules, tokens, and the source material link live in the Motion section above.

AI activity beam

A border beam means AI is active there, right now — on the surface where it streams, the input that drives it, and the trigger that starts it. Compose through ( + /), never by hand, and never decorate idle UI with it.

Liquid Metal

Liquid Metal () marks the one element to act on — the premium CTA or prompt bar a surface is built around. Interactive elements only, one per surface, and never a state signal: metal drives the click; the beam shows AI working — the two never swap roles.

Mobile

Below the shell keeps the sidebar but switches to a push: opening a panel slides the page off-screen (dimmed + scroll-locked); the sidebar pushes right, the help panel pushes left. Tap the page to close.

Keyboard shortcuts

Register power-user keys in (the source for the help dialog, opened from the profile menu): then / switch elevation, toggles the sidebar, the help panel, opens the list.

Marketing pages

Wrap content in (adds the shared ) and lead with . The marketing surface uses the cream hero on white sections; the global renders once in .

Buttons & navigation

Use the Coss for every CTA. For links, pass a router Link to : . Map primary→, subtle→.

Icons

Lucide only. Import glyphs and from . Use a 2px stroke and semantic colors. Icon-only buttons need an accessible name; decorative glyphs are hidden from assistive technology.

Tokens & type

Tokens live in . Body = (Inter); headings (h1-h6) = (Geist); logo = (Space Grotesk). Consume colors via utilities, never hex.