Files
HMDesign/packages/ui/src/theme/textarea.css
T

83 lines
4.1 KiB
CSS

/* Textarea mapping: the control only. Label, Required star and Helper/Error message are consumer composition, not part of Textarea.
States use native selectors (:focus-visible, [aria-invalid="true"], :disabled, [readonly]); resize uses data-resize.
Input and Textarea values are separate Tokens even where the numbers match (ui_viz keeps them as separate component owners). */
:root, [data-hm-theme] {
/* ui_viz: docs/components/textarea.md §8.1 TEXTAREA-01/02 — SCOPED_DESIGN_APPROVAL (2026-09-17 owner, Textarea component-local).
Not D-093 Confirmed; Canonical min-height and inset stay TBD in ui_viz. Not promoted to size.* or space.* scale. */
--hm-textarea-min-height: 112px;
--hm-textarea-padding-block: 8px;
--hm-textarea-padding-inline: 12px;
/* ui_viz: docs/components/textarea.md §2 Typography — Value 16/24/400 (existing role) */
--hm-textarea-font-size: 16px;
--hm-textarea-line-height: 24px;
--hm-textarea-font-weight: 400;
/* ui_viz: docs/components/textarea.md §2, §2.2, §3.3 — Confirmed (border 1px, radius 4px, surface, colors, Focus/Error 1.5px) */
--hm-textarea-radius: var(--hm-radius-input);
--hm-textarea-border-width: 1px;
--hm-textarea-state-border-width: 1.5px;
--hm-textarea-background: var(--hm-sem-bg-surface);
--hm-textarea-text: var(--hm-sem-fg-primary);
--hm-textarea-placeholder: var(--hm-sem-fg-placeholder);
--hm-textarea-border-color: var(--hm-sem-stroke-input-default);
--hm-textarea-focus-border-color: var(--hm-sem-stroke-input-focus);
--hm-textarea-error-border-color: var(--hm-sem-action-destructive);
}
[data-slot="textarea"] {
box-sizing: border-box;
min-height: var(--hm-textarea-min-height);
padding: var(--hm-textarea-padding-block) var(--hm-textarea-padding-inline);
border: var(--hm-textarea-border-width) solid var(--hm-textarea-border-color);
border-radius: var(--hm-textarea-radius);
background: var(--hm-textarea-background);
color: var(--hm-textarea-text);
font-size: var(--hm-textarea-font-size);
line-height: var(--hm-textarea-line-height);
font-weight: var(--hm-textarea-font-weight);
box-shadow: none;
resize: vertical;
}
[data-slot="textarea"][data-resize="none"] { resize: none; }
[data-slot="textarea"][data-resize="both"] { resize: both; }
[data-slot="textarea"]::placeholder {
color: var(--hm-textarea-placeholder);
opacity: 1;
}
/* Hover is identical to Default (textarea.md §3.3, TEXTAREA-05 user decision): no hover rule. */
/* Focus: the border alone marks it (1.5px, no shadow or glow). Padding gives back the extra 0.5px so the value does not move. */
[data-slot="textarea"]:focus-visible {
outline: none;
border-width: var(--hm-textarea-state-border-width);
border-color: var(--hm-textarea-focus-border-color);
padding: calc(var(--hm-textarea-padding-block) - (var(--hm-textarea-state-border-width) - var(--hm-textarea-border-width)))
calc(var(--hm-textarea-padding-inline) - (var(--hm-textarea-state-border-width) - var(--hm-textarea-border-width)));
}
/* Invalid owns the border; keyboard focus adds the same HM 3px / 50% semantic ring as Input. */
[data-slot="textarea"][aria-invalid="true"] {
border-width: var(--hm-textarea-state-border-width);
border-color: var(--hm-textarea-error-border-color);
padding: calc(var(--hm-textarea-padding-block) - (var(--hm-textarea-state-border-width) - var(--hm-textarea-border-width)))
calc(var(--hm-textarea-padding-inline) - (var(--hm-textarea-state-border-width) - var(--hm-textarea-border-width)));
}
[data-slot="textarea"][aria-invalid="true"]:focus-visible {
border-color: var(--hm-textarea-error-border-color);
outline: none;
box-shadow: 0 0 0 3px color-mix(in srgb, var(--ring) 50%, transparent);
}
/* Disabled keeps the surface face. Opacity 0.6 is set in ui/textarea.tsx: ui_viz `.6` is Temporary; 2026-10-02 user decision extends it to Textarea. */
[data-slot="textarea"]:disabled {
background: var(--hm-textarea-background);
}
/* Readonly (textarea.md §3.1): keeps the Default surface, border and typography, not dimmed, no resize affordance whatever `resize` says. */
[data-slot="textarea"][readonly] {
resize: none;
opacity: 1;
}