Design system · @bebshai/ui

Foundations

Tokens and rules from docs/design/admin-monitoring.md, as defined in packages/ui/src/styles/globals.css. Switch the theme in the header to compare light and dark.

DoSeparate surfaces with a border and a change of tone.
Don'tAdd a shadow to a card, popover, menu, sheet or toast. Only focus rings use box-shadow.
DoGive every status an icon or a label as well as a colour.
Don'tLet an icon outweigh its label: icons are smaller than the text and muted.
DoKeep filters, time range and paging in the URL.
Don'tUse a light slab for a dark-mode card.

Backgrounds (bg/*)

Separated by tone and border, never by shadow. In dark mode surfaces sit just above the canvas.

--bg-canvasbg-canvas · page
--bg-surfacebg-surface · cards, panels, sheets
--bg-surface-raisedbg-surface-raised · menus, dialogs
--bg-surface-sunkenbg-surface-sunken · wells
--bg-mutedbg-muted · tracks, code
--bg-hoverbg-hover · pointer and keyboard highlight
--bg-selectedbg-selected · selected row, current item
--bg-disabledbg-disabled
--hover-canvashover on the canvas (automatic)
--muted-canvastracks on the canvas (automatic)
--hover-raisedhover in menus (automatic)
--sidebarbg-sidebar · white / canvas
--inversebg-inverse · tooltips, kbd

Strokes (border/*)

Close to the background. Row separators are the quietest, card and input borders one step up.

--separatorborder-separator · table rows, dividers
--border-defaultborder-default · cards, menus
--border-inputborder-input · inputs, selects
--border-strongborder-strong · dashboard cards, switch track
--border-controlborder-control · checkbox and radio
--border-focusring-focus · focus

Text and icons (text/*)

Icons are muted and smaller than the text beside them; only the active nav icon is full ink.

--text-defaulttext-default · on the canvas
--text-on-surfacetext-on-surface · on surfaces
--text-mutedtext-muted
--text-selectedtext-selected
--text-disabledtext-disabled
--icontext-icon
--linktext-link

Brand (brand/*)

Accent is brand decoration, never state: state uses hover and selected.

--brand-primarybg-primary / text-on-primary
--brand-secondarybg-secondary / text-on-secondary
--brand-accentbg-accent / text-on-accent

Status (status/*)

Solid for dots, bars, icons and filled badges (ink: on-solid); subtle fills carry on-subtle ink. Always pair colour with an icon or a label.

--status-success-solidbg-success-solid / text-success-on-solid
--status-success-subtlebg-success-subtle / text-success-on-subtle
--status-warning-solidbg-warning-solid / text-warning-on-solid
--status-warning-subtlebg-warning-subtle / text-warning-on-subtle
--status-error-solidbg-error-solid / text-error-on-solid
--status-error-subtlebg-error-subtle / text-error-on-subtle
--status-info-solidbg-info-solid / text-info-on-solid
--status-info-subtlebg-info-subtle / text-info-on-subtle

Charts (chart/*)

Figma series, estimate, ordinal ramp, grid and baseline, then the app's extra categorical hues. Use hues in sequence, not by meaning.

--chart-series-1
--chart-series-2
--chart-estimated
--chart-muted
--chart-ordinal-1
--chart-ordinal-2
--chart-ordinal-3
--chart-negative
--chart-grid
--chart-baseline
--chart-3
--chart-4
--chart-5
--chart-6
--chart-7
--chart-8

Severity

Log levels in badges and histogram stacks.

--severity-debug
--severity-info
--severity-warn
--severity-error
--severity-fatal

Scrims and tints

Sheets and dialogs dim the page with overlay; popovers and menus with overlay-soft. Tints mark diff lines.

--overlay
--overlay-soft
--tint-add
--tint-del

Primitives

The Figma palette, exact hex. Only globals.css and this page name them; feature code uses the tokens above.

--green-50
--green-100
--green-200
--green-300
--green-400
--green-500
--green-600
--green-700
--green-800
--green-900
--green-950
--olive-50
--olive-100
--olive-200
--olive-300
--olive-400
--olive-500
--olive-600
--olive-700
--olive-800
--olive-900
--olive-950
--slate-50
--slate-100
--slate-200
--slate-300
--slate-400
--slate-500
--slate-600
--slate-700
--slate-800
--slate-900
--slate-950
--stone-50
--stone-100
--stone-200
--stone-300
--stone-400
--stone-500
--stone-600
--stone-700
--stone-800
--stone-900
--stone-950
--blue-50
--blue-100
--blue-200
--blue-300
--blue-400
--blue-500
--blue-600
--blue-700
--blue-800
--blue-900
--blue-950
--sky-50
--sky-100
--sky-200
--sky-300
--sky-400
--sky-500
--sky-600
--sky-700
--sky-800
--sky-900
--sky-950
--teal-50
--teal-100
--teal-200
--teal-300
--teal-400
--teal-500
--teal-600
--teal-700
--teal-800
--teal-900
--teal-950
--red-50
--red-100
--red-200
--red-300
--red-400
--red-500
--red-600
--red-700
--red-800
--red-900
--red-950
--amber-50
--amber-100
--amber-200
--amber-300
--amber-400
--amber-500
--amber-600
--amber-700
--amber-800
--amber-900
--amber-950
--purple-50
--purple-100
--purple-200
--purple-300
--purple-400
--purple-500
--purple-600
--purple-700
--purple-800
--purple-900
--purple-950
--rose-50
--rose-100
--rose-200
--rose-300
--rose-400
--rose-500
--rose-600
--rose-700
--rose-800
--rose-900
--rose-950
--lime-50
--lime-100
--lime-200
--lime-300
--lime-400
--lime-500
--lime-600
--lime-700
--lime-800
--lime-900
--lime-950
--white
--neutral-canvas
--neutral-subtle
--neutral-border
--neutral-ink
--neutral-text-muted

Strokes in use

The three stroke tokens stacked the way a list page uses them.

Card header (separator)
First row
Second row
Third row

Icon scale

Tabler icons, muted by default (text-icon). Always smaller than the text next to them.

ContextSizeStrokeExample
Beside 14px text (nav, page)size-4 · 16px1.75 Search
Inside buttons and inputs (13px)size-3.5 · 14px1.75 Filters
Chips and facets (the +)size-3 · 12px2 Level
Inside badges≈11px2.2, currentColorSee Components → Status badges

Type

Inter for everything, Geist Mono for ids, routes and code. Every size is a rem token in globals.css, so it follows the root font size.

text-title1.25rem · 20px 600

Page title

text-metric1.375rem · 22px 600

৳12,480

text-fact0.9375rem · 15px 600

৳999 / month

text-heading0.9375rem · 15px 600

Sheet and dialog title

text-panel0.8125rem · 13px 600

Panel and card title

text-body0.8125rem · 13px

Body, tables and controls: the main UI default

text-label0.75rem · 12px 500

Form label

text-small0.75rem · 12px

Groups and metadata labels

text-code0.75rem · 12px mono

01a0e7e8-83bf-7b62 · /v1/admin/tenants/{id}

text-overline0.6875rem · 11px 500

Table header

text-caption0.6875rem · 11px

Helper and secondary text

text-badge0.6875rem · 11px 500

Status and version chips

Motion

One duration (--duration-base, 200ms) and one curve (ease-out: cubic-bezier(.2,.7,.2,1)). prefers-reduced-motion sets the duration to zero.

Hover to run the base transition