Mediquo documentation home

Textarea

A multi-line field that grows with what the patient writes.

mq-textarea is the console's Textarea as a design-system primitive. It ships from @mediquo/ui as a custom element and as a React component.

Install

// Custom element — the import registers <mq-textarea>
import "@mediquo/ui/components/textarea";
// React
import { Textarea } from "@mediquo/ui/react/textarea";

It renders the control and nothing else

Like OTP input, it has no label, hint or error text of its own — those belong to your field wrapper. invalid (the console's error) is a state: it turns the border red and sets aria-invalid, and the integrator says what went wrong.

<Field>
  <FieldLabel htmlFor="reason">Motivo de la consulta</FieldLabel>
  <Textarea label="Motivo de la consulta" invalid={isReasonError} />
  {isReasonError ? <FieldError>Cuéntanos algo más.</FieldError> : null}
</Field>

Sizing

The field grows with its text, the way the console's does with field-sizing: content, starting from rows lines (3 by default). Set fixed to keep it at rows and scroll instead. Where the browser does not support field-sizing yet, it keeps its rows and can still be resized by hand.

Forms

It is form-associated through ElementInternals: name submits the text, the form's reset puts back the initial value attribute, a disabled fieldset disables it, and required, minlength and maxlength report to the form's validation exactly as a native <textarea> would.

Accessibility

  • label is the accessible name, set as aria-label. The real textarea lives in a shadow root where an outer <label for> cannot reach it, so the component warns in the console when label is missing.
  • placeholder is a hint, not a label — it disappears as soon as the user types.
  • invalid sets aria-invalid; pair it with your field wrapper's error text so the failure is never communicated by colour alone.
  • required sets aria-required as well as the native required.
  • The focused field gets a ring as well as a brand border — the console's 1px border change alone is too faint to find the focused field by.

Events

onvaluechange fires on every edit with the new text on event.value. The native input event also bubbles out of the shadow root.

Styling

These custom properties are the supported override points:

mq-textarea {
  --mq-textarea-min-height: 4rem;
  --mq-textarea-max-height: none;
  --mq-textarea-radius: 0.375rem;
  --mq-textarea-background: #ffffff;
  --mq-textarea-border-color: #edecf1;
  --mq-textarea-invalid-border-color: #ff014d;
}

part="control" reaches the inner <textarea>.