forms
Expandable Composer
A single-line composer grows into an attached multiline editing surface with tools and a submit path.
- forms
- composer
- textarea
- progressive
- editing
Progressive composer expansion; it is not a chat-specific component or modal.
Live preview
Quick usage
import { ExpandableComposer } from "@pinky-ui/systems";
<ExpandableComposer value={draft} onValueChange={setDraft} onSubmit={send} />Presets
Default
Restrained production behaviour.
Default behaviour
Quiet
Reduced intensity for dense product screens.
disabled={true}
Install
Add @pinky-ui/systems as a dependency, or use the CLI to copy this component's source directly into your project — no dependency to manage, fully editable.
npm install @pinky-ui/systemspnpm add @pinky-ui/systemsyarn add @pinky-ui/systemsnpx pinky-ui add expandable-composerPrefer to run the whole repository locally instead?
git clone https://github.com/florash/Pinky-UI.git
cd Pinky-UI
npm install
npm run devProps
| Prop | Type | Default | Description |
|---|---|---|---|
| onSubmit | (value: string) => void | — | Called after an intentional submit from the expanded composer. |
| className | string | — | Styles the outer interaction surface. |
Accessibility
- The compact input and expanded textarea share one labelled composer region.
- Escape closes without discarding draft text; tools and submit remain keyboard reachable.
Performance
- The richer editor mounts only after focus or content intent and never opens a viewport-level overlay.
Reduced motion
Motion resolves immediately while semantics, focus and state remain unchanged.
When to use
- Comments, messages, notes and content creation that start as a small prompt
When not to use
- Full document editing or a modal workflow that needs route-level context
Skill
Purpose
Use Expandable Composer when a message, note or content prompt starts small and needs a richer editor only after intent increases.
Interaction
Begin with one attached line. Focus, typing or Enter opens the multiline surface in place; tools and submit actions appear below the draft. Escape closes the richer state without discarding text.
Usage
<ExpandableComposer value={draft} onValueChange={setDraft} onSubmit={send} />Accessibility
Use a labelled input or textarea, real buttons for tools and submit, and preserve the draft when the composer contracts. Do not turn the expansion into an unlabelled dialog.
Reduced motion
Resolve height and opacity immediately while keeping the richer editing surface, tools and submit path available.