Passer au contenu principal

PackageCard

Implemented

Season/bundle package offer card on a teal-tinted surface — event-count eyebrow, title, short description, big total price with per-event breakdown line, inclusion list, and a choose CTA pinned to the card bottom. Static display organism (Family 7 Commerce, sibling of MerchCard): price strings are pre-formatted by the caller and every built-in string switches FR/EN via locale.

Categoryorganisms
Sourcecomponents/organisms/packagecard/PackageCard.tsx
AI HintUse for bundle/season-pass offers on storefront commerce surfaces (Family 7, sibling of MerchCard/SideCard). Fully presentational: no onChoose callback yet (the CTA Button has no onClick — ADR follow-up), price/perEventPrice are pre-formatted strings rendered verbatim, includes items are plain strings. locale switches every built-in string. Dormant organism — zero live consumers (verified 2026-09-14).

Carte forfait (5 evenements combines, prix effectif, inclusions). FR-CA : « 5 evenements · soit 49,60 $ par evenement · Choisir ce forfait ».

PackageCard

Organism - Commerce family (Family 7)

Carte verticale avec accent teal/5, prix effectif et liste d inclusions.

5 événements

Decouverte Jazz

Selection de 5 concerts parmi les mieux notes du Festival Jazz MTL.

248,00 $

soit 49,60 $ par événement

Inclusions

  • Concert Quartet 24 juin
  • Concert Hommage 28 juin
  • Concert Fusion 1 juillet
  • Concert Latin 3 juillet
  • Concert Final 5 juillet

5 événements

Soirees Lion d Or

5 galas du vendredi soir au Lion d'Or.

220,00 $

soit 44,00 $ par événement

Inclusions

  • Gala 2 mai
  • Gala 9 mai
  • Gala 16 mai
  • Gala 23 mai
  • Gala 30 mai

5 événements

Classique OSM

5 concerts symphoniques Maison symphonique.

380,00 $

soit 76,00 $ par événement

Inclusions

  • Beethoven n 5
  • Mozart Requiem
  • Brahms n 4
  • Stravinsky Sacre
  • Dvorak Symphonie n 9

This component supports light and dark mode.

Props

Prop
Type
Default
Description
id*
string
—

Identifiant du forfait.

title*
string
—

Titre.

description*
string
—

Description courte.

eventCount*
number
—

Nombre d evenements inclus.

price*
string
—

Prix total formate.

perEventPrice*
string
—

Prix par evenement.

includes*
string[]
—

Liste des evenements inclus.

locale
"fr" | "en"
—

Bascule toutes les chaines integrees (eyebrow singulier/pluriel, ligne par evenement, Inclusions/Includes, CTA). Defaut fr.

className
string
—

Classes supplementaires ajoutees a la racine (dimensionnement, ex. max-w-sm).

Props

Preview

PackageCard

Prop
Type
Required
Default
Description
id
string
Required
—

Unique per-card id; anchors the aria-labelledby wiring (pkg-${id} on the article and the h3 title, pkg-${id}-includes on the list label). Must be unique per rendered card on the page.

title
string
Required
—

Bundle title, rendered as the h3 heading that labels the article.

description
string
Required
—

Short body copy under the title.

eventCount
number
Required
—

Number of events in the bundle, rendered in the uppercase eyebrow with locale-aware singular/plural (fr « 1 événement / 5 événements », en « 1 event / 5 events »).

price
string
Required
—

Pre-formatted total price string (e.g. « 248,00 $ ») rendered verbatim at 2xl tabular-nums — the organism does no currency formatting.

perEventPrice
string
Required
—

Pre-formatted per-event breakdown string rendered after « soit » / « only » in the xs line under the total.

includes
string[]
Required
—

Inclusion lines (event names / perks) rendered as the « Inclusions » / « Includes » bulleted list.

locale
"fr" | "en"
Optional
'fr'

Switches every built-in string: eyebrow noun + plural, « soit … par événement » / « only … per event », Inclusions/Includes label, Choisir ce forfait/Choose this package.

className
string
Optional
—

Extra classes appended to the root article (layout sizing, e.g. max-w-sm).

Quick use:<PackageCard />

Accessibility

ARIA rolearticle

ARIA

2 rules

WCAG 1.3.1

Article labelled by its title heading: aria-labelledby="pkg-${id}" on the root article pointing at the h3 id — id must be unique per rendered card

WCAG 1.3.1

Includes list programmatically labelled by its heading: <ul aria-labelledby="pkg-${id}-includes"> wired to the Inclusions/Includes label id

Contrast

2 rules

WCAG 1.4.3

Eyebrow: --ep-text-teal token on the teal/5 card — 5.50:1 light (#00708A); dark: the token itself swaps to #009FCA (4.75:1 on dark card). Per-event line and Inclusions label use text-body on both themes (7.30:1 / 8.18:1)

WCAG 1.4.3

Choose CTA: text-inverse on btn-primary 5.70:1, hover 8.26:1 light / 4.64:1 dark — theme-stable AA

i18n

1 rule

DS i18n convention (locale prop)

Toutes les chaînes FR/EN miroirées via locale prop, y compris le singulier/pluriel de l'eyebrow (1 événement / 5 événements, 1 event / 5 events)

tap

1 rule

WCAG 2.5.5

CTA uses the DS Button atom (size md) whose min-height is pinned to --ep-tap-min 44px

Usage

Import

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

Example 1

tsxSnippet
<PackageCard id="pkg-jazz" title="Forfait Découverte Jazz" description="Cinq concerts parmi la série estivale." eventCount={5} price="248,00 $" perEventPrice="49,60 $" includes={["Concert Quartet Latin 24 juin", "Concert Hommage 28 juin"]} />

Example 2

tsxSnippet
<PackageCard {...props} locale="en" className="max-w-sm" />

Anti-patterns

— Do not expect onChoose/onAddToCart callbacks or an expandable tickets section — the package/isExpanded/onToggle/onAddToCart/currency API was a franken-catalog artifact, never implemented (removed from docs 2026-09-14)

— Do not pass raw numbers to price/perEventPrice — pre-formatted strings only, the caller owns currency formatting

— Do not reuse the same id across cards on one page — pkg-${id} anchors aria-labelledby wiring and DOM ids must be unique

Design System v4.1.0 | ePassLive