Responsive props

Props whose right value depends on the window size take one value per M3 window tier.

Window tiers

M3 sizes layouts by window size class, measured in density-independent pixels (dp). A responsive prop takes up to five tiers, one per class, and each tier is a Tailwind variant backed by a --breakpoint-* token. Use these instead of Tailwind's default sm, md, lg and xl variants, whose stops match no M3 class. A test fails the build if the library or this site uses one.

Tier Class From Typical device
compactno prefix0Phone
mediummedium:600dpTablet, foldable
expandedexpanded:840dpLandscape tablet
largelarge:1200dpLaptop, desktop
extraLargeextra-large:1600dpLarge desktop, external display

One value or several

A Responsive<T> prop takes a single value, or an object with one value per tier. A tier you leave out inherits from the tier below it, the way Tailwind prefixes do:

<!-- Always side by side -->
<PaneGrid direction="row">…</PaneGrid>

<!-- Stacked on phones and small tablets, side by side from expanded up -->
<PaneGrid direction={{ compact: 'column', expanded: 'row' }}>…</PaneGrid>

<!-- A small app bar that grows to large on wide windows -->
<AppBar title="Travel" size={{ compact: 'small', expanded: 'large' }} />

<!-- Your own classes use the same names -->
<div class="grid grid-cols-1 medium:grid-cols-2 large:grid-cols-3">…</div>

Today PaneGrid's direction, gap, padding and margin, and AppBar's size are responsive.

Responsive defaults

Where M3 gives per-window guidance, the default follows it instead of being one value. PaneGrid's direction defaults to { compact: 'column', expanded: 'row' }: one pane until the expanded class, as in M3's canonical layouts. So a split that must stay side by side at every width needs direction="row" explicitly.

Resolved in CSS

Every tier becomes a breakpoint-prefixed class, so the right value applies during server rendering, with no matchMedia, no JavaScript and no flash when the page hydrates. Resizing the window switches values instantly.