Skip to content

feat(textarea): add Textarea atom (no variants, sm/md/lg, aria-invalid)#53

Merged
dgraciac merged 1 commit into
mainfrom
feat/textarea-atom
Apr 28, 2026
Merged

feat(textarea): add Textarea atom (no variants, sm/md/lg, aria-invalid)#53
dgraciac merged 1 commit into
mainfrom
feat/textarea-atom

Conversation

@dgraciac
Copy link
Copy Markdown
Member

Summary

Adds the Textarea atom — multi-line text input that completes the form-control sibling pair started by Input (0.6.0). Same chrome (border tone, focus ring, inline padding per size, aria-invalid error state), same composition philosophy (Escuela 1 / D11: no error / helperText / icon-slot props on the atom; the consumer composes <label>, helper, and error message — the future <Field> molecule will encapsulate that pattern).

  • Three size values (sm / md / lg). Inline padding and font-size per size are identical to Input's, so a <Textarea> lines up flush with <Input> controls in the same form.
  • Vertical dimension uses min-height (~3-4 lines at the size's font-size) instead of a fixed height. resize: vertical lets the user drag the bottom edge to grow it; consumers can override via style.resize if needed.
  • Error state via aria-invalid="true" (CSS reacts to the attribute selector), matching shadcn / Base UI / Mantine and the Input atom.
  • No useRender polymorphism — <textarea> has no meaningful render-as use-case, same reasoning as Input.
  • Resting border --pharos-color-neutral-500 (~5.4:1 vs white) — same WCAG 1.4.11 fix that landed for Input / Button-secondary / Badge-outline in 0.6.0.

API

import { Textarea } from '@code-sherpas/pharos-react';

<Textarea size="md" placeholder="Tell us…" />
<Textarea aria-invalid="true" defaultValue="Too short." />
<Textarea disabled defaultValue="Read-only-ish" />
<Textarea rows={5} />            // native attr passthrough
<Textarea ref={textareaRef} />   // ref forwarded to <textarea>

TextareaProps extends ComponentProps<'textarea'> plus the typed size axis. No native attribute is shadowed (unlike Input, which reuses the size slot — <textarea> has no native size attribute).

Storybook

Components/Textarea: Playground, Default, Disabled, ReadOnly, Invalid (aria-invalid), WithLabel (composition pattern), Matrix (sizes × states grid).

Test plan

  • pnpm typecheck — clean.
  • pnpm lint — clean.
  • pnpm format:check — clean.
  • pnpm build — Vite library build + verify:dist-types smoke pass.
  • pnpm test — 79 tests across 6 files, 0 failures (10 new Textarea tests).
  • Chromatic baseline — published by CI on push; manual approval required for the new Textarea story snapshots.
  • CI checks on PR.

Out of scope

  • Adoption in alexandria-web-application — separate PR, opens after this one publishes (0.8.0) and after currently open Alexandria PRs are settled. The shared formFieldBaseClasses + Textarea.tsx local component are the swap target.
  • <Field> molecule that wires <label> + <Textarea> + helper / error message slot. Planned post-Select / SearchSelect.
  • field-sizing: content auto-grow — interesting CSS proposal but not yet broadly supported; deferred.

🤖 Generated with Claude Code

Multi-line text input that mirrors Input's chrome — neutral-500 resting
border (WCAG 1.4.11), shared focus ring, identical inline padding per
size. No `variant` axis (composition Escuela 1, D11): error state via
`aria-invalid="true"`, message rendered consumer-side.

Three `size` values (sm/md/lg) align inline padding + font-size with
Input so a textarea sits flush next to inputs in the same form. Vertical
dimension uses `min-height` (~3-4 lines at the size's font-size) plus
`resize: vertical` so users can drag to grow it; consumers can override
via `style.resize`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@chromatic-com
Copy link
Copy Markdown

chromatic-com Bot commented Apr 28, 2026

Tip

All tests passed and all changes approved!

🟢 UI Tests: 7 visual and accessibility changes accepted as baselines
🟢 UI Review: Approved by David Gracia
Storybook icon Storybook Publish: 46 stories published

@dgraciac dgraciac merged commit 1eab57c into main Apr 28, 2026
10 checks passed
@dgraciac dgraciac deleted the feat/textarea-atom branch April 28, 2026 22:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant