Material 3

Components

Gallery recipes from wod-gallery. Compose Applied (#apply-*) and Opportunities (#opportunity-*) classes: wod-btn, wod-chip, wod-card, wod-breadcrumb, wod-empty, wod-alert, wod-frame, wod-h-scroll, wod-search.

Buttons

Hover 1.02 · press 0.96 · keep pill radius. One filled or inverse per screen. Break harness: /design/motion.

Empty state

Media well → title → description → one CTA. Verb-first label; no bare “Learn more.”

No events this day

Try another date or browse places nearby.

Browse places

Short trails stay inline. Longer trails collapse the middle in <details>. Current page is text with aria-current="page".

Field addons

Search and URL fields share .wod-field--with-addons. Placeholders end in ellipsis; URL fields use spellcheck="false".

Scroll fade

Pair .wod-h-scroll with .wod-scroll-fade. Do not use .wod-carousel on listing strips.

Jazz at The Pinhook

Fri · 8pm

Food truck Friday

Downtown

Open mic · Cocoa Cinnamon

Sign-ups 6:30

Durham Bulls home

Gates 5:30

Alerts

Inline notices, not dialogs or snackbars. One action plus optional dismiss.

Filters tip

Chip filters stay selected until you clear them.

Hours may change

Holiday schedule — confirm before you go.

Icon buttons

Share template

FAB

Medium (80) is default. Standard 56 · large 96 · extended is a pill. Surface-color FABs are not used.

Cards

Filled

Surface-container, elevation 0.

Outlined

Outline-variant hairline. Listing default.

Elevated

Tone first; +1 shadow on hover.

Chips

Assist = rest. Filter selected = secondary-container. Emphasis = volt “new” only.

Connected button group

Sliding white thumb in a padded highest-container track. Compact: do not wrap or shorten labels.

Navigation dock

Product keeps this floating dock at every breakpoint — no rail, no drawer. Search stays in the top bar. Labels live in tooltips and More.

Text field

Radius 12. Label always visible. Error is text + color.

Supporting text sits under the field.

Search

Leading icon, hint containing “Search”, ≤2 trailing icons. Focus is a real ring.

Event date strip

Live on /events. Months are label-small dividers; the selected day uses secondary-container. Horizontal scroll-snap at micro (≤370px). Compact trip chrome wraps filters above this strip — not a third sticky band.

Frame / Quick facts

Maps-style list inside .wod-frame: 24dp icon, 16dp to a text column. Keep When / Where / Address labels above the value.

Hotel list row

56 min row. Name left, price meta right. Dividers use outline-variant.

Date pickers

Events calendar is a single day (navigate on select). No OK/Cancel. Docked on medium+; modal <dialog> + native ::backdrop below 600dp. Month title is a year menu.

Year menu (month title + arrow_drop_down).

List

Tabs

Peer content in a pane. Shared 3px primary indicator. Not top-level destinations.

Switch, checkbox, radio, select

Dialog

Leave this plan?

Stops stay saved on this device.

Sheet

Chatbot panel is a native <dialog> with .wod-sheet handle, toolbar, panel, and footer — not .wod-dialog. Closed dialogs stay display: none. One filled Send.

Ask Durham

What’s free this weekend near Brightleaf?

House banner (ad slot)

Stacked under the Google unit at opacity 0 so the 90px space is reserved. Fades in only if AdSense returns unfilled. First-party featured placements never show this. In astro dev, force it visible with /events/?wod_house_banner=1.

Snackbar

Short process update. One optional text action. No icons. role="status".

Saved to your plan

Badge

Progress