Default
import { PixelTextarea } from '@pxlkit/ui-kit';
export function Default() {
return (
<PixelTextarea
label="Notes"
placeholder="Write something..."
hint="Up to 280 characters."
/>
);
}Multi-line text input with label, hint, error chrome plus optional auto-grow and character counter.
value + onChange (React), v-model (Vue), [(value)] or forms (Angular) — or uncontrolled with defaultValueimport { PixelTextarea } from '@pxlkit/ui-kit';| Prop | Type | Default | Description |
|---|---|---|---|
label | string | — | Floating label rendered above the textarea. |
hint | string | — | Helper text shown below the field. Hidden when error is set. |
error | string | — | Error message shown below the field; flips visual state to invalid. |
tone | 'green' | 'cyan' | 'gold' | 'red' | 'purple' | 'pink' | 'neutral' | 'neutral' | Visual tone for focus ring + border emphasis. Default: 'neutral'. |
surface | 'pixel' | 'linear' | — | Surface variant. Inherits from PxlKitSurfaceProvider when omitted. |
autosize | boolean | — | Auto-grow the textarea with content (between minRows and maxRows). |
minRows | number | 3 | Minimum visible rows when autosize is on. Defaults to 3. |
maxRows | number | — | Max rows before scrolling. Optional cap. |
showCount | boolean | { max?: number } | — | Render a character counter under the textarea. true shows N; { max } shows N/max. |
Also takes the native attributes and event handlers of <textarea> (TextareaHTMLAttributes<HTMLTextAreaElement>).
ref points to <textarea>.
WCAG target: 2.1 AA
textboxWraps a native <textarea> so multiline textbox semantics are announced by assistive tech automatically. The label prop is wired through FieldShell, error toggles aria-invalid, and the hint/error it shows is exposed via aria-describedby, after any ids you pass. The counter uses aria-live="polite" so screen readers announce updates without stealing focus.
| Key | Action | When |
|---|---|---|
| Tab | Moves focus into and out of the textarea | — |
| Enter | Inserts a newline within the textarea | — |
| Shift+Tab | Moves focus to the previous focusable element | — |
import { PixelTextarea } from '@pxlkit/ui-kit';
export function Default() {
return (
<PixelTextarea
label="Notes"
placeholder="Write something..."
hint="Up to 280 characters."
/>
);
}import { PixelTextarea } from '@pxlkit/ui-kit';
export function Default() {
return (
<PixelTextarea
label="Notes"
placeholder="Write something..."
hint="Up to 280 characters."
/>
);
}import { PixelTextarea } from '@pxlkit/ui-kit';
export function Uncontrolled() {
return (
<PixelTextarea
label="Bio"
defaultValue="Frontend engineer focused on retro UIs."
hint="Edit freely."
/>
);
}import { useState } from 'react';
import { PixelTextarea } from '@pxlkit/ui-kit';
export function Controlled() {
const [value, setValue] = useState('');
return (
<PixelTextarea
label="Message"
value={value}
onChange={(e) => setValue(e.target.value)}
placeholder="Type to see live updates..."
hint={`${value.length} chars`}
/>
);
}import { PixelTextarea } from '@pxlkit/ui-kit';
export function Tones() {
return (
<div className="flex flex-col gap-3">
<PixelTextarea label="Neutral" tone="neutral" defaultValue="Neutral tone" />
<PixelTextarea label="Green" tone="green" defaultValue="Green tone" />
<PixelTextarea label="Cyan" tone="cyan" defaultValue="Cyan tone" />
<PixelTextarea label="Gold" tone="gold" defaultValue="Gold tone" />
<PixelTextarea label="Red" tone="red" defaultValue="Red tone" />
<PixelTextarea label="Purple" tone="purple" defaultValue="Purple tone" />
<PixelTextarea label="Pink" tone="pink" defaultValue="Pink tone" />
</div>
);
}import { PixelTextarea } from '@pxlkit/ui-kit';
export function Surfaces() {
return (
<div className="flex flex-col gap-3">
<PixelTextarea label="Pixel surface" surface="pixel" defaultValue="Chunky pixel chrome" />
<PixelTextarea label="Linear surface" surface="linear" defaultValue="Sleek linear chrome" />
</div>
);
}import { PixelTextarea } from '@pxlkit/ui-kit';
export function WithError() {
return (
<PixelTextarea
label="Feedback"
defaultValue=""
error="Feedback is required."
placeholder="Tell us what went wrong..."
/>
);
}import { PixelTextarea } from '@pxlkit/ui-kit';
export function Disabled() {
return (
<PixelTextarea
label="Locked notes"
disabled
defaultValue="Cannot edit this field"
/>
);
}import { useState } from 'react';
import { PixelTextarea } from '@pxlkit/ui-kit';
export function Autosize() {
const [value, setValue] = useState(
'Type more lines to watch this grow.\nIt will expand between minRows and maxRows.',
);
return (
<PixelTextarea
label="Auto-grow"
autosize
minRows={2}
maxRows={8}
value={value}
onChange={(e) => setValue(e.target.value)}
/>
);
}import { useState } from 'react';
import { PixelTextarea } from '@pxlkit/ui-kit';
export function WithCharCount() {
const [value, setValue] = useState('Short blurb');
return (
<PixelTextarea
label="Short bio"
value={value}
onChange={(e) => setValue(e.target.value)}
showCount={{ max: 140 }}
placeholder="Up to 140 characters"
/>
);
}import { PixelTextarea } from '@pxlkit/ui-kit';
export function Required() {
return (
<PixelTextarea
label="Required"
required
placeholder="This field is required"
hint="Don't leave it blank."
/>
);
}