Azalea
Azalea

Layout

Radius, spacing and page width — the parts of the system that are conventions rather than code.

Radius carries hierarchy

Three steps, and the step tells you what kind of thing you are looking at: the bigger the radius, the bigger the thing. A button inside a card is 8px inside 12px, and that nesting reads correctly. Swap them and it looks wrong before you can say why.

rounded4pxBadges and status pills — small enough that more would look soft.
rounded-lg8pxControls: buttons, inputs, selects, filters.
rounded-xl12pxSurfaces: cards, dialogs, the border around a table.
rounded-fullAvatars and the switch track only.
BHv1
full · 8px · 4px, nested inside a 12px surface

Why radius is not a token

It would have been easy to add --radius-sm/md/lg and feel systematic. It would also have been the wrong call.

Tokenising radius in Tailwind means redefining what rounded-lg and rounded-xl mean for every consumer — and Hana already uses both, on hundreds of elements, for things Azalea knows nothing about. Adopting the design system would have silently reshaped a working app, which is exactly the outcome the “tokens lifted verbatim” rule exists to prevent.

Colour earns a token because it changes with the theme and must be swappable. Radius does not change; it just needs to be consistent. A documented convention buys that at no risk. Revisit if the three steps ever stop being enough.

Spacing

Tailwind's scale, used at five steps. Anything outside them is usually a sign the layout wants restructuring rather than a new value.

gap-1.5 / 6pxInside a control — icon to label, badge to count.
gap-3 / 12pxBetween controls on one row.
p-5 / 20pxCard padding.
py-3 / 12pxA row in a DataList.
mb-10 / 40pxBetween page sections.

Page width

Operational tools, not marketing pages — the constraint is scannability, not immersion.

  • max-w-3xl for a detail page — a run, a deployment. Long lines are harder to scan than short ones.
  • max-w-5xl for a list or a dashboard, where rows carry several columns.
  • Never full-bleed. A table on a 32-inch monitor with no max width is unreadable, and the person reading it is the one who has to scan across it.

Motion

Transitions are for state changes a person caused — a hover, a toggle. Nothing animates on its own except a Skeleton, which is signalling that something is happening.

Azalea ships a global prefers-reduced-motion reset in tokens.css: every animation and transition collapses to nothing when the OS asks. It is a global reset rather than a per-component opt-in because a system that leaves this to each component leaves it out of the next one — and nothing here animates in a way that carries meaning when it stops.