Skip to main content

FormLayout

Implemented

Multi-step wizard layout — vertical step rail (240 px, left) + step content panel (right) + optional footer CTA slot. Owns no <form>, no fields, no validation, no data: the route fills each step via children and drives navigation via steps/currentStepId/onStepChange. Bilingual rail heading via locale (default fr); step labels stay caller-localized. Dormant organism (no consumer yet).

Categoryorganisms
Sourcecomponents/organisms/formlayout/FormLayout.tsx
AI HintMulti-step wizard scaffold (checkout, onboarding, multi-page admin flows). Provide step content via children and drive currentStepId/onStepChange from route state — the organism owns no form element, no validation, no fetching. Footer slot hosts the CTA pair (DS Button atoms); omit onStepChange for a read-only progress rail; locale only switches the Étapes/Steps heading. For a single-page form with titled sections use FormSection molecules on a plain page; for a form inside a dialog use FormModal. Do NOT pass title/sections/onSubmit — that is the never-implemented legacy Ventixe form-scaffold API.

Squelette multi-étapes — rail latéral d'étapes et panneau de contenu, avec slot footer pour les CTA (démo : parcours d'achat en 4 étapes). FR-CA : « Étapes · Vos billets · Coordonnées · Paiement · Confirmation ».

FormLayout

Organism

Disposition deux colonnes : rail vertical d'étapes à gauche (240 px) avec coche pour les étapes complétées, contenu principal à droite. L'étape courante est marquée par aria-current="step".

Coordonnées de l'acheteur

Les billets seront envoyés à cette adresse courriel.

This component supports light and dark mode.

Props

Prop
Type
Default
Description
steps*
FormStep[]
—

Étapes du parcours.

currentStepId*
string
—

Étape active.

onStepChange
(id) => void
—

Navigation latérale (clic sur une étape).

children*
React.ReactNode
—

Contenu de l'étape.

footer
React.ReactNode
—

Pied de page (boutons Suivant / Précédent).

locale
"fr" | "en"
—

Bascule le heading du rail : « Étapes » (fr, défaut) / "Steps" (en). Labels caller-localisés.

className
string
—

Classes CSS additionnelles sur la racine <section>.

Props

Preview

FormLayout

Prop
Type
Required
Default
Description
steps
FormStep[]
Required
—

Ordered wizard steps for the left rail; each is { id, label, description? }. Array order is visual order; ids must be unique.

currentStepId
string
Required
—

id of the active step. The rail item gets aria-current="step" + teal tint; steps before it show the completed check.

onStepChange
(id: string) => void
Optional
—

Rail item click handler. Omit for a read-only progress rail (buttons render but do nothing).

children
React.ReactNode
Required
—

Content of the active step, rendered inside the right panel card.

footer
React.ReactNode
Optional
—

Footer slot at the bottom of the content panel (CTA row, e.g. Précédent/Continuer Button atoms); right-aligned above a top border.

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

Switches the section/rail heading: « Étapes » (fr) / "Steps" (en). Step labels and descriptions are caller-localized.

className
string
Optional
—

Additional CSS classes appended to the root <section> (spacing/width overrides).

Quick use:<FormLayout />

Accessibility

ARIA roleregion

ARIA

1 rule

WCAG 1.3.1

Root is <section aria-label="Étapes" (fr) / "Steps" (en)> (implicit region); rail is an <ol> of step <li> so screen readers announce position/total; active step button carries aria-current="step"; completed check glyph is aria-hidden

Keyboard

1 rule

WCAG 2.1.1

Every rail step is a native <button type="button"> (Tab/Enter/Space operable, focus-visible ring ep-btn-primary, min-height --ep-tap-min); no <form>, no error summary, no validation owned by this layout — the route owns form semantics

i18n

1 rule

WCAG 3.1.2

Heading switches Étapes/Steps via the locale prop (default fr); step label/description strings arrive localized from the caller

Usage

Import

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

Example 1

tsxSnippet
<FormLayout steps={[{ id: "tickets", label: "Vos billets" }, { id: "info", label: "Coordonnées", description: "Acheteur et destinataire" }, { id: "pay", label: "Paiement" }]} currentStepId="info" onStepChange={setStep} footer={<Button variant="primary">Continuer</Button>}>{stepContent}</FormLayout>

Example 2

tsxSnippet
<FormLayout steps={steps} currentStepId="pay" locale="en">{paymentForm}</FormLayout>

Anti-patterns

— Do not fetch data directly in organisms

— Avoid tight coupling to specific data sources

— Do not pass title/sections/onSubmit — legacy scaffold API that was never implemented here

Design System v4.1.0 | ePassLive