Skip to content

Radius and Shadow

Radius and shadow feed Tailwind’s own theme keys, so the classes stay Tailwind’s. Read this for the scales, and for the focus ring’s two static classes.

View source View as Markdown

Radius and shadow are passthroughs, which means we feed our tokens into Tailwind’s native --radius-* and --shadow-* theme keys and the classes stay Tailwind’s own with Mirror’s scale behind them. Per-corner variants, arbitrary values and editor completion all work exactly as they do everywhere else.

Radius

Component

2xs

xs

sm

md

lg

xl

2xl

Surface

sm

md

lg

index.html
<button class="rounded-component-md">Control</button>
<section class="rounded-surface-md">Container</section>

Component radii size controls such as buttons, inputs, checkboxes and chips, and run from rounded-component-2xs through rounded-component-2xl, with the tighter rounded-component-compact-sm through -compact-xl alongside them and rounded-component-round for a pill.

Surface radii size containers instead, as rounded-surface-sm, -md and -lg, each with an -inset partner.

A rounded container with padding needs a smaller radius on its children, or the corners visibly diverge. The -inset step is the container’s radius minus the container’s inset, so nested corners stay concentric.

<div class="rounded-surface-md p-2">
  <img class="rounded-surface-md-inset" src="…" />
</div>

Shadow

There are three elevations, each of which takes its colour from a shadow-ink token, so a theme that softens the ink softens every elevation at once.

component

shadow-component

component high

shadow-component-high

surface

shadow-surface

index.html
<div class="shadow-component">Card</div>
<div class="shadow-component-high">Popover</div>
<div class="shadow-surface">Sheet</div>
ClassUse
shadow-componentResting controls and cards.
shadow-component-highRaised chrome such as popovers and menus. Two layers.
shadow-surfaceWhole surfaces such as sheets and dialogs.

The focus ring

The focus ring has exactly one shape, so it ships as a single static class rather than a family.

index.html
<button class="border-2 outline-4 outline-transparent focus-visible:focus-ring">
  Ringed on focus
</button>
.focus-ring {
  border-color: var(--app-color-focus-border);
  border-width: var(--app-dimension-border);
  outline-color: var(--app-color-focus-outline);
  outline-width: var(--app-dimension-outline-focus);
  outline-style: solid;
}

Because the class sets a border width and an outline width alongside their colours, reserve both at rest, as the button above does with border-2 and outline-4 outline-transparent. Leave them out and the control gains a 2px border the moment it takes focus, nudging its neighbours along, and animates its outline out of whatever currentColor happens to be. Styling shows the same reservation on a full control.

Both the colour and the width come from tokens, which means an app can’t style the ring down to nothing while still using the class.

focus-shadow draws the same ring with two box shadows instead, for elements whose border or outline is already doing something else. It needs no reserved border and shifts nothing.

.focus-shadow {
  box-shadow:
    inset 0 0 0 var(--app-dimension-border) var(--app-color-focus-border),
    0 0 0 var(--app-dimension-outline-focus) var(--app-color-focus-outline);
}