Textarea
ImplementedMulti-line text input with fixed rows (default 4) and resize-y — it does NOT auto-grow. Optional char counter, helper text, and error state. Focus indication is painted directly via `focus:ring-2 focus:ring-ep-teal focus:border-ep-teal`; `focus:outline-none` suppresses the browser's default outline so a single focus indicator is visible. Same label/error/required contract as Input. Note: the props array below is partial — showCounter, helperText, error, and required are documented in the interface string but not yet mirrored as props rows.
patterns/atoms/textarea.htmlMulti-line text input with label, helper text, error state. FR-CA: Zone de texte multiligne.
TextArea
Interactive atom (Family 1 — Tier 1)
Always renders a visible label. Pair with a character counter when limits matter.
Champ requis
This component supports light and dark mode.
Interactive demo
0/280 caracteres
Usage
import { TextArea } from '@epasslive/design-system'
<TextArea label="Biographie" value={bio} onChange={setBio} rows={4} maxLength={280} helperText={`${bio.length}/280 caracteres` }/>Accessibility
- Native
<textarea>with htmlFor label association. - Helper + error bind via
aria-describeby. - Required adds an asterisk to the label and
aria-required.
Props
label*stringVisible and announced label.
value*stringControlled value.
onChange*(value: string) => voidChange handler.
placeholderstringPlaceholder text ✅ decorative only.
rowsnumber4Initial visible rows.
helperTextstringHelper copy.
errorstringValidation message announced via aria-describedby.
requiredbooleanfalseMarks the field required.
maxLengthnumberHard character limit.
ariaLabelstringOverride the announced label.
Props
Textarea
labelstring—valuestring—onChange(value: string) => void—<Textarea />Accessibility
Type
1 ruleARIA
1 ruleUsage
Import
import { Textarea } from "@epasslive/design-system"Example 1
<Textarea />Example 2
<Textarea variant="default" />Anti-patterns
— Do not compose atoms directly — use molecules instead
— Avoid inline styles on atoms