Textarea
A native multi-line text field with a label, description, status message and counter.
import { Textarea } from '@aksornproject/aksara-ui'Labelled field
label renders a <label> linked to the textarea, with a generated id unless you pass id. description renders under it. required sets native required and draws a star after the label. The native textarea owns value, defaultValue, onChange, validation and form submission, and ref is the HTMLTextAreaElement.
<div className="w-full max-w-spacing-384">
<Textarea
label="Feedback"
description="Tell us what to improve in this lesson."
name="feedback"
placeholder="Enter your feedback"
required
/>
</div>Status and message
status takes 'error', 'warning' or 'success' and colours the border. 'default' is the same as no status. statusMessage renders under the box in the status colour, with its glyph. 'error' also sets aria-invalid, unless you pass your own.
<div className="flex w-full max-w-spacing-384 flex-col gap-spacing-16">
<Textarea
label="Reason for absence"
status="error"
statusMessage="Enter a reason before you submit."
/>
<Textarea
label="Lesson summary"
defaultValue="Students practised reading short Thai poems aloud."
status="success"
statusMessage="Saved."
/>
</div>Counter
counter is app-owned text at the end of the row under the box. The message grows to fill the row and the counter stays right-aligned. In a narrow field the row wraps. The component does not count anything, and maxLength passes through to the textarea unchanged.
<div className="w-full max-w-spacing-384">
<Textarea
label="Note to parents"
value={value}
onChange={(event) => setValue(event.target.value)}
maxLength={LIMIT}
statusMessage="Parents see this note in the app."
counter={`${value.length} / ${LIMIT}`}
/>
</div>Size and resizing
The textarea is 120px tall at least and 320px at most at the default scale, and longer content scrolls. It does not grow as you type. An editable textarea resizes vertically with the browser's grip. iOS may not show the grip. className and style reach the textarea, so a height or resize class you pass wins.
<div className="w-full max-w-spacing-384">
<Textarea label="Term plan" defaultValue={PLAN} />
</div>States
disabled keeps native disabled behaviour, so the value is left out of form data. readOnly uses a grey surface. loading sets readOnly and aria-busy and shows a spinner at the end of the first line. The value, label, description, message and counter stay visible while loading. All three states turn off resizing.
<div className="flex w-full max-w-spacing-384 flex-col gap-spacing-16">
<Textarea
label="Disabled"
defaultValue="Submissions closed on 30 June."
disabled
/>
<Textarea
label="Read-only"
defaultValue="Graded by Kru Malee on 2 July."
readOnly
/>
<Textarea
label="Loading"
defaultValue="Checking your answer for spelling."
loading
/>
</div>Start icon
startIcon draws a decorative 20px icon before the first line of text. There is no default icon.
<div className="w-full max-w-spacing-384">
<Textarea
label="Answer"
placeholder="Write your answer"
startIcon={<IconInterfaceEssentialEditLine />}
/>
</div>Accessibility
aria-describedbylists your own ids first, then the description, the message and the counter.- The required star is
aria-hidden. The textarea carries nativerequired. - The start icon and the spinner are
aria-hidden. - No live region is added. Announce validation messages yourself if they need it.
- The focus ring draws when the textarea has keyboard focus.
API
Textarea
className, style, events and ref go to the <textarea>. fieldClassName targets the bordered box and wrapperClassName the whole field. children is not accepted. Use value or defaultValue.
Prop
Type