Radius
Everything you press is a pill; surfaces nest concentric radii and take continuous corners where the browser has them.
Scale
Everything you press is a pill.
| Token | Use | Corner | Value |
|---|---|---|---|
| Bars and tiny marks. | Round | ||
| Key caps. | Round | ||
| Small surfaces and inline code. | Round | ||
| Nested wells and tooltips. | Round | ||
| Rows and fields: the sidebar, palette results, inputs. | Round | ||
| Code windows, menus and settings groups. | Continuous | ||
| A palette and a user's message. | Continuous | ||
| Large display surfaces. | Continuous | ||
| Everything you press: buttons, icon buttons, segmented controls, tabs, badges, chips, the compact composer. | Round |
Inner radius = outer radius − inset. Menus, card rows and trays derive their corners from their frame and padding. A composer stays round around its round 24px send button: 12px + 8px padding + a 1px border gives --radius-frame-composer. Changing the inset changes the inner corner with it.
Surfaces follow nesting: a surface's radius is its child's plus the padding between them, so corners stay concentric. The large steps take continuous corners where the browser has them.
Concentric corners
Outer = inner + padding. A part within reach of its frame's corner takes the frame's radius less its inset, so the gap between the two curves stays even all the way round.
- A child within reach of a corner (inset d below the frame's radius R on both axes) has r = max(4, R − d). Never equal radii on nested parts unless the part is flush and clipped.
- The inset at a reached corner is the same on both axes. If it isn't, fix the padding, not the radius.
- A pill fixes its own radius (h / 2), so a frame that hosts one in its corner derives its radius from it: R = h / 2 + d. Those are the frame radii below, the same in both corner modes and round: a pill's round cap is never concentric with a continuous corner.
- Components derive it for you: a container sets the nest pair (`stylex.env.nest.frame`), its parts read `stylex.env.nest.radius`, and the lint (`nest-derived`, `frame-radius`) refuses a radius worked out by hand.
Frame radii
Derived from what sits in their corner, so the corner and its control are one curve.
| Token | What sits in the corner | Value |
|---|---|---|
| Composer: the 24px send pill, 8 in behind a 1px frame (12 + 8 + 1). | ||
| Tray: a 24px pill in the footer corner at 8 (12 + 8). | ||
| Popover: a 24px pill at the 12px pad (12 + 12). | ||
| Dialog: a 28px pill at the 16px pad, behind a 1px frame (14 + 16 + 1). | ||
| Card: a 6px rounded control 8 in, behind a 1px frame (6 + 8 + 1). |
Scrollers
A scroller's thumb keeps out of its corners too: 4px wide, 2px from its side, its straight run ending r − 2 from the outer edge, so its cap is concentric with the corner.
A scroller names its corner with --scroll-radius and opts in with data-scroll-inset.
Continuous corners
Large surfaces set corner-shape: var(--corner).
Continuous corners read smaller than round ones at the same radius, so where they apply the large steps go up a quarter: --radius-xl 12 to 15, --radius-2xl 16 to 20 and --radius-4xl 24 to 30. Elsewhere --corner is round and the steps stay 12, 16 and 24.
Where they apply
- Continuous: stream cards, menus, hover cards, toasts and a product's user bubble. Inset rows inherit their frame's shape.
- Round: pills (
--radius-full), the frames that host a pill in their corner (trays, popovers, dialogs, a composer), standalone rows and fields, tooltips and nested cards.
Where the browser has it (Chromium 139 and later) that is superellipse(1.6): the curve eases in from the straight edge instead of starting abruptly, the way a machined part does.