j3w1 / theme

j3w1 / theme4.0.0

j3w1 / command

  • SPEC Overview
  • SPEC Foundations
  • SPEC Components
  • SPEC Patterns
  • SPEC Tokens
  • SPEC Tools
  • SPEC Workbench
  • SPEC Form builder
  • SPEC Task kit
  • SPEC Recipes
  • SPEC Figma bridge
  • SPEC Report an issue
  • SPEC Implement
  • SPEC For agents
  • SPEC Ports
  • SPEC Releases
  • SPEC Specification
  • DEMO Vue application demo

Textarea

Multi-line free-text entry in the same box as the text field; resizes vertically only and can show a character count.

stable · light DOM · 4.0.0. Visible native controls retain FormData, labels, constraints, disabled fieldsets and reset. No duplicate form-value mechanism is installed.

Live variants

default

Plain text; one change per line.

✕ Say why, not only what.

Markup
<j3w1-textarea id="example-textarea-default"><div class="textarea">
  <label class="textarea-label" for="example-textarea-default-ta-notes">Release notes <span class="textarea-required" aria-hidden="true">*</span><span class="textarea-required sr-only"> required</span></label>
  <div class="textarea-root">
    <textarea class="textarea-input" id="example-textarea-default-ta-notes" rows="3" placeholder="What changed and why" aria-describedby="example-textarea-default-ta-notes-help example-textarea-default-ta-notes-message" name="example-textarea-default-ta-notes">Focus rings now recolour on filled surfaces.
Disabled controls no longer use opacity.</textarea>
  </div>
  <p class="textarea-help" id="example-textarea-default-ta-notes-help">Plain text; one change per line.</p>
  <p class="textarea-message" id="example-textarea-default-ta-notes-message">✕ Say why, not only what.</p>
</div></j3w1-textarea>

with-count

46 / 200

Counts characters, not bytes.

✕ Over the limit.

Markup
<j3w1-textarea id="example-textarea-with-count"><div class="textarea">
  <label class="textarea-label" for="example-textarea-with-count-ta-summary">Commit summary <span class="textarea-required" aria-hidden="true">*</span><span class="textarea-required sr-only"> required</span></label>
  <div class="textarea-root">
    <textarea class="textarea-input" id="example-textarea-with-count-ta-summary" rows="3" maxlength="200" placeholder="Under 200 characters" aria-describedby="example-textarea-with-count-ta-summary-help example-textarea-with-count-ta-summary-count example-textarea-with-count-ta-summary-message" name="example-textarea-with-count-ta-summary">spec: button, link and the basic form controls</textarea>
  </div>
  <p class="textarea-count" id="example-textarea-with-count-ta-summary-count" aria-live="polite">46 / 200</p>
  <p class="textarea-help" id="example-textarea-with-count-ta-summary-help">Counts characters, not bytes.</p>
  <p class="textarea-message" id="example-textarea-with-count-ta-summary-message">✕ Over the limit.</p>
</div></j3w1-textarea>

Install and register

Use the exact version. If npm publication is pending, install the release tarball from the installation guide.

npm install --save-exact @j3w1/ui@4.0.0
import '@j3w1/ui/tokens.css';
import '@j3w1/ui/styles/textarea.css';
import '@j3w1/ui/register/textarea';

Insert the maintained markup above after loading these imports. Its native children provide accessible names and form behavior; the empty custom tag alone does not create a control.

Vue SFC, React, Astro and plain HTML integration →

Copy the complete implementation

npx --package=@j3w1/ui@4.0.0 j3w1-ui copy textarea --out ./vendor/j3w1/textarea

The CLI verifies every file before writing and refuses overwrites. Serve the output over HTTP and open index.html. Keep its modules, CSS, tokens and licence notices together.

Public API

attributes

NameType / signatureMeaning
disabledCustomEventDisable the native controls owned by this instance.
loadingCustomEventMark the primary control busy and prevent duplicate activation.
valueCustomEventForwards value to the primary native control.
requiredCustomEventForwards required to the primary native control.
readonlyCustomEventForwards readonly to the primary native control.
checkedCustomEventForwards checked to the primary native control.

properties

NameType / signatureMeaning
disabledbooleanDelegates disabled state to native children.
namestringNative control name; application form keys remain explicit.
valuestringPrimary native value; assignment does not fabricate user events.
checkedbooleanNative checkbox state.
requiredbooleanNative required constraint.
readOnlybooleanNative readonly property.
formHTMLFormElement | nullOwning native form. Read only.

methods

NameType / signatureMeaning
refresh(): voidReconnect behavior after replacing native child structure.
focus(options?: FocusOptions): voidFocus the first usable native control.
checkValidity(): booleanCheck owned native constraints.
reportValidity(): booleanReport the first invalid owned control.
clear(): voidClear an editable primary input and emit native input/change.

events

NameType / signatureMeaning
j3w1-changeCustomEventNative change from an owned control, alongside the original native event.

Dependencies and verification

Registered components: none. Style dependencies: none.

Package presence establishes an available implementation. Actual passes depend on the tested artifact and environment. Read specification execution evidence; read packed-consumer evidence; inspect the complete state matrix.

Full implementation manifest, API and token dependency closure

Canonical specification

Textarea textarea

  • Family: Basic forms
  • Maturity: stable
  • Priority: R1
  • Since: 0.1.0
  • Native control: native <textarea> with <label> — APG pattern
  • specified
  • demonstrated

Multi-line free-text entry in the same box as the text field; resizes vertically only and can show a character count.

Report an issue with this component

Tokens

Focus a role to inspect its values; follow its link for persistent usage and source details.

PartRoleValueUse
root.bgcolor.surface.inputapproveduse#000000Form-control fill.
root.bordercolor.border.controlapproveduse#c81a1aD-041 owner correction: red control and floating-frame borders, distinct from rose text.
root.bg-hovercolor.interaction.hover.bgapproveduse#1c1010D-041 interaction.hover.bg: color.primitive.modern.hover.
root.border-focuscolor.border.activeobserveduse#e53935Active or focused control border.
root.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
root.ring-invalidcolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
root.border-invalidcolor.status.danger.borderobserveduse#e53935Danger border, 2px on invalid inputs.
root.border-disabledcolor.border.disabledapproveduse#482b2bD-041 border.disabled: color.primitive.modern.divider.
root.bg-disabledcolor.interaction.disabled.bgapproveduse#0d0707D-041 interaction.disabled.bg: color.primitive.modern.panel.
root.border-readonlycolor.border.dividerapproveduse#482b2bD-041 border.divider: color.primitive.modern.divider.
root.bg-readonlycolor.surface.canvasapproveduse#000000Page and terminal background.
input.textcolor.text.defaultapproveduse#e99499D-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills.
input.text-disabledcolor.text.disabledapproveduse#a3676bD-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills.
input.placeholdercolor.text.placeholderapproveduse#bd787dD-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills.
input.caretcolor.code.caretapproveduse#ffa2a7D-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills.
input.selection-bgcolor.interaction.text-selection.bgobserveduse#420f0cD-041 subdued burgundy selection keeps rose text readable in hosts retaining its foreground.
input.selection-textcolor.interaction.text-selection.textobserveduse#f4eeee::selection text.
label.textcolor.text.brightapproveduse#ffa2a7D-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills.
label.required-markcolor.status.danger.textobserveduse#f07178D-041 readable error text on neutral surfaces and native warning tints.
help.textcolor.text.mutedapproveduse#d4868bD-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills.
count.textcolor.text.mutedapproveduse#d4868bD-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills.
count.text-overcolor.status.danger.textobserveduse#f07178D-041 readable error text on neutral surfaces and native warning tints.
message.textcolor.status.danger.textobserveduse#f07178D-041 readable error text on neutral surfaces and native warning tints.

State matrix

Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

StateDefaultWith character count
default

Plain text; one change per line.

✕ Say why, not only what.

46 / 200

Counts characters, not bytes.

✕ Over the limit.

hover
focus-visible
placeholder-shown
filled
required
invalid
invalid+focus-visible
disabled
read-only

Purpose

Free text longer than a line: descriptions, messages, notes. It shares the text field’s box, states and message so a form reads as one system. Code goes in the code-editor component.

Anatomy

Parts as listed in the anatomy, top to bottom: label, box, count, help; the message takes the help slot visually while help stays in the DOM.

States

StateVisualNon-colour channel
default1px color.border.control on color.surface.input; text color.text.default—
hover→ color.interaction.hover.bg; border unchangedcursor: text
focus-visibleborder → color.border.active; 1px dashed color.interaction.focus.ring at −2pxthe ring
placeholder-showncolor.text.placeholder, italicitalic
filledas default with a value—
required* after the label in color.status.danger.text plus visually hidden “required”required; the mark
invalid2px color.status.danger.border; message with ✕; a count past its limit turns color.status.danger.text with the glyphborder 1 → 2px; glyph; aria-invalid
invalid+focus-visiblethe 2px danger border and a color.interaction.focus.ring-container ring at −4pxdouble boundary
disabledtext color.text.disabled, border color.border.disabled, fill color.interaction.disabled.bg; no resize handledisabled; cursor: not-allowed
read-onlyno box: 1px dotted color.border.divider bottom edge on color.surface.canvas; no resize handle; selectablereadonly; dotted edge

Precedence: disabled > invalid > hover; focus-visible is always drawn.

Keyboard

As in the key table. A host that needs literal tabs provides a separate command and documents it. The count is not focusable.

Accessibility

A programmatic label is required. aria-describedby lists help, count and message in that order. The help text states the limit before typing. aria-invalid="true" only after interaction or submit. Text and placeholder meet 4.5:1; control and invalid borders 3:1.

Portability

Hosts without a resize handle grow the box with content up to a maximum and record it. Hosts without dashed outlines draw a solid 1px ring.

Non-examples

Horizontal or free resizing. A box narrower than its label column. A count that only changes colour past the limit. A glow instead of the dashed ring. Rounded corners. Auto-growing with no maximum. Tab inserting a character. Placeholder as the label. Disabling by opacity.

Contrast report

20 declared pairs measured on resolved sRGB values with the WCAG 2.x formula; 0 waived (decorative only), 0 failing. A pass is a design target for the named role, not an application-wide conformance claim.

PairStateKindForegroundBackgroundRatioMinResult
textarea default textdefaulttextcolor.text.default #e99499color.surface.input #0000009.164.5pass
textarea default borderdefaultuicolor.border.control #c81a1acolor.surface.input #0000003.623pass
textarea hover texthovertextcolor.text.default #e99499color.interaction.hover.bg #1c10108.104.5pass
textarea hover borderhoveruicolor.border.control #c81a1acolor.interaction.hover.bg #1c10103.203pass
textarea focus-visible textfocus-visibletextcolor.text.default #e99499color.surface.input #0000009.164.5pass
textarea focus-visible borderfocus-visibleuicolor.border.active #e53935color.surface.input #0000004.973pass
textarea focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.input #0000004.973pass
textarea placeholder-shown textplaceholder-showntextcolor.text.placeholder #bd787dcolor.surface.input #0000006.154.5pass
textarea placeholder-shown borderplaceholder-shownuicolor.border.control #c81a1acolor.surface.input #0000003.623pass
textarea invalid textinvalidtextcolor.text.default #e99499color.surface.input #0000009.164.5pass
textarea invalid borderinvaliduicolor.status.danger.border #e53935color.surface.input #0000004.973pass
textarea invalid+focus-visible textinvalid+focus-visibletextcolor.text.default #e99499color.surface.input #0000009.164.5pass
textarea invalid+focus-visible borderinvalid+focus-visibleuicolor.status.danger.border #e53935color.surface.input #0000004.973pass
textarea invalid+focus-visible outlineinvalid+focus-visibleuicolor.interaction.focus.ring-container #ffa2a7color.surface.input #00000010.983pass
textarea read-only textread-onlytextcolor.text.default #e99499color.surface.canvas #0000009.164.5pass
validation message on the panel surface—textcolor.status.danger.text #f07178color.surface.default #0d07076.984.5pass
help and count on the panel surface—textcolor.text.muted #d4868bcolor.surface.default #0d07077.224.5pass
disabled text (exempt; house floor 3:1)disableduicolor.text.disabled #a3676bcolor.interaction.disabled.bg #0d07074.483pass
disabled border (exempt)disableduicolor.border.disabled #482b2bcolor.interaction.disabled.bg #0d07071.581pass
read-only bottom edge (decorative; the field has no box)read-onlyuicolor.border.divider #482b2bcolor.surface.canvas #0000001.661pass

Keys

KeyAction
Tab / Shift+TabMoves focus in and out; Tab never inserts a tab character.
EnterInserts a line break; never submits.
Ctrl+Enter / Cmd+EnterMay submit the owning form when the host binds it; announced in the help text.

For agents

Component JSON ·Implementation brief ·Build a task kit ·

Related: text-field field code-editor

Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-TOUCH FX-DENSITY FX-OVERFLOW FX-STATE-MATRIX