Skip to content
Home Theme Gallery

Textarea

The custom element is <hui-textarea>.

Overview

A form-associated multi-line text control. It submits through ElementInternals like hui-input, and the optional auto-resize keeps the field as tall as its content.

Example

Plain textarea
Source
<hui-textarea name="notes" rows="4" placeholder="Notes" aria-label="Notes"></hui-textarea>

The Go template that renders it:

<hui-textarea name="notes" rows="4" value="{{ .Notes }}" placeholder="Notes" aria-label="Notes"></hui-textarea>

API

Attributes12
Attributes
NameTypeDefaultDescription
namestring''The form field name. With no name the control contributes no entry to FormData.
disabledbooleanfalseDisables the control and clears its form value.
valuestring''The current value. Not reflected; the attribute only seeds the value restored by a form reset.
placeholderstring''Placeholder text, forwarded when non-empty.
rowsnumber3The initial visible row count, forwarded to the native textarea.
readonlybooleanfalseMakes the internal textarea read-only.
requiredbooleanfalseMarks the control required and forwards constraint validity to the form.
minlengthnumber-Minimum length, forwarded to the native textarea. Omitted when unset.
maxlengthnumber-Maximum length, forwarded to the native textarea. Omitted when unset.
autocompletestring-An autocomplete hint, forwarded to the native textarea. Omitted when unset.
auto-resizebooleanfalseGrows the textarea to its scroll height on every input. Reflected as auto-resize and exposed as the autoResize property.
codebooleanfalseDraws the field as a code field: monospace, ligatures off, white-space: pre and a 2-column tab. Reflected.
Properties14
Properties
NameTypeDefaultDescription
namestring''Reflects to the name attribute.
disabledbooleanfalseReflects to the disabled attribute.
valuestring''The current value. Not reflected; changing it commits the new value to the form.
placeholderstring''Reflects to the placeholder attribute.
rowsnumber3Reflects to the rows attribute.
readonlybooleanfalseReflects to the readonly attribute.
requiredbooleanfalseReflects to the required attribute.
minlengthnumber-Reflects to the minlength attribute.
maxlengthnumber-Reflects to the maxlength attribute.
autocompletestring-Reflects to the autocomplete attribute.
autoResizebooleanfalseReflects to the auto-resize attribute.
codebooleanfalseReflects to the code attribute.
caret{ line: number; column: number }-Read-only. The caret's one-based line and column, normalised to \n and counting a tab as one character.
selection{ start, end }-Read-only. Both ends of the selection, each a { line, column } position.
Methods1
Methods
NameTypeDescription
selectRange(line, column, endLine?, endColumn?)-Moves the caret, and the selection, to a one-based line and column, focuses the control and scrolls it into view. Out-of-range input clamps to the nearest valid position rather than throwing.
Events3
Events
NameDescription
inputEmitted from the host on every keystroke, after the value, validity and auto-resize update. bubbles and composed; no detail.
changeEmitted from the host when the native change fires. bubbles and composed; no detail.
hui-caret-changeThe caret moved - a keystroke, an arrow, a click or a selection. bubbles and composed, with detail { line, column }.
CSS custom properties6
CSS custom properties
NameDefaultDescription
--hui-backgroundoklch(1 0 0)Field fill.
--hui-inputoklch(0.62 0.019 323.02)Border colour of the control boundary.
--hui-font-mono"JetBrains Mono", ui-monospace, …Code-mode face; a host that sets it replaces the stack.
--hui-radius0.45remBase radius; the field uses --hui-radius-lg.
--hui-mutedoklch(0.96 0.003 325.6)Fill while readonly.
--hui-focus-ring-width3pxWidth of the keyboard focus ring.
::part() hooks2
::part() hooks
NameDescription
inputThe internal native <textarea>.
controlThe same element; the control carries both part names.

States

Auto-resize

auto-resize grows the box with the text rather than scrolling it, starting at the height rows gives.

Auto-resize
Source
<hui-textarea name="bio" rows="3" auto-resize value="one line" aria-label="Auto resize"></hui-textarea>

Disabled

Disabled: greyed, out of the tab order, and not submitted.

Disabled
Source
<hui-textarea name="locked" value="nope" disabled aria-label="Locked"></hui-textarea>

Code mode

code draws the field as a code field: --hui-font-mono, ligatures off, white-space: pre and a 2-column tab. It is still a textarea, not an editor: a host that needs syntax highlighting mounts CodeMirror in a hui-field.

Code mode
Source
<hui-textarea code rows="5" name="config" value="service:&#10; port: 8080&#10; debug: true" aria-label="Configuration"></hui-textarea>

Jump to a validation error

A server reports "line 2, column 9". The host renders the message and calls selectRange(2, 9), which moves the caret there and scrolls it into view; caret reads the position back. Lines and columns are one-based, and a tab counts as one character.

Jump to a validation error
Source
<div style="display:flex;flex-direction:column;gap:.5rem;width:100%">
<hui-textarea code rows="3" name="config" aria-invalid="true" value="service:&#10; port: eight" aria-label="Configuration"></hui-textarea>
<p class="hui-muted" style="margin:0">Line 2, column 9: port must be a number.</p>
</div>

Server-side mechanics

The server owns name, value, rows, placeholder, required, minlength/maxlength, autocomplete, readonly, disabled and auto-resize, and the text submits under name through ElementInternals. As with hui-input, value is not reflected, so a swap has to re-render the value attribute to seed the control, and a swap mid-typing loses the unsaved text and focus. Server-side validation arrives as required and the length bounds, with aria-invalid="true" or a hui-field invalid wrapper supplying the invalid styling.

Accessibility

  • The accessible name comes from an aria-label or from a hui-field label; IDREFs are resolved in the light DOM by hui-field.
  • The forwarded aria-invalid swaps the border and focus ring to --hui-destructive.
  • Focus is shown with the shared ring on :focus-visible only.
  • auto-resize changes only the visual height; it does not alter the control role or value.
  • code changes only the type and layout; validation, setCustomValidity and the submitted value are untouched.

Keyboard

Keyboard
KeysAction
Tab, Shift+TabMoves focus to and from the control; Tab does not insert a tab character.
EnterInserts a newline.
Standard editing keysArrows, Home, End, Backspace and selection behave exactly as the native textarea does.

Gotchas

  • value is not reflected; the attribute only seeds the value restored by a form reset, so a server that reads it back sees the original.