Textarea
A multi-line text field, with the same chrome as VInput: label above, hint below, icons inside, a counter and a clear button. It can grow as the text is typed.
Usage
Examples
Label and hint
label is a real <label> tied to the field, so clicking the words puts the cursor in the box. hint goes under the field and is tied to it through aria-describedby.
Sizes
size sets the padding, the type scale and the icons, never the height, which comes from rows. compact takes 4px off the padding at any of the three.
Icons
iconStart and iconEnd place a decorative icon at either end, on the first line rather than in the middle of the box. The #end slot replaces the end icon, where #start is rendered after the start icon rather than in its place.
Clickable icons
A @click:icon-start or @click:icon-end listener turns that icon into a real button, which then needs its label. Each button is its own tab stop and stays outside the textarea.
Clearable
clearable adds a cross that empties the field, shown while there is something to clear and the field can be edited. Pressing it hands the focus straight back to the textarea, and clear fires after the fact.
Counters
counter goes under the field, beside the hint. Against maxlength the browser refuses everything past the limit, where softLimit lets the reader type on: the counter goes red and the field reports itself invalid through the native validity. It counts characters, as on VInput; on VFileInput the same prop counts files and their size.
Auto grow
rows gives the field its starting height, and by default its height full stop. autoGrow lets the box get taller as the text is typed, in pure CSS.
States
invalid is for a rule the browser cannot check by itself. disabled greys the field out through the colour tokens. readonly can still be focused and copied from, and hides the clear cross. loading puts a spinner where the end icon goes, the field staying usable.
API
Props
| Prop | Type | Default |
|---|---|---|
size | TextareaSize'sm' | 'md' | 'lg' | 'md' |
| The size of the field, which sets its padding, its type scale and its icons. | ||
compact | boolean | false |
| Takes 4px off the field by tightening its padding, leaving the number of lines, the type and the icons alone. | ||
rows | number | 5 |
How many lines of text the field shows, the native rows attribute, which is what gives the field its height. Anything under 1 is raised to 1, and at 1 the field is exactly as tall as a VInput of the same size. | ||
autoGrow | boolean | false |
Lets the field grow as the text is typed, instead of scrolling inside the height rows gives it, which stays its starting height. It is pure CSS: where the browser does not support it, the field behaves like an ordinary textarea. | ||
invalid | boolean | false |
| Marks the field as invalid whatever the browser thinks, the route for a rule only the server can check. | ||
disabled | boolean | false |
| Makes the field unusable, greyed out through the colour tokens. | ||
readonly | boolean | false |
| Shows the text without allowing it to be changed. The field can still be focused and copied from, and the clear button is hidden. | ||
label | string | none |
| The label above the field, tied to it so that clicking it focuses the field. | ||
hint | string | none |
| A line of help under the field, tied to the textarea for assistive technology so that it is read out along with the label. | ||
iconStart | IconSource | none |
An icon inside the field, at the start. It is decorative until a @click:icon-start listener is attached, at which point it becomes a real button and needs iconStartLabel. | ||
iconEnd | IconSource | none |
The same at the end of the field. The #end slot replaces it, and the loading spinner takes its place while it turns. | ||
iconStartLabel | string | none |
| What the start icon does, in words, once it is clickable. | ||
iconEndLabel | string | none |
| What the end icon does, in words, once it is clickable. | ||
loading | boolean | false |
| Shows a spinner at the end of the field, in place of the end icon or slot. | ||
loadingText | string | none |
| What screen readers announce while the spinner turns. It falls back to the design system dictionary. | ||
clearable | boolean | false |
| Offers a cross that empties the field. It appears when there is something to clear and the field can be edited. | ||
clearVisible | boolean | none |
| Decides whether the cross is shown, instead of letting the field work it out from its own content, a read-only field included. It is the same escape hatch VInput offers, for components built on top of this one that hold what there is to clear somewhere other than the text. | ||
clearLabel | string | none |
| What the clear button does, in words. It falls back to the design system dictionary. | ||
maxlength | number | none |
| The maximum number of characters. By default this is the browser's own limit, which simply refuses anything beyond it. | ||
softLimit | boolean | false |
| Turns that limit into a soft one: the reader may type past it, and the field goes into error instead of silently refusing the keystrokes. It is reported through the native validity, so a form cannot be submitted over the limit. | ||
counter | boolean | false |
| Shows how much has been typed, under the field: 12/80 against a limit, or just 12 without one. | ||
v-model | string | '' |
| The text in the field, empty to begin with. | ||
Events
| Event | Type |
|---|---|
click:icon-start | [event: MouseEvent] |
| The start icon was pressed. Attaching this listener is what turns it into a button. | |
click:icon-end | [event: MouseEvent] |
| The end icon was pressed. Attaching this listener is what turns it into a button. | |
clear | [] |
| The clear button was pressed. The value has already been emptied. | |
Slots
| Slot | Type |
|---|---|
start | {} |
Content at the start of the field, rendered after iconStart rather than in its place. | |
end | {} |
Content at the end of the field, which replaces iconEnd. It is hidden while the field is loading, the spinner taking that place. | |
value-end | {} |
Controls of your own inside the field, placed before the ones the field owns: the clear cross and the icon that opens the panel. Those two are the component own affordance, which is why there is no end slot here. | |
Types
The types the tables above name, written as the library declares them. The ones carrying export can be imported from vectis-ui to type your own code; the others are the shape of what a slot hands out.
export interface BuiltinIcon {
name: string
paths: readonly [string] | readonly [string, string]
}export type IconRender =
| { path: string; viewBox?: string }
| { component: Component; props?: Record<string, unknown> }
| { src: string }
| { text: string; class?: string }
| { class: string }export type IconSource = string | BuiltinIcon | IconRender