Skip to main content

ValuePropsStrip

Implemented

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.).

Categorymolecules
Sourcesrc/components/molecules/valuepropsstrip/ValuePropsStrip.tsx
AI HintMarketing trust strip for landing pages: 3-4 icon-led value propositions (secure payment, instant tickets, mobile wallet, refund guarantee). Data-in API — pass items array, no render props. Distinct from CardGrid (render-prop generic grid) and StatGrid (KPI numbers). Non-interactive: no href/onItemClick by design.

Horizontal strip of 3-4 value proposition items with icon, heading, and description.

ValuePropsStrip

Content & Layout — molecule

Icon-led marketing trust strip beneath heroes: bounded 3-4 items, region landmark with a required accessible name.

  • Secure payment

    Encrypted checkout on every order.

  • Instant tickets

    Scan-ready passes the moment you pay.

  • Mobile wallet

    Tickets and receipts in one place.

  • Refund guarantee

    Clear refunds on every purchase.

ValuePropsStrip — compact

Content & Layout — molecule

Compact variant: same responsive ladder, one-step smaller type scale (text-ep-xs), tighter rhythm (py-6/lg:py-8, gap-6/md:gap-8, 32px icon chip) for dense surfaces such as checkout panels.

  • Secure payment

    Encrypted checkout on every order.

  • Instant tickets

    Scan-ready passes the moment you pay.

  • Mobile wallet

    Tickets and receipts in one place.

Usage

Data-in molecule: pass 3-4 typed items plus the required ariaLabel. Icons are Phosphor components imported per-icon from @phosphor-icons/react/dist/ssr (ADR-022) and render filled (weight="fill") on the teal chip.

import { ShieldCheck, Ticket, Wallet, Receipt } from "@phosphor-icons/react/dist/ssr";
import { ValuePropsStrip } from "@epasslive/design-system";

const valueProps = [
  { icon: ShieldCheck, heading: "Secure payment", description: "Encrypted checkout on every order." },
  { icon: Ticket, heading: "Instant tickets", description: "Scan-ready passes the moment you pay." },
  { icon: Wallet, heading: "Mobile wallet", description: "Tickets and receipts in one place." },
  { icon: Receipt, heading: "Refund guarantee", description: "Clear refunds on every purchase." },
];

// Default — 4 items beneath a hero
<ValuePropsStrip items={valueProps} ariaLabel="Why ePassLive" />

// Compact — 3 items on a dense surface
<ValuePropsStrip items={valueProps.slice(0, 3)} variant="compact" ariaLabel="Event benefits" />

Bounds

items.length must be 3-4, enforced at runtime. In development the component throws Error("ValuePropsStrip: items.length must be 3-4, got N"); in production it logs console.warn("[ValuePropsStrip] items.length must be 3-4, got N — rendering nothing.") and renders nothing. Do not pass 2 items — the guard fires by design (a two-item caption is a Caption, not a ValuePropsStrip). No out-of-bounds example is rendered live here on purpose: it would throw in dev and take this page down.

Responsive

One breakpoint, two layouts — no intermediate tablet grid. Below md: stacked single column, icon left of text. At md and up: horizontal 3-4-up row, icon above text. The compact variant uses the same ladder with a one-step smaller type scale (text-ep-xs vs text-ep-sm), tighter padding, tighter gaps and a 32px icon chip.

Accessibility

  • The root is a role="region" landmark named by the required ariaLabel prop.
  • Items render as a real ul / li list, so screen readers announce the item count.
  • Icons are decorative (aria-hidden — the PhosphorIcon atom default); the heading carries the meaning.
  • No aria-live by design — static content must not be a live region.
  • Contrast meets WCAG AA in both themes: heading text-ep-text-heading and description text-ep-text-muted (5.49:1) on bg-ep-surface-card; icon glyph text-ep-text-teal (5.70:1) on bg-ep-teal/10.
  • Items are non-interactive — no focus targets. href / onItemClick are deliberately excluded from the API.
  • Reduced motion is respected: nothing animates by default.

Props

Prop
Type
Default
Description
items*
ValuePropsItem[]
—

3-4 value props, runtime-guarded (see Bounds). Each item: { icon: PhosphorComponent; heading: string; description: string } — icon is the Phosphor component imported per-icon from @phosphor-icons/react/dist/ssr (ADR-022). Heading 2-4 words; description up to 140 chars.

variant
"default" | "compact"
"default"

default: horizontal strip at md+ (icon above text), stacked below md (icon left of text). compact: same ladder with a one-step smaller type scale (text-ep-xs vs text-ep-sm) and tighter rhythm — py-6/lg:py-8, gap-6/md:gap-8, 32px icon chip — for dense surfaces.

ariaLabel*
string
—

Accessible name for the role="region" landmark. Required — unlike CardGrid, this strip is a named landmark. Examples: "Why ePassLive", "Event benefits".

className
string
—

Additional classes on the root element.

id
string
—

Stable root id; falls back to an SSR-safe useId() value.

Props

Preview

ValuePropsStrip

Prop
Type
Required
Default
Description
items
Array<{ icon: PhosphorIconComponent; heading: string; description: string }>
Required
—

3-4 value props (minItems=3, maxItems=4 per NASA Rule 2, runtime-guarded). Each item: icon (Phosphor component reference, per-icon import per ADR-022), heading, description.

variant
'default' | 'compact'
Optional
'default'

'default' = 1-col stacked below md, 3-4-up row at md+. 'compact' = tighter gaps + smaller icon chip for dense surfaces.

ariaLabel
string
Required
—

Required for region landmark. Examples: 'Why ePassLive' or 'Event benefits'.

className
string
Optional
—

Additional CSS classes for the root element.

id
string
Optional
—

Optional id for the root element.

Quick use:<ValuePropsStrip />

Accessibility

ARIA roleregion

Type

1 rule

NASA Rule 2

items must have minItems=3, maxItems=4 (NASA Rule 2; dev throws, prod warns + renders nothing)

ARIA

1 rule

WCAG 1.3.1, 4.1.2

Root must have role=region with aria-label from the required ariaLabel prop. Items as ul/li; icons decorative (aria-hidden). No aria-live on static content.

Usage

Import

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

Example 1

tsxSnippet
<ValuePropsStrip ariaLabel="Why ePassLive" items={[{ icon: ShieldCheck, heading: "Secure payment", description: "..." }]} />

Example 2

tsxSnippet
<ValuePropsStrip variant="compact" ariaLabel="Benefits" items={threeItems} />

Anti-patterns

— Do not hardcode data in molecules

— Avoid complex business logic in molecules

— Do not add aria-live — the strip is static content

— Do not pass icon name strings — pass Phosphor component references (ADR-022 tree-shaking)

Design System v4.1.0 | ePassLive