Passer au contenu principal

FooterColumn

Implemented

Footer column with title + optional accent underline + vertical link list. Column sizing is owned by the parent Footer organism.

Categorymolecules
Sourcepatterns/molecules/footercolumn.html
AI HintLabeled link column for footers and nav contexts (NavGroup is deprecated — use this). Column sizing belongs to the parent Footer organism. All strings caller-owned; pair headingAs='3' with ariaLabel when embedding under a page H2.

One labelled navigation column for footer contexts: a semantic <nav aria-label> with a heading, an optional ADR-031 decorative accent underline, and a list of anchor links. All strings are caller-owned, so the molecule is bilingual-safe by construction. Column sizing is owned by the parent Footer organism's CSS grid.

FooterColumn

Navigation molecule (Footer family)

Renders title + links as a nav landmark with an overline heading. The heading element defaults to <h2> and is overridable via headingAs for embedded document outlines — the visual scale stays pinned to the overline treatment regardless of level.

This component supports light and dark mode.

Usage

import { FooterColumn } from '@epasslive/design-system'

// Default heading level (<h2>) — as composed by the Footer organism.
<FooterColumn
  title="Browse"
  accent="teal" // events identity (ADR-031)
  links={[
    { label: 'Events', href: '/events' },
    { label: 'Venues', href: '/venues' },
  ]}
/>

// Embedded context — demote the heading so it nests under an existing h2
// instead of injecting a sibling h2 into the page outline.
<FooterColumn
  title="Help"
  accent="indigo" // support identity (ADR-031)
  headingAs={3}
  links={[{ label: 'FAQ', href: '/faq' }]}
/>

Heading levels

  • Default is <h2> — correct for a standalone footer landmark. The [slug] docs outline is H1 (page) → H2 (sections), so this demo's second column uses headingAs={3}.
  • The visual scale never follows the level: the overline treatment (text-ep-sm uppercase tracking-wider) is kept at every level, mirroring the Heading atom's decoupled as/size contract.
  • Pick the level from the surrounding document outline, not from the desired visual size.

Accessibility

  • Semantic <nav aria-label> per column — each of several columns on a page is an independently labelled landmark; the label falls back to the visible title.
  • role="list" on the <ul> restores list semantics under Tailwind preflight.
  • Every anchor carries min-h-[var(--ep-tap-min)] (44px, WCAG 2.5.5) and a focus-visible ring (ring-ep-teal + ring-offset-ep-bg).
  • The accent underline is aria-hidden — decorative only (ADR-031 §4.3); the heading carries the semantics.

i18n contract

The molecule contributes zero strings: title, links[].label/href, and ariaLabel are all consumer props. The storefront consumer (SiteFooter) pulls every string from useTranslations("Footer"). Note: the heading carries truncate — very long FR titles can visually clip in narrow columns (screen readers still read the full text).

Composition

  • Composes the AccentUnderline atom for the decorative accent (ADR-031 identity mapping: events=teal, support=indigo, company=amber, newsletter=pink).
  • Composed by the Footer organism — one FooterColumn per navigation column. Column sizing and the responsive grid are owned by the organism, not this molecule.
  • Links are currently raw <a> anchors with the DS focus/tap recipe. Consolidation onto the TextLink atom (external href handling: rel="noopener noreferrer", new-tab announcement) is planned behind an ADR — until then, prefer internal hrefs or add rel at the consumer.
  • Boundary: NavGroup is deprecated (superseded by the sidebar) — FooterColumn is the live molecule for labelled link columns in footer/nav contexts.

Props

Prop
Type
Default
Description
title*
string
—

Heading rendered above the link list. Also used as the nav label when ariaLabel is omitted.

links*
ReadonlyArray<{ label: string; href: string }>
—

Links rendered in the column. Every string is caller-owned (i18n contract).

ariaLabel
string
—

Accessible name for the inner <nav>. Falls back to the visible title.

accent
'teal' | 'indigo' | 'amber' | 'pink'
—

Decorative AccentUnderline beneath the heading. Must attach to a stable identity per ADR-031 §3 (events=teal, support=indigo, company=amber, newsletter=pink) — never index % 4 cycling.

headingAs
1 | 2 | 3 | 4 | 5 | 6
2

Semantic heading level for the column title. Default 2 renders <h2>; pass 3 when embedding the column under an existing h2 section. Visual scale is decoupled — the overline treatment is kept at every level (Heading atom as/size contract).

id
string
—

Optional id for the inner nav. Auto-generated when omitted.

className
string
—

Extra utility classes appended to the nav.

Props

Preview

FooterColumn

Prop
Type
Required
Default
Description
ariaLabel
string
Optional
visible title

Accessible name for the inner <nav>; falls back to the visible title.

title
string
Required
—

Heading rendered above the link list (also the nav label fallback).

links
ReadonlyArray<{ label: string; href: string }>
Required
—

Link list — strings are caller-owned (bilingual-safe by construction).

accent
'teal' | 'indigo' | 'amber' | 'pink'
Optional
—

Decorative AccentUnderline below the heading — identity-stable per ADR-031 (events=teal, support=indigo, company=amber, newsletter=pink).

headingAs
HeadingLevel
Optional
2 (<h2>)

Semantic heading level for the title; visual scale stays pinned to the overline treatment regardless of level (use h3 in embedded contexts).

id
string
Optional
auto

Optional id for the inner nav; auto-generated when omitted.

className
string
Optional
—

Extra utility classes appended to the nav.

Quick use:<FooterColumn />

Accessibility

ARIA rolenavigation

ARIA

1 rule

WCAG 1.3.1

inner nav carries aria-label (explicit or the visible title); link list is a real <ul> with list semantics

Type

1 rule

NASA Rule 5

accent is identity-stable per column (ADR-031) — do not cycle accents by index%4

Usage

Import

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

Example 1

tsxSnippet
<FooterColumn title="Browse" accent="teal" links={BROWSE_LINKS} />

Example 2

tsxSnippet
<FooterColumn title="Newsletter" accent="pink" headingAs={3} ariaLabel="Newsletter links" links={NEWS_LINKS} />

Anti-patterns

— Do not cycle accents by index — accents are identity-stable per column (ADR-031)

— Do not hardcode column strings — pull labels from your i18n Footer namespace

Design System v4.1.0 | ePassLive