AhaSlides Design
v0.52.0React · Vue · Lit

Patterns · Settings

Counted textarea

The multi-line settings field — a CountedInput that wraps to several lines, grows from minRows to maxRows then scrolls, with the same focus-only character counter.

Examples

Max length
Status
Focus a field — the counter appears only while focused; type past a few lines and it scrolls
States · no counter · disabled · readonly

API

PropTypeDefaultNotes
valuestring""Controlled text value
placeholderstringHint shown when empty
maxlengthnumber150Character cap (settings-lab default 150); drives the focus-only counter (shows current/max). Pass `none` to drop the cap and hide the counter
minrowsnumber2Rows shown at rest — the field never shrinks below this
maxrowsnumber5Rows the field grows to before it scrolls internally instead of growing
statusdefault | errordefaultError recolours the border + ring and sets aria-invalid
disabledbooleanfalseNon-interactive; grey fill
readonlybooleanfalseSelectable but not editable; secondary fill
borderlessbooleanfalseDrop the field's own border/ring/fill — for composing inside a parent that carries the one border (OptionRow, SETTINGS-34)
inputCustomEvent<{value}>Composed event on each keystroke; read e.detail.value
changeCustomEvent<{value}>Composed event on commit (blur)

Install

# .npmrc — once: point the @ahaslides-product scope at GitHub Packages
@ahaslides-product:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}   # a GitHub token with read:packages

npm i @ahaslides-product/design
import '@ahaslides-product/design/tokens.css';   // once, at the app root
import '@ahaslides-product/design/aha-counted-textarea';   // registers <aha-counted-textarea>

Agent feed for this component (absolute, fetchable anywhere): counted-textarea.agent.json · counted-textarea.md · counted-textarea.llms.txt

When to use

When to use
  • Counted textarea — a multi-line settings field — a description, a long answer — that needs a character cap; the counter appears only on focus
  • Counted input — the single-line sibling — option/answer/label text with a cap
  • Input — a general single-line field with no counter (names, search)
Never show a permanent counter on every field — it reads as heavy. The counter belongs inside the field, revealed on focus. Cap the growth: a textarea that grows without bound pushes the rest of the panel down; grow to maxRows then scroll.
Surfaces
editor settings

Spec

Box radius 8 · padding 6 12 · resize off · Autogrow minrows (default 2) → maxrows (default 5); beyond maxrows scrolls internally, never grows unbounded · Rest border 1px #E3E3E3 · Focus #6A1EBB border + 2px #D3B4FF@30% ring (on the persistent wrapper) · Counter 12/18 #8A8A8A, overlay bottom-right; opacity 0 at rest → 1 on focus · Reveal focus-only (:host([_focused][_counted])) — hidden at rest; space always reserved (no shift) · Error #F5222D border + error-tinted ring; sets aria-invalid · Disabled #F1F1F1 fill, #EBEBEB border, not-allowed · Text Plus Jakarta 14/21; placeholder #8A8A8A