The eyebrow at the top of every widget.
One to three words. Pick the framing that orients the reader — usually a topic, sometimes a time window, occasionally an activity.
All widgets · Runtime grid
Each card is a standalone Lit custom element from the manifest, mounted inside its own HostShell iframe and loading its bundle on demand. Same overview ↔ detail-takeover morph the React hero uses, expressed as <lm-widget-grid> + custom elements via the View Transitions API.
Each badge marks where that widget actually ships. To appear in the hero grid at all, a widget of any tier has to be listed in it; the badge then governs who sees it once it is listed. Prod is live and public: shown on every host, in the App Store. Lab is experimental and public: also shown on every host, but the badge warns it may change or vanish. Beta is pre-release: the grid hides it everywhere except non-release iOS builds (staging and nightly), so dogfooders see it while App Store users do not. Team is staff-only: internal previews the grid hides unless the host opts in. Hibernation is a seasonal widget whose event has ended: the grid drops it until the event comes round again next year, but the gallery still lists it here. Filter the gallery by any tier with the pills below.
ari-labLablab-ideasLabstepsLabdistanceLabair-qualityLabWidget Runtime · Design System
Every tile in the phone above is assembled from the Lit elements documented below — same eyebrow position, same headline weight, same stat captions. Press D (or tap the dial) to reveal the spacing diagram and watch each primitive hold its place.
The eyebrow at the top of every widget.
One to three words. Pick the framing that orients the reader — usually a topic, sometimes a time window, occasionally an activity.
Above a grouped sub-region inside a tile.
Short, all caps, parallel in shape with its siblings. Read across, not down. Used today by the BADI column header and the moon-phase footer shelf.
The unit caption next to a numeric figure.
Abbreviated, six characters or fewer, parallel across the strip. The numbers do the work — the caption disappears into the rhythm.
One editorial eyebrow, picked from topic, time, or activity. Up to three words. Reach for time or activity only when that framing is what orients the reader best — otherwise the topic noun is the default.
Single topic noun, parallel in shape with its pair-mate. Never time or activity. The two tiles must read as a unit when the eye scans across — same weight, same baseline.
One real tile, five callouts. The night-route widget recipe carries every part of the system — turn diagram mode on to draw the spacing guides.
lm-text carries every visible string in the widget set. The variant prop picks a type-scale token; orthogonal modifiers handle color, italic, uppercase, and tracking. The serif-italic mix in editorial headlines lives in its own primitive — see lm-editorial-headline below.
lm-tile-header is the spine — it locks the head block across every widget. lm-card, lm-stack, and lm-list are the three primitives you reach for when arranging children.
Every value next to a caption uses tabular numerals. Captions are abbreviated and parallel — km · min · lit · dim. The numbers do the work.
The small interactive parts. Every tile that's tappable wears a CTA at the foot; every tile that classifies wears chips at the head. Icons live inside their shell so a 16-pixel glyph is a 16-pixel glyph everywhere.
Every widget that fetches data should ship a skeleton and an unavailable state. The primitives below make both single-line authoring jobs.
Half-width pairs live in lm-pair. The grid renders them whenever a row in grid.ts is declared as [a, b]. Both members must share an eyebrow weight and a baseline so the pair reads as a unit.
topic, time, or activity. Half-width: a single topic noun parallel to the pair-mate."Lake |& Limmat|", "Through the |canopy|.". Don't hand-roll <b> + span class="serif" markup.lm-tile-header — eyebrow, headline, lead, optional meta. Skip the head block and your tile will drift from every other.lm-stat-strip for value+caption rows. Two values or eight, same primitive. Captions ≤ 6 chars, parallel across siblings.lm-skeleton stack + one lm-unavailable block. No bare backgrounds while the SDK fetches.eyebrow as tabs-eyebrow.