Workshop Kit · widget reference

Shipped

map-radius

Radius slider around the operator's address, with a visual neighborhood placeholder. The plan calls for pre-baked static map tiles at /brand/maps/ keyed by metro area; that tile-bake is a separate infrastructure task, so today the widget renders an SVG street-grid (seeded from a hash of the operator's address, so the same address always shows the same neighborhood layout). When real tiles arrive, the SVG can be swapped for a CSS background-image of the metro PNG without changing the widget's external contract.

Live demo

Drag the slider from 0.5 to 5 miles. The circle resizes; the summary text updates with car-minutes + walk-minutes equivalents (15 mph urban arterial average, 3 mph walking). If you've set a restaurant address in any other lesson, it shows below the map; otherwise a prompt deep-links to L10.

No config block — slider range fixed at 0.5–5 miles in 0.25 increments

Current MuntinContext.deliveryRadius Drag the slider above to write a radius…

Contract

BehaviorNotes
Reads restaurantProfile.address Display only — the widget never geocodes (no fetch). The address is hashed to seed the SVG street-grid layout so a given address always shows the same neighborhood pattern.
Reads deliveryRadius Initial slider position. Defaults to 1.5 miles.
Reads palette[0] Tints the radius circle + the address pin marker.
Writes deliveryRadius Number, miles, 0.5..5 in 0.25 increments. Used in L12 keyword phrasing and (eventually) in the L14 generator's schema markup.
Address arrives later If the operator finishes L10 (sets their address) after mounting this widget on L4, the widget re-renders the street grid + display address via the mtn:context-change subscription. No remount needed.
Time-equivalents Pure arithmetic — 15 mph for car (urban arterial average at dinner), 3 mph for walking. Reasonable rough orders of magnitude; not turn-by-turn estimates.

Markup

<section class="course-widget" data-widget="map-radius"></section>

No config block. The widget reads restaurantProfile.address + deliveryRadius from MuntinContext.

Accessibility

Why a street-grid placeholder, not a real map

Real map tiles need either a tile-server fetch (violates "no fetch") or pre-baked PNGs for every metro the operator could possibly be in (a real infrastructure task — picking a tile provider, building the asset pipeline, choosing which metros to cover, refreshing them periodically as cities change). Until that infra ships, the SVG street-grid conveys the only signal the lesson actually needs: scale. A diner glancing at "0.5 miles" vs "5 miles" sees the difference; they don't need to recognize their own street. The address-hash seeding means the placeholder is at least consistent — the same address always shows the same neighborhood pattern, which makes it feel intentional rather than random.

When the tile pipeline ships, the widget swap is one CSS rule: change .mrw-map to background-image: url("/brand/maps/" + metro + ".webp") and the placeholder SVG goes away. The radius circle, slider, address row, and context wire all keep working.

Where it ships

Source

/tools/_shared/workshop/map-radius.js — ~210 LOC. Exports { tag, contextKeys, mount, serialize }. The SVG street-grid is built by buildStreetGrid(addrHash, accent) at the top of the file; a future tile-based replacement would just swap that one function out. Time-equivalent helpers carMinutes() and walkMinutes() use simple constants documented in comments.

← Back to the Workshop Kit