Molecules
90 composites of atoms — form fields, search selects, navigation items.
Composites of atoms. Form fields, search selects, navigation items, and other small interactive units.
Implemented
SelectionCard
Shows the entity a picker has selected, with a divided action rail on the trailing edge. Use when a chosen value needs confirming (two venues can share a name) or acting on (edit, clear). Composes Surface.
Open componentListbox
Inline ARIA selection widget with full keyboard support (WAI-ARIA Listbox pattern 1.2). Single and multiple selection modes, option groups, and custom option rendering.
Open componentRadioGroup
Radio group container — wraps Radio atoms with shared name, controlled value, roving tabindex, and arrow-key navigation. Provides role="radiogroup" semantics.
Open componentSearchSelect
Async typeahead search input with debounced server-side querying, optional inline create, keyboard navigation, and ARIA combobox semantics. Generic — takes a fetcher callback, not a hardcoded endpoint.
Open componentValuePropsStrip
Horizontal strip of 3-4 value proposition items with icon, heading, and description. Used in storefront landing pages to communicate trust signals (secure payment, instant delivery, etc.).
Open componentAccordion
Vertical stack of expandable sections. Single or multi-expand modes. Each header is a button with aria-expanded.
Open componentActivityItem
Activity feed row — a semantic <li> with an 8px tone dot, a bold actor name, action text and a muted relative time in a <time> element. Consumers own the surrounding list (and any aria-live region).
Open componentAlert
Inline alert (success, error, warning, info) — distinct from Banner. Used for form validation, system messages.
Open componentAvatarGroup
Stacked avatar list — up to max (default 3) initial circles overlapping by -8px, remaining members collapsed into a "+N" overflow chip. The wrapper is a single role="img" with one accessible description. Used for attendees, collaborators, team members.
Open componentBadgeGroup
Cluster of removable label badges with overflow handling. Renders its own label chips — does not compose the Badge atom.
Open componentBreadcrumbs
Hierarchical path indicator with separator. Last item is current page (aria-current='page'). variant='bar' absorbs the former BreadcrumbBar molecule (Wave 3 Tier-1 / L2-M3).
Open componentButtonGroup
Group of related buttons with role=group semantics. Declarative items mode (array of ButtonGroupItem with optional icon + hidden) or slot mode (caller-provided children). Aligns start/end, wraps responsively.
Open componentColorPicker
Per-event brand color picker — a controlled native color input with an optional preset palette row. Replaces legacy color-picker.xsl. API under revision: preset palette rendering and keyboard navigation are not yet implemented.
Open componentCopyButton
Button that copies a value to clipboard and shows a brief checkmark + 'Copied' feedback. Uses navigator.clipboard API.
Open componentDatePicker
Native <input type="date"> wrapper with ISO value normalization — accepts string | Date, emits yyyy-mm-dd strings. The browser owns the calendar popup, keyboard navigation and locale formatting.
Open componentDateRangePicker
Controlled pair of native date inputs (start → end) for range capture. Live onChange emits { start, end } when either input changes. Container is role='group' labelled by the visible label (htmlFor → start input) or ariaLabel fallback; each input carries its own accessible name from startLabel/endLabel. Error is aria-describedby-wired + aria-invalid on inputs. Not a calendar — for dashboard range filters use StatisticsDateFilter; for visual month-grid use Calendar.
Open componentEmptyState
Empty/zero-state placeholder — icon slot + required title + optional description and action node. default/compact/centered/info variants. The fleet's most-consumed molecule (lists, tables, search results).
Open componentHeroSearch
Homepage hero search — GET form (what + where) with a submit button; stacks vertically on mobile. An optional third « Quand » segment (ADR-057) renders when whenPlaceholder is supplied. Either field can be turned into a DS combobox with the optional onSearch (What) / onLocationSearch (Where, ADR-074) / onSelectSuggestion / suggestionLabels API; the outer GET form always stays the no-JS fallback.
Open componentLanguageSwitcher
EN/FR bilingual toggle with instant language switch — inline EN | FR pair (header default) or compact single button showing the target locale (ADR-038: fab retired). Controlled and stateless: the consumer owns URL-segment navigation and the document language.
Open componentNewsletter
Newsletter signup molecule (ADR-069 / plan T5): first name, last name, email, Canadian postal code, a persona choice (buyer / organizer), optional interest options and a required consent checkbox. Ships ZERO hardcoded copy — every title, label, placeholder, CTA, success/error message and the consent string is a prop. The consent box is unticked by default (Law 25 / GDPR). Used in the storefront footer modal and dedicated landing blocks.
Open componentNewsletterSlotTrigger
Newsletter slot trigger (ADR-069 / plan T6, decision D17): a tiny client component that renders a real <button type="button"> and dispatches the DOM CustomEvent 'ep:newsletter-open' on window (detail: { source }). It bridges the server/client boundary for server-rendered slots such as FooterStub, where a function prop cannot cross — the consumer listens for the event and opens its modal. Ships no hardcoded copy: the CTA label and the accessible name are props.
Open componentNotification
Notification item — avatar/icon + title + body + timestamp + unread dot. Used in notification dropdown and feed.
Open componentPagination
Page-number navigator with prev/next — button pager by default, <a href> SEO mode via href. Computes totalPages from totalItems/pageSize and hides itself when there is ≤1 page.
Open componentLoadingOverlay
Non-dismissible busy treatment — covers a region or the viewport, blocks interaction and announces what is happening. Reuses the Modal scrim family. Not a dialog: no close, no focus trap.
Open componentProgressBar
Horizontal progress indicator — 6px height, 3px radius. Fill is teal→blue gradient. ARIA progressbar with valuenow/min/max.
Open componentPromoCodeValidator
Promo-code entry molecule with an embedded async validation state machine (idle → validating → valid / invalid). Renders input + Apply + a live-region feedback line; the result is a {valid, message} text line — no discount/expiry/terms display. Used in checkout.
Open componentRating
Star rating display + input. Read-only (display) or interactive (input). 5 stars by default, half-stars supported.
Open componentRefundStatusTracker
Read-only refund-progress tracker for order history — status pill + summary line (id, dates, reason) + 5-stage linear track with terminal rejected branch; live-region announcement; consumer-supplied localized labels.
Open componentRichTextEditor
Rich text editor for event descriptions. Replaces TinyMCE. TipTap/Lexical wrapper.
Open componentSkipLink
Skip-to-main-content link. Hidden off-screen at top:-40px, slides down on focus. WCAG 2.4.1 Bypass Blocks.
Open componentSlider
Range slider — single or dual thumb. 4px track, 20px thumb. Keyboard arrow keys, ARIA slider pattern.
Open componentStatCard
KPI metric card — 40×40 colored icon + trend pill + 28px/800 value + 12px muted label. White card with 1px border, hover lift -2px + card shadow.
Open componentStepper
Horizontal step indicator — 3-6 steps with state (complete/current/upcoming). Used in checkout, multi-step forms, onboarding.
Open componentTabs
Horizontal tab group with underline indicator. WAI-ARIA tabs pattern: role='tablist', roving tabindex, ArrowLeft/Right to navigate. variant='href' renders the former TabsTrigger link-mode strip (anchor or button tabs, underline or pills appearance) — TabsTrigger was merged into Tabs (Wave 3 Tier-1, L3-M3).
Open componentThemeInitScript
Pre-hydration FOUC prevention script — server-rendered blocking inline <script> that reads a localStorage theme key (plus optional legacy keys, in read order) and stamps data-theme on <html> before first paint. Consolidates the storefront (DS-CORR-09-07), client-portal (DM-09) and docs-shell (DM-08) copies (W2).
Open componentTimePicker
Typeable time combobox over a 15-minute grid (separate from date). Used for event start time, doors time, and any range with min/max. E11-INTK-1 rewrite — the list opens on click/focus and the field accepts free text (`7:30 pm`, `1930`, `19:30` all normalise to `19:30`). Out-of-range options are GREYED rather than hidden so the producer sees the constraint.
Open componentToast
Ephemeral notification card — 4 variants (success/info/warning/error). Card-only: positioning, stacking and dismissal timing belong to the consuming container (no DS container molecule yet). error announces via role='alert' + aria-live='assertive'; the other variants via role='status' + aria-live='polite'.
Open componentTooltip
Hover/focus tooltip portaled to document.body as a <div role='tooltip'> (role='dialog' when interactive), linked to its single trigger via aria-describedby. No show/hide delay exists and the portaled surface is positioned against the viewport, not the anchor — surface positioning is being overhauled (tracked).
Open componentWidgetCard
Generic dashboard card surface — header (title + subtitle + right-aligned action slot) over a body slot, optional footer after. Variants: chart (bordered, 16px rhythm), side (borderless rail, 14px rhythm), accent (theme-stable dark surface + inverse text).
Open componentSearchBar
Thumb-zone search trigger for mobile layouts (HV2 / R5, ADR-058). A plain button (no state, no navigation) that opens the DS SearchSheet; carries the 56px bar height, the 44px tap-target floor and a semantic focus ring (ADR-071: outset recipe with ring-offset-ep-bg). Pairs with SearchSheet; the consumer owns what 'open' does.
Open componentCategoryChip
One primary event-category filter chip (SEARCH-03). Presentation only: composes the Chip atom, so it inherits the native-button contract, aria-pressed, the 44px tap target and the theme-stable selected colours. Data, i18n and routing live in the consumer.
Open componentCategoryChipRow
Single-select event-category chip row (SEARCH-03, Pattern A: one category per event). Owns layout, the aria group and the All semantics; the consumer owns data, i18n and navigation. Selecting the active category or All reports null.
Open componentCityChip
One city in the multi-select city facet (SEARCH-05). Presentation only: composes the Chip atom and optionally announces the result count. Cookie, URL and navigation stay in the consumer.
Open componentCitySelector
Multi-select city facet (SEARCH-05, ADR-055). All-cities chip clears the selection, toggling the last city off returns to All, and the selection is capped (default 5) with unselected chips disabled at the cap. Router-agnostic and i18n-free: the consumer injects copy, cookie persistence and URL updates. Handles loading, empty and error+retry states.
Open componentMenu
Dropdown command list. Context menu or navigation menu with items, separators (item.divider), custom content rows (item.content — search fields, rich blocks), and submenus. Header's responsive MoreMenu overflow composes this molecule (L8b, Wave 3 Tier-2).
Open componentFormSection
Dashboard form section with title + description + sibling divider. Replaces the um-form-section CSS layout system.
Open componentFormRow
Dashboard form row layout — flex-wrap row with a tokenized gap, replaces um-form-row CSS. Wraps when children no longer fit but does NOT stack on narrow viewports; use ResponsiveFieldGroup for mobile-first stacking.
Open componentSettingsPanel
A settings surface's full anatomy: optional panel title, a stack of titled concerns (rendered through FormSection) and an optional actions footer. Chrome-less composition extracted from the 11 dashboard/portal sites that hand-rolled it.
Open componentAudioPlayer
Inline audio player — custom compact/expanded UI with play/pause, seek via keyboard (Space, ←→ ±5s, ↑↓ volume), and an error fallback alert. No pointer scrubbing yet (slider is keyboard-only). Autoplay is guarded by prefers-reduced-motion and gesture-blocked autoplay currently surfaces as the error state (tracked).
Open componentCardGrid
Responsive grid wrapper that renders an array of items as cards via a caller-supplied render function. Supports 1–4 columns and three gap scales, with an empty-state message when the list is empty.
Open componentCategoryPill
Ticket-category pill (Diamond, Platinum, Silver, Gold, CAT 1/2/3). Distinct from StatusBadge (state) — encodes categorization only. Tints derived via color-mix() from existing CSS variables so dark-mode adapts automatically.
Open componentFilterChipGroup
Filter row composing the Chip atom. Active chips use the canonical DS selected-control idiom (theme-stable 5.70:1 contrast). Supports single- and multi-select modes; optional count badges are announced by SR.
Open componentSearchInput
WAI-ARIA combobox with a grouped Top-N typeahead (SEARCH-04, ADR-049). The DS owns debounce, keyboard navigation (ArrowUp/Down, Enter, Escape), aria-activedescendant and the loading/empty/short-query states; the consumer supplies onSearch and receives grouped suggestions. Renders a real GET form, so search still works without JavaScript. ADR-071: the chromeless variant owns its field-level ring (`ring-offset-ep-bg`) as the blessed HeroSearch-style indicator; the boxed (non-chromeless) variant rings the input box itself — never nest either inside a parent focus-within ring.
Open componentFooterColumn
Footer column with title + optional accent underline + vertical link list. Column sizing is owned by the parent Footer organism.
Open componentImageUploader
Image picker with currentSrc preview (the persisted image IS the control — click to replace), variant=avatar (96px circular slot with initials fallback), and an optional inline remove control. Absorbs the removed AvatarUploader and FileDropzone molecule surfaces (D1 dedup merge).
Open componentMarkdownRenderer
XSS-safe Markdown-subset → HTML renderer (h1-h3, bold/italic, inline+block code, ul/ol, blockquote, safe links; no images/tables). Raw HTML inside content is escaped FIRST. Allowlist for links: http(s), mailto, /, #, ./, ../ (javascript: stripped). html mode renders pre-sanitized HTML verbatim.
Open componentMediaGallery
Responsive image+video gallery grid (2/3/4 columns). Tiles become full-size buttons when onSelect is provided; video tiles show a centered play indicator. Empty state renders a role='status' message.
Open componentPaymentMethodCard
Saved-payment-method display card: brand label + last4 + expiry, with an optional default badge, Set-default action and Remove action. Compact wallet row — supersedes the deprecated paymentmethod (selection semantics live there, not here).
Open componentProgressUpload
Per-file upload row: file icon + name + size, an inline status-colored bar (not composed of ProgressBar — composition refactor tracked), a percent/status readout, and ghost-button Cancel/Retry actions gated on status. uploading/done/error/paused states; error renders a role='alert' message and paused differentiates with a warning-tinted bar.
Open componentResponsiveFieldGroup
Horizontal form fields that auto-stack on narrow viewports. Wraps each child in a min-w-0 flex slot so flex children can shrink below their intrinsic content width — fixes the 129-167% horizontal overflow on 375 px viewports.
Open componentTableToolbar
Composing molecule: search input (44px-hit clear button) + filter chip group + optional trailing slot + conditional bulk actions, wrapped in role=toolbar. Every announced string has an EN default plus an i18n port (filtersLabel, clearSearchLabel, bulkActionsLabel).
Open componentTextFormatToolbar
Formatting toolbar (bold/italic/underline/strikethrough/h1/h2/h3/ul/ol/link/quote/code/undo/redo) for contentEditable surfaces. Roving-tabindex keyboard nav (ArrowLeft/Right wrap, Home/End), per-command localized aria-labels via labels, 44px tap hit-rects (--ep-tap-min) with 32px visuals, Phosphor glyphs for link/quote/lists/undo/redo. Each button is a real <button> and onMouseDown preventDefault preserves the caret position.
Open componentVideoPlayer
Video playback frame wrapping native <video controls> with aspect-ratio enforcement (16:9, 4:3, 1:1), poster, loading skeleton, and error fallback. Keyboard: Space (play/pause), ←/→ (seek ±5s), ↑/↓ (volume ±0.1), f (fullscreen), c (captions toggle — case-insensitive). prefers-reduced-motion guard blocks autoplay. Error state (role=alert) on playback failure.
Open componentCalendar
Standalone month-grid calendar with click-to-select, roving-tabindex keyboard navigation (arrows/PageUp/PageDown/Home/End/Enter), min/max/disabled dates, and overridable labels (English defaults; Monday-first). Optional range mode (selectionMode='range' + range/onChangeRange, hero « Quand » picker, ADR-068 amendment): first click sets the start, same-day second click completes a single-day range, later-day second click completes the range, earlier-day restarts it; hover previews the pending range. For locale-aware date entry use DatePicker (native UA widget); for dashboard range filters use StatisticsDateFilter.
Open componentCommandMenu
Portal command palette with keyboard navigation and shortcut registration. Real implementation; the organisms/commandmenu stories twin was removed per ADR-035.
Open componentDrawer
Side panel dialog (portal, scrim, Escape, scroll-lock). Always renders a header row — title <h2> left, close IconButton right — above a scrolling body (flex column, flex-1 overflow-y-auto). Placements left/right, sizes. Real implementation; the organisms/drawer stories twin was removed per ADR-035.
Open componentModal
Centered dialog (portal, scrim, Escape, focus trap, restore-focus, topmost-ESC stacking, 85vh panel scroll, configurable scrim, sizes, footer slot). Composes the Modal molecule for dialog chrome.
Open componentSidebar
Vertical navigation sidebar with grouped items, active-state indicator (aria-current), and a built-in mobile drawer (portal + scrim + focus trap + Escape + scroll lock). Persistent at >= breakpoint; overlay drawer below it. Real implementation; the organisms/sidebar stories twin was removed per ADR-035.
Open componentPlanned
- ArtistCard— Performer/artist card — circular image, name, role, follow button. Used in event detail and artist pages.
- DateBadge— Square date label — 16px/800 day on top, 9px/700 uppercase month below. Positioned absolute top-left of EventCard thumbnail. White bg + card shadow.
- QuickBuyBar— Sticky quick-buy bar at bottom of event page — event name, date, price from, and 'Buy Now' CTA. Appears on scroll past hero. Critical UX pattern: 3-click purchase flow.
- VenueCard— Venue preview — image, name, address, capacity, link to venue page. Static, server-rendered.
- WaitlistJoinForm— Waitlist join form for sold-out events — email input, notification preference, and join button.
- WillCallPicker— Will-call ticket pickup selector — choose pickup location, date, and time slot. Shows ID requirements. Critical UX pattern: will-call pickup.