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.
- A part shares its frame's corner shape through any wrapper between them: `cornerShape: nest.corner`, the frame naming a continuous corner in `nest.frame(R, pad, corner)` or `nest.shape(corner)`. A round part in a continuous frame flares at the corner's middle by an eighth of the frame's radius, 2px in a 15px menu; the lint (`nest-corner`) refuses `inherit`, which reads the parent only.
Clear of the curve
What can't be concentric keeps clear: a line of text, or a row too tall for the radius it would need, sits on the corner's centre line on one axis, its middle R from that edge.
- The inset is `nest.capInset(R, h)` from the frame's edge (a dialog's title line, a popover's first and last lines, the settings window's nav title and Docs row), or `nest.cornerLine(h)` past a nest frame's pad.
- A capsule keeps its own shape: where it can't be concentric it takes extra margin, never a radius of its own.
- The layout check's `corner` rule reads every shot at each corner: the gap to the curve never pinches more than 1.5px under the part's inset from the edges (2px for a text, by its cap band), and a part that draws its own corner never flares more than 1.5px past it.
So a frame's padding near its corners comes from its radius.
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). | ||
| A list popover: a 24px row at the 6px pad (12 + 6). | ||
| 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.