Skip to main content

QuickBuyBar

Planned

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.

Categorymolecules
Sourcepatterns/molecules/quickbuybar.html
AI HintUse for grouped UI patterns. Combine atoms into functional units.

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.

QuickBuyBar

Commerce — Family 7 (planned)

Sticky quick-buy bar at the bottom of the event page: event name, date, a 'from' price and a Buy Now CTA that appears once the hero scrolls out of view.

Osheaga — Day 1

Sat Aug 1, 2026 · 14:00

from CA$89.50

2

Design reference mock — not a rendered component. The third row shows the planned TicketSelector composition (quantity stepper, barrel-exported organism) — not yet part of the canonical contract.

This component supports light and dark mode.

Status

Planned molecule — the React component is not yet implemented. Nothing is exported from the DS barrel; the render above is a design reference mock typed to the planned interface, not the component.

Composition targets (all barrel-exported, ready to compose): PriceTag (atom, variant="from-prefix", locale-aware Intl.NumberFormat) for the price display, Button (atom, size="lg", loading={isLoading}) for the Buy Now CTA, and TicketSelector (organism, value / onChange / min / max) for optional inline quantity selection. Do not use the Stepper molecule — it is a progress stepper (steps / currentIndex), not a quantity input.

Planned API

Sketch of the intended contract. Until the component ships, this is not importable code.

interface QuickBuyBarProps {
  eventName: string;
  eventDate: string;
  priceFrom: number;
  currency?: string; // 'USD' per patterns.ts — reconcile with PriceTag ('CAD')
  onBuyNow: () => void;
  isLoading?: boolean;
}

// Sketch — QuickBuyBar is planned and NOT exported from the barrel yet.
<QuickBuyBar
  eventName="Osheaga — Day 1"
  eventDate="Sat Aug 1, 2026 · 14:00"
  priceFrom={89.5}
  currency="CAD"
  onBuyNow={() => router.push('/checkout')}
  isLoading={false}
/>

The implementation composes existing atoms: PriceTag with variant="from-prefix" renders the locale-aware "from" price, and Button with size="lg" loading={isLoading} renders the CTA (44×44px tap target and aria-busy come from the atom). For optional inline quantity, compose the barrel-exported TicketSelector organism (value / onChange / min / max) — the Stepper molecule is progress-only and cannot serve as a quantity input.

When to use

  • Event detail pages, once the hero (with its own CTA) scrolls out of view.
  • The 3-click purchase flow: page → bar CTA → ticket selection.
  • Do not stack with another sticky bar (cookie / App banners) — reserve one sticky slot per viewport edge.

Known interface gaps

Recorded from the MOL-59 audit cascade. None block the catalog entry; each must be closed before real storefront wiring:

  • Missing locale prop — FR/EN CTA labels and price formatting (storefront uses Intl.NumberFormat with fr-CA / en-CA).
  • Currency default mismatch — patterns.ts documents 'USD'; PriceTag defaults 'CAD'; the whole platform is CAD.
  • No sold-out / sale-window state — EventTicketList computes soldOut / notOnSaleYet / saleEnded; a bar with only enabled / isLoading shows a live "Buy Now" for a sold-out event.
  • No overridable CTA labels — docs hardcode 'Buy Now'; storefront uses next-intl.
  • No privateLinkToken extension for private-link event pages.
  • No scroll-visibility / z-index contract — the retired mobile language FAB no longer competes for the overlay layer (ADR-038).
  • No mobile safe-area padding — zero env(safe-area-inset-bottom) usage in the monorepo.

Accessibility

Planned contract (no implementation exists to audit yet): the CTA exposes an aria-label including the event name (WCAG 4.1.2 — a patterns.ts assertion); the bar root is role="complementary"; the price is announced as one text token via PriceTag (WCAG 1.3.1), never color-only; the CTA keeps a ≥44×44px tap target (--ep-tap-min, WCAG 2.5.5) and sets aria-busy while loading; the sticky bar must not obscure content — the host reserves bottom spacing and keeps the bar's controls after the page content in DOM order so keyboard Tab order is predictable.

Props

Prop
Type
Default
Description
eventName*
string
—

Event title shown in the bar; also part of the Buy Now button's accessible name.

eventDate*
string
—

Event date label shown under the title (pre-formatted, locale-appropriate string).

priceFrom*
number
—

Lowest available ticket price in the currency's major unit; must be a positive number (NASA Rule 5).

currency
string
'USD'

ISO 4217 currency code forwarded to the price formatter. patterns.ts records 'USD'; the composed PriceTag atom defaults to 'CAD' — pass currency explicitly until the defaults are reconciled.

onBuyNow*
() => void
—

Fired when the Buy Now CTA is activated; the host routes to checkout / ticket selection.

isLoading
boolean
false

Forwards to the Button atom's loading — disables the CTA and sets aria-busy during the checkout transition.

Props

Preview

QuickBuyBar

Prop
Type
Required
Default
Description
eventName
string
Required
—
No description.
eventDate
string
Required
—
No description.
priceFrom
number
Required
—
No description.
currency
string
Optional
'USD'
No description.
onBuyNow
() => void
Required
—
No description.
isLoading
boolean
Optional
False
No description.
Quick use:<QuickBuyBar />

Accessibility

ARIA rolecomplementary

Type

1 rule

NASA Rule 5

priceFrom must be positive number

ARIA

1 rule

WCAG 4.1.2

Buy Now button must have aria-label with event name

Usage

Import

tsxSnippet
import { QuickBuyBar } from "@epasslive/design-system"

Example 1

tsxSnippet
<QuickBuyBar />

Example 2

tsxSnippet
<QuickBuyBar variant="default" />

Anti-patterns

— Do not hardcode data in molecules

— Avoid complex business logic in molecules

Design System v4.1.0 | ePassLive