Skip to content

Foundations

Space and radius

A 4px base and one radius token that everything else multiplies. Both are rendered at true size below. The point of the page is that you can hold a ruler up to it.

Source of truth: varick-site/app/globals.css · varick-charts chart-spec.md §1

Space

4px base. Every gap, pad and inset is a step on this scale. There are no in-between values.

0.52px
14px
28px
312px
416px
520px
624px
832px
1040px
1248px
1664px
2080px
2496px

These map one-to-one onto Tailwind’s default scale, so gap-6 is 24px here and 24px in the product. That is the reason to keep the base at 4.

Vertical rhythm

Where the scale actually gets spent.

GapStepBetween
4px1A label and the value under it.
8px2Items in a tight list. Icon and its text.
12px3Bullets in a list a reader scans.
16px4Cards in a grid. Paragraph to paragraph.
24px6Card padding. Heading to its content.
32px8Subsection to subsection.
64px16Section to section.
96px24Page header to first section, on a long page.

Radius

Two radii. Small shapes, the things you press and read, take 4px. Containers, the things that hold them, take 8px. Nothing in between.

--radius-sm

4px

Buttons, inputs, chips, badges, checkboxes, tabs, table cells, kbd.

--radius-lg

8px

Cards, panels, menus, dialogs, tiles, the navigation and the search bar.

TokenCalcRenderedWhere
--radius-sm4px4pxButtons, inputs, chips, badges, checkboxes, tabs, table cells, kbd.
--radius-lg8px8pxCards, panels, menus, dialogs, tiles, the navigation and the search bar.
--radius-sm: 4px; /* controls, chips, badges, cells */
--radius-lg: 8px; /* cards, menus, dialogs, navigation */
--radius: var(--radius-lg);

Radius inside a chart

Charts follow the same two values: 8px on the card, 4px on bars, tracks and controls.

ElementRadiusNote
Card8pxn/a
Control, segmented4pxn/a
Bar4px[4,4,0,0] for columns
Track4pxn/a

Never fully pill

Unless someone explicitly asks for one. A pill reads as a tag or a toggle, and using it for something that is neither makes the interface ambiguous.

Hairlines for structure, shadow for lift

The hairline is still the structural line of the system. Elevation is a separate, and separately tokenised, job.

A hairline says this is a boundary. A shadow says this surface sits above that one. They answer different questions, so the system uses both, and splits them by surface: on the web a card gets a hairline and a low layered shadow. Documents and print stay completely flat, which is why the document palette has no shadow token at all.

--shadow-card

Cards and asset tiles at rest.

--shadow-card-hover

The same surface on hover, to signal it is interactive.

--shadow-tooltip

Chart tooltips and the copy toast. Floats over content.

This rule was amended. It previously read “hairlines, not shadows” with one exception for chart tooltips, which made every card on this site read as a wireframe. Elevation is now tokenised rather than banned, and the ban survives where it was always right: anything that ends up on paper.

Default

#EBEBEB

Every card, table and input.

Hover

#DEDEDE

The border on hover, and where a hairline must assert itself.

Document rules

#D9D9D9

Table strokes inside a .docx.

Grid lines inside a chart are the same colour, dashed 4 4, horizontal only, except on a scatter, where both axes get them.