Design language
The look follows Stripe's dashboard: a white canvas, structure from type, whitespace and hairlines, colour only where it means something, and motion that answers the pointer at once. The one deliberate difference is the primary colour: teal wherever Stripe uses purple.
Greys
Stripe's neutrals carry almost everything: text, borders, surfaces.
gray-0#ffffffCanvas, cards, popovers
gray-50#f6f8faSidebar, subtle surfaces
gray-100#ebeef1Muted fills, hover
gray-150#d8dee4Borders and hairlines
gray-400#87909fField underline, inactive icons
gray-500#687385Secondary text
gray-800#30313dPrimary text
gray-900#1a1b25Toast background
Status: one meaning per colour
A status is a badge — a light fill and dark ink of one hue — plus the word. Never colour alone.
ApprovedFinished, succeeded
In reviewIn progress, or waiting on someone else
Needs actionYou must act, or it's about to go wrong
RejectedFailed or stopped
DisabledOff, not applicable
- Waiting is blue. Orange is reserved for the viewer's own action or imminent trouble.
- Unknown statuses are neutral, never alarming.
- Money: credit green with “+”, debit red with “−” — the sign carries it without the colour.
Type
Stripe's step names at Stripe's dashboard sizes. Medium is 600. Sentence case everywhere; the only uppercase is table column headers. Numbers in tables and figures are tabular.
2xl24 / 32Page titles, record names
xl20 / 28Big figures, sub-headings
lg16 / 24Inputs, section headings
base14 / 20Body, table cells, nav
sm13 / 18Descriptions, figure labels
xs12 / 16Chips, badges, captions
2xs11 / 16Table column headers
Shape
- 6px corners on everything — buttons, inputs, chips, menus. Avatars are round.
- 1px hairlines in gray-150 separate sections and rows. No coloured left borders, no accent stripes.
- No elevation on the canvas. Popovers, menus and dialogs get a soft shadow; toasts a deeper one.
- Form fields are an underline that turns teal on focus and red when invalid. List search and filter controls are boxed, 32px tall, so they line up.
Motion
Motion shows what changed, fast enough that nothing trails the pointer. Entrances ease out (cubic-bezier(0.215, 0.61, 0.355, 1)).
Hover, press, selectioninstant, at most 100ms; nothing glides after the pointer
Tabsunderline slides 200ms, panel cross-fades 160ms
Content replacing a skeleton200ms fade and a 4px rise
A panel (FocusView)200ms in, 150ms out
Bars400ms ease-out
Reduced motionfades stay, every movement goes
Words
- Sentence case, in the user's vocabulary: “Customers”, “Add money”.
- Buttons say what happens (“Add person”), and the toast repeats the verb (“Person added”).
- Toasts are one line of at most 30 characters. A server's reason goes in a Banner where the action happened.
- Empty states say why and offer the next action. Errors say what happened and how to fix it, and never apologise.
- Dates read “22 Oct 2026”; relative times show the exact time on hover.