Corners are tokens, not pixel guesses. Nested boxes use the -8 and -4 nest sizes so concentric radii look intentional.
The radius scale
radius on Flex, Row, Column, Card, and the rest takes a T-shirt size — the same model as spacing and type:
Token
Use
`none`
Sharp corners
`xs` / `s`
Compact chips, tight controls
`m`
Default for cards and panels
`l` / `xl`
Soft, friendly surfaces
`full`
Pills and circular clips
Pick one size and stick to it across a surface family. Mixing xs cards with xl buttons reads as two products on one page.
Nested radius
When a rounded box sits inside another rounded box, the inner corner must be smaller than the outer one or the gap between them looks uneven. Once UI encodes that as nest suffixes on the same size:
{size}-8 — outer container padded with spacing token "8"
{size}-4 — middle layer padded with "4"
{size} — innermost content
The TypeScript type is a plain size (xs … xl, full, none) or that size plus a nest suffix (-4 or -8). So m-8, l-4, and xl-8 are valid; inventing m-12 is not.Match the nest number to the padding you actually use. An outer radius="m-8" with padding="24" will not look concentric — the nest tokens are tuned for "8" and "4" padding, the sizes you reach for most often when nesting.
One side or one corner
When only part of the box should round — a tab bar, a split card, a list row that shares edges — use the side and corner props instead of hacking CSS:
<Row
border="neutral-medium"
background="surface"
topLeftRadius="m"
topRightRadius="m"
bottomLeftRadius="none"
bottomRightRadius="none"
>
Top of a stacked group
</Row>
These take plain size values (xs … xl, full, none). They do not take nest suffixes — nest only on the full radius prop.
Global shape with data-border
The app-wide shape language is not a prop on every component. It is a data attribute on a semantic ancestor (usually html, set by ThemeProvider / ThemeInit):
data-border="rounded" — balanced default
data-border="playful" — larger corners
data-border="conservative" — tighter corners
<div data-border="playful">
<Column radius="m" padding="24" border="neutral-medium">
Same radius="m", softer corners under playful
</Column>
</div>
radius="m" still means medium relative to the active shape scale. Change data-border when the whole product should feel sharper or softer; change radius when one element needs to differ from its siblings.
Borders that go with the corner
Radius rarely travels alone. The same style props cover the stroke:
Prop
Values
`border`
Scheme token (`neutral-medium`, `brand-alpha-weak`, …), `surface`, `transparent`, or `true`
`borderWidth`
`1`, `2`, `4`, `8`
`borderStyle`
`solid` (default) or `dashed`
Side helpers (borderTop, borderX, …) accept the same colour tokens when only some edges need a stroke.
Write this / not this
Do
Avoid
`radius="m"`
`style={{ borderRadius: 12 }}`
`radius="m-8"` with `padding="8"`
Same `radius="m"` on every nested box
`topLeftRadius="m"` for partial rounds
Custom CSS classes for one corner
`data-border` for product-wide feel
Per-component pixel tweaks to match brand
More design tips
The full prop tables live in the Border docs. Theme-level data-border is covered with the other runtime style knobs in this section.