Prisma
Live Preview

Textarea Component Generation Skill

Skill này hướng dẫn bạn (AI Agent) tạo component Textarea — trường nhập liệu nhiều dòng, dùng cho nội dung dài như mô tả, bình luận, ghi chú.

1. Mục tiêu (Objective)

Tạo component Textarea hoàn chỉnh, hỗ trợ auto-resize, character count, min/max rows. Chia sẻ hệ thống token với Input nhưng mở rộng cho multi-line editing.

2. AI Context & Intent (Ngữ cảnh cho AI)

Khi nào dùng Textarea?

  • Nội dung dài hơn 1 dòng: mô tả sản phẩm, bình luận, tin nhắn, ghi chú
  • User cần thấy nhiều dòng cùng lúc: review text, soạn email

Phân biệt với component khác

Tình huống Component đúng Lý do
Text ngắn, 1 dòng Input Tiết kiệm không gian
Text dài, nhiều dòng Textarea Cần thấy toàn bộ nội dung
Rich text (bold, italic, list) Rich Text Editor Textarea chỉ plain text
Chat message Textarea (auto-resize, sm) Multi-line nhưng compact

Decision Tree cho AI

text
User cần nhập nội dung dài?
├─ Plain text, nhiều dòng → Textarea
│   ├─ Cần giới hạn ký tự? → showCount=true, maxLength
│   ├─ Cần auto-grow? → autoResize=true
│   └─ Cần fixed height? → rows={N}
├─ Cần formatting (bold, list) → Rich Text Editor (ngoài scope)
└─ Text ngắn, 1 dòng → Input

3. Ngữ nghĩa & Phân loại (Semantics)

3.1. Default Textarea

  • Mục đích: Multi-line input chuẩn với border.
  • Đặc điểm: Resize handle, scrollbar khi vượt quá height.
  • Tương đồng: Outlined TextField (multiline) (Material 3), TextView (iOS).

3.2. States

Kế thừa hoàn toàn từ Input: Idle, Focused, Error, Success, Disabled, Readonly.

3.4. Slot Map (Figma ↔ Code)

📎 Source: slot-manifest.jsontextarea · Layer: item

Figma Slot data-slot CSS Class Required Accepts
Root textarea .textarea
Label textarea-label .label text
Field textarea-field .textarea-field textarea-element
Helper textarea-helper helper-text, error-text, char-count

4. Token Mapping

📦 Token values: Xem ATOMIC-MAPPING.md — single source of truth cho tất cả actual token values.

Token Type Value Mô tả
min-height number {min-width.20} Minimum height — approximately 3 lines
line-height number {font.leading.6} 24px line height for body text
resize-handle-color color {base.muted-foreground} Resize grab handle color
counter-font-size number {font.size.xs} Character counter text size
counter-color color {base.muted-foreground} Character counter text color
counter-color-warning color {base.warning} Counter when nearing limit
counter-color-error color {base.destructive} Counter when at/over limit
counter-margin-top number {spacing.1} Gap between textarea and counter
color.focus-ring color {focus.ring-color} Focus ring color — ref shared/focus
color.disabled-bg color {base.muted} Disabled state background
color.disabled-fg color {base.muted-foreground} Disabled state foreground

| transition | string | {duration.fast-2} {easing.standard} | Default interaction transition | | padding | number | {item.padding-default} | Internal padding | | radius | number | {comp.radius} | Corner radius — inherits from density tier | | font-weight | number | {font.weight.medium} | Default font weight |

5. Props & API

typescript
interface TextareaProps {
  /** Visual variant */
  variant?: 'default' | 'filled';
  /** Size preset */
  size?: 'sm' | 'md' | 'lg';
  /** Label hiển thị phía trên */
  label?: string;
  /** Placeholder */
  placeholder?: string;
  /** Số dòng hiển thị mặc định */
  rows?: number;
  /** Min rows (auto-resize mode) */
  minRows?: number;
  /** Max rows (auto-resize mode) */
  maxRows?: number;
  /** Auto resize theo nội dung */
  autoResize?: boolean;
  /** Hiển thị character count */
  showCount?: boolean;
  /** Giới hạn ký tự tối đa */
  maxLength?: number;
  /** Helper text */
  helperText?: string;
  /** Error message */
  errorMessage?: string;
  /** Cho phép resize thủ công */
  resizable?: boolean | 'vertical' | 'horizontal' | 'both';
  /** Disabled */
  disabled?: boolean;
  /** Readonly */
  readOnly?: boolean;
  /** Full width */
  fullWidth?: boolean;
}

6. Accessibility (a11y)

  • Kế thừa toàn bộ a11y rules từ input.md.
  • Character count: Dùng aria-live="polite" để screen reader thông báo khi gần đạt giới hạn (vd: còn 10 ký tự).
  • Auto-resize: Đảm bảo aria-multiline="true" (mặc định trên <textarea>).

7. Best Practices & Rules

  • Semantic HTML: Dùng <textarea>, KHÔNG dùng <div contenteditable>.
  • Auto-resize: Dùng JavaScript để điều chỉnh height theo scrollHeight, KHÔNG dùng CSS-only hack.
  • Resize handle: Mặc định resize: vertical. Set resize: none khi autoResize=true.
  • Mọi quy tắc không hardcode, dark mode, responsive — kế thừa từ Input.

8. Example Usage

jsx
{/* Basic */}
<Textarea label="Mô tả" placeholder="Nhập mô tả sản phẩm..." rows={4} />

{/* Auto-resize with char count */}
<Textarea
  label="Bình luận"
  autoResize
  minRows={2}
  maxRows={8}
  showCount
  maxLength={500}
/>

{/* Error state */}
<Textarea
  label="Ghi chú"
  errorMessage="Nội dung không được để trống"
/>