metro components

ui kit

Accent color · cobalt

typography

src/styles/metro/tokens.css

Type is the interface. Large, light and lowercase for headers; regular for body; semibold only for short emphasis. Hierarchy comes from size and color (fg vs subtle), never from boxes or lines.

heropage headerpivot headersubheader / list titleTitle — dialogs, item titlesBody — the default reading size for paragraphs and controls.Subtle — secondary information, timestamps, hints.caption / app title

color

src/styles/global.css · src/styles/metro/tokens.css

Two themes (dark is the default), one accent. The accent marks what is interactive or selected — use it sparingly so it keeps its meaning. Flat fills only: no gradients, no shadows.

--metro-bg
--metro-fg
--metro-subtle
--metro-chrome
--metro-accent

button

src/components/ui/Button.tsx

Outlined and transparent by default; inverts on press. Use the accent variant for the single primary action on a surface. Buttons tilt towards where they are pressed.

app bar button

src/components/ui/AppBar.tsx (AppBarButton)

The round icon button. One of the only circles in Metro. Icons are single-color SVGs tinted by CSS; labels are one lowercase word.

toggle switch

src/components/ui/ToggleSwitch.tsx

For settings that take effect immediately. Always print the state in words next to the switch — never rely on the fill color alone.

check box & radio button

src/components/ui/CheckBox.tsx · RadioButton.tsx

Check boxes for independent options that are applied later (e.g. on save). Radio buttons for one-of-many; if there are more than ~5 options, use a list picker instead.

slider

src/components/ui/Slider.tsx

Flat track filled with the accent, narrow rectangular thumb. Show the value when it matters to the user.

text box

src/components/ui/TextBox.tsx

Header above the box, never placeholder-only. The box lights up (solid + accent border) while focused. Errors go under the box in red, in plain words.

That doesn't look like an email address.

list picker

src/components/ui/ListPicker.tsx

The Metro combo box. Expands in place and pushes content down instead of floating a dropdown; the selected option is shown in the accent color.

Ringtone

progress

src/components/ui/ProgressBar.tsx · ProgressRing.tsx

Indeterminate dots when you can't tell how long it will take; the determinate bar only when you can. The ring is for inline or blocking waits in a small space.

indeterminate bar
determinate bar · 35%
rings · small / medium / large

list

src/components/ui/ListItem.tsx

Large light title + one subtle line. Whitespace separates items — no dividers, no chevrons. Items enter with a stagger and tilt on press.

last tapped: —

pivot

src/components/ui/Pivot.tsx

Several filtered views of the same content. Tap a header or swipe. The selected header always moves to the front; headers run off the edge to hint there is more.

MAIL · OUTLOOK

panorama

src/components/ui/Panorama.tsx

A single wide canvas you scroll through horizontally, with the title and background moving slower than the content (parallax). Each section should peek into the next.

music + videos

collection

history

new

app bar

src/components/ui/AppBar.tsx

Up to four round icon buttons for the most common commands, plus a text menu for the rest. Tap the ellipsis to reveal labels and the menu. Pass `fixed` to pin it to the viewport.

last command: —

message dialog

src/components/ui/MessageDialog.tsx

A full-width band across the middle of a dimmed screen (top-anchored on phones). No close button: every exit is an explicit, verb-labelled command. Escape = cancel.

toast

src/components/ui/Toast.tsx

Short, glanceable, and optional to act on. Slides in from the right on desktop, drops from the top on phones, and dismisses itself.

motion

src/styles/metro/animations.css

Fast and decelerating: things arrive quickly and settle. Exits are shorter than entrances. Related items move together with a small stagger. Every class below is plain CSS you can put on any element.