Design system · v1.0

Facet

A design system for data-dense products. Thirty accessible components, live tokens, and its own light and dark themes, built from scratch.

  • Accessible by default
  • Token-driven
  • Calm density

In use

The same primitives documented below, composed into one real screen. No mockups, this is the components running.

Team members

Manage who can access this workspace.

MemberRoleStatus
AO

Ada Okafor

ada@facet.design

AdminActive
LM

Leo Marsh

leo@facet.design

EditorActive
PR

Priya Raman

priya@facet.design

EditorActive
SC

Sam Cole

sam@facet.design

ViewerInvited

Color

Six ramps of eleven steps. Components never read raw hex; they read the semantic tokens below, which remap for light and dark.

Ink (brand)

50

faf9f7

100

f2f1ec

200

e6e4dd

300

d3d0c6

400

a8a498

500

7b7870

600

5b584f

700

43413a

800

2a2925

900

1a1916

950

0e0d0b

Bronze (signal)

50

faf6ec

100

f3e8cd

200

e7d3a0

300

d8bb74

400

c6a04e

500

ae863a

600

a07d36

700

7d612a

800

5a461f

900

3b2e15

950

241b0c

Success

50

ecfdf5

100

d1fae5

200

a7f3d0

300

6ee7b7

400

34d399

500

10b981

600

0f9d76

700

0b7a5c

800

0a6249

900

084c39

950

032b20

Warning

50

fdf8ec

100

faefcb

200

f5de93

300

f0c858

400

f0b530

500

d99b1c

600

b67b14

700

915e13

800

6f4816

900

4e3313

950

2b1a08

Danger

50

fdf2f1

100

fbe0de

200

f7c4c0

300

f19c95

400

f0736b

500

e0554c

600

c8443b

700

a5352e

800

832b26

900

631f1c

950

3a0f0d

Info

50

eff8fd

100

d8eefa

200

b0dcf4

300

7dc5eb

400

56b6e8

500

2f97cf

600

1f7fb5

700

1b6491

800

1b5375

900

164560

950

0e2c3e

TokenUsage
--fc-bgPage background
--fc-surfaceRaised surfaces, inputs
--fc-fgPrimary text
--fc-mutedSecondary text
--fc-borderDividers, edges
--fc-primaryBrand actions, focus
--fc-successPositive status
--fc-warningCaution status
--fc-dangerDestructive, errors
--fc-infoInformational status

Typography

One ramp, seven steps. Sizes in pixels, with line height, weight, and tracking fixed per step so text stays consistent across the system.

Display

32px / 1.1 / 600

Hero and page titles

Heading 1

24px / 1.2 / 600

Section titles

Heading 2

19px / 1.25 / 600

Sub-section titles

Heading 3

16px / 1.35 / 500

Card and group titles

Body

14px / 1.6 / 400

Default reading text

Small

13px / 1.55 / 400

Secondary text, help

Caption

12px / 1.5 / 400

Labels, meta, tags

Spacing

A 12-step scale in pixels. Every gap, padding, and margin snaps to a step, which keeps rhythm consistent without one-off values.

2px0.125rem
4px0.25rem
6px0.375rem
8px0.5rem
12px0.75rem
16px1rem
20px1.25rem
24px1.5rem
32px2rem
40px2.5rem
48px3rem
64px4rem

Radii

Five corner radii. Small for inputs and chips, medium for buttons and cards, large for surfaces, full for pills and avatars.

sm

6px

md

8px

lg

12px

xl

16px

full

9999px

Elevation

Four shadow tokens for lifting surfaces. Used sparingly: popovers use sm, dropdowns md, dialogs lg, and the highest layer xl.

shadow-sm

shadow-md

shadow-lg

shadow-xl

Motion

Three durations and one easing curve. Motion is functional, never decorative, and every transition is disabled under prefers-reduced-motion.

Durations
fast120ms
base200ms
slow320ms
ease: cubic-bezier(0.16, 1, 0.3, 1)

Iconography

A single-weight, 16px line set on a 16px grid. Icons are decorative by default (aria-hidden); when an icon is the only label, its control carries an aria-label.

check
x
chevronDown
chevronRight
arrowRight
external
search
info
alert
success
danger
plus
copy
menu
filter
user

Grid & breakpoints

A 12-column grid inside a 1240px max width, with a 24px gutter. Five breakpoints drive every responsive change.

1
2
3
4
5
6
7
8
9
10
11
12
sm640pxLarge phone
md768pxTablet
lg1024pxLaptop
xl1280pxDesktop
2xl1536pxWide

Buttons & links

Five variants, three sizes, and every state. Real buttons: keyboard focusable, disabled and loading states expose aria-busy, focus rings meet contrast.

Variants
<Button variant="primary">Save changes</Button>
Sizes
<Button size="sm|md|lg" />
StatesTab to focus and see the ring
<Button loading /> · <Button disabled />
Icon button & groupIcon-only buttons carry an aria-label
<IconButton label="Search" />
Links
<Link external href="...">Docs</Link>

Inputs & controls

Every control is labelled, keyboard operable, and states its errors with an icon and text, never color alone. Selection controls use roving tabindex, so each group is a single tab stop.

Text fieldsTab through to see focus rings

As it appears on your ID.

Enter a valid email address.

<Field label="Email"><Input /></Field>
Textarea

Markdown is supported.

<Field label="Notes"><Textarea /></Field>
SelectNative select, styled chevron
<Select><option>…</option></Select>
ComboboxType to filter, arrows to move, Enter to pick

Start typing to filter the list.

<Combobox options={countries} />
Checkbox
<Checkbox label="…" indeterminate />
Radio groupArrow keys move and select
<RadioGroup options={plans} />
Switch
<Switch checked={on} onChange={setOn} />
SliderArrows adjust, Home and End jump to ends
Volume
60
<Slider value={v} onChange={setV} />
Segmented controlArrow keys switch segments
<SegmentedControl options={views} />

Alerts & status

Messages, live regions, and progress. Every status carries an icon and text, so meaning never rests on color. Tooltips answer to hover and keyboard. Motion respects reduced-motion.

Alertsrole=status, icon plus text

Changes saved

Your profile is up to date. We synced it across every signed-in device.

Draft autosaved

We keep a copy as you type, so you can close this tab without losing work.

Storage almost full

You have used 92 percent of your plan. Archive old files to free up room.

Payment failed

We could not charge your card. Update your billing details to keep access.

<Alert tone="success" title="Saved">…</Alert>
ToastAuto-dismisses after 4s, or close it
<ToastDemo />
TooltipHover or Tab to the button, Escape to hide
Account settingsCopy link
<Tooltip label="Account"><button>…</button></Tooltip>
BadgesText carries the meaning
DraftBetaLivePendingFailedInfo
<Badge tone="success">Live</Badge>
TagsRemove any chip with the keyboard or a click
Read onlyNo remove button
DesignResearchPrototypeAccessibility
<Tag onRemove={fn}>Design</Tag>
ProgressDeterminate and indeterminate
Uploading assets60%
Preparing export
<Progress value={60} /> · <Progress indeterminate />
Skeletonaria-hidden placeholder while data loads
<Skeleton className="h-4 w-40" />

Dialogs & menus

Modal and non-modal layers built from scratch. Dialogs trap focus and lock scroll, Escape and outside clicks dismiss, and menus move focus with the arrow keys. No overlay library.

DialogFocus trapped, Esc to close
<Dialog open onClose={fn} title="Delete project" />
DrawerSlides in from the right
<Drawer open onClose={fn} title="Settings" />
PopoverClick outside or Esc to dismiss
<Popover trigger={<>Filters</>}>...</Popover>
Dropdown menuArrow keys, Enter to select
No action yet
<DropdownMenu label="Actions" items={items} />

Tables & display

A sortable data table, cards, avatars, an accordion, and the small pieces that make dense screens legible. Sort state is announced through aria-sort, and every disclosure is keyboard operable.

Data tableClick a header to sort. Header sticks on scroll.
AOAmara Okafor
EngineeringActive
BCBen Carter
DesignInvited
CWChen Wei
ProductActive
DIDara Idris
SupportSuspended
ERElena Ruiz
DesignActive
FBFemi Bello
EngineeringInvited
GLGrace Lin
ProductActive
HAHassan Ali
SupportActive
<Table columns={columns} rows={rows} sortable />
Card

Storage

Your team has used 48 GB of the 100 GB included on the current plan.

Updated just now
<Card title="Storage" footer={...} />
AvatarsInitials fall back when no image is set
AOBCCW
AOBCCWDI+4
<AvatarGroup max={4}>...</AvatarGroup>
AccordionAny number of panels can be open

Yes. Every component reads semantic CSS variables through Tailwind arbitrary values, so one token change re-themes the whole system.

<Accordion items={faqs} />
Empty state

No results

No members match that search. Try a different name or clear the filter.

<EmptyState title="No results" action={...} />
Keyboard keys
KOpen command menuPCommand paletteEscDismiss
<Kbd>⌘</Kbd><Kbd>K</Kbd>

Accessibility

Not a claim, a property. Every pairing below is read live from the tokens, so it tracks the theme and can never drift. Every component is operable by keyboard alone.

Contrast, read live from the tokens

PairingRatioLevel

Body text

fg on bg

AA

Secondary text

muted on bg

AA

Text on surface

fg on surface

AA

Primary button label

primary-fg on primary

AA

Bronze signal

accent on bg · large/UI

AA

Error text

danger on bg

AA

Success indicator

success on bg · large/UI

AA

Focus ring

ring on bg · large/UI

AA

Keyboard

Button, Switch, CheckboxSpace or Enter activates or toggles
Radio group, SegmentedArrow keys move focus and select
SliderArrow keys adjust, Home and End jump to min and max
ComboboxDown and Up move options, Enter selects, Escape closes, typing filters
TabsLeft, Right, Home, End move between tabs
Dropdown menuUp, Down, Home, End move items, Enter selects, Escape closes
Dialog, DrawerTab cycles within, Escape closes, focus returns to the trigger
AccordionEnter or Space expands and collapses

Reduced motion

Under prefers-reduced-motion, every transition and animation is reduced to near-zero. Nothing meaningful is conveyed by motion alone.

Color is never the only signal

Status always pairs a hue with an icon and text, like Error.