HextaUI

Textarea

Yazdıklarınıza göre en az ve en çok satır sayısı arasında akıcı biçimde büyüyen çok satırlı metin; sayaçlar, doğrulama ve gönderme kısayolu içerir.

Grows with your text, then scrolls.

import { Field, FieldDescription, FieldLabel } from "@/components/ui/field"
import { Textarea } from "@/components/ui/textarea"

export function TextareaDemo() {
  return (
    <Field className="w-full max-w-sm">
      <FieldLabel>Feedback</FieldLabel>
      <Textarea placeholder="What could we do better? Keep typing — the box grows with you." />
      <FieldDescription>Grows with your text, then scrolls.</FieldDescription>
    </Field>
  )
}
pnpm dlx shadcn@latest add https://hextaui.com/r/textarea.json

Bileşeni, HextaUI tema token'larını ve bileşenin bağımlı olduğu tüm HextaUI bileşenlerini ekler.

import { Textarea } from "@/components/ui/textarea"
<Textarea placeholder="Write something…" />

Kutu metninizle büyür; zıplamak yerine her yeni satıra yumuşayarak minRows'tan maxRows'a kadar, sonra kayar. Yazmak animasyon yüzünden asla gecikmez.

Kısayolla gönder

submitOnShortcut formu ⌘ + Enter veya Ctrl + Enter ile gönderir. Tek başına Enter yine yeni satır başlatır.

"use client"

import * as React from "react"

import { Button } from "@/components/ui/button"
import { Kbd, KbdGroup } from "@/components/ui/kbd"
import { Textarea } from "@/components/ui/textarea"

export function TextareaSubmit() {
  const [comments, setComments] = React.useState<string[]>([])

  return (
    <form
      className="flex w-full max-w-sm flex-col gap-3"
      onSubmit={(event) => {
        event.preventDefault()
        const form = event.currentTarget
        const text = String(new FormData(form).get("comment") ?? "").trim()
        if (text) {
          setComments((list) => [...list, text])
          form.reset()
        }
      }}
    >
      {comments.length > 0 ? (
        <ul className="flex flex-col gap-1 text-sm">
          {comments.map((comment, index) => (
            <li
              key={index}
              className="rounded-md bg-muted px-3 py-2 whitespace-pre-wrap"
            >
              {comment}
            </li>
          ))}
        </ul>
      ) : null}
      <Textarea
        name="comment"
        aria-label="Comment"
        placeholder="Write a comment…"
        minRows={2}
        submitOnShortcut
      />
      <div className="flex items-center justify-between gap-3">
        <span className="flex items-center gap-1.5 text-xs text-muted-foreground">
          <KbdGroup>
            <Kbd keys="Mod+Enter" />
          </KbdGroup>
          to send
        </span>
        <Button type="submit" size="sm">
          Comment
        </Button>
      </div>
    </form>
  )
}

Karakter sayısı

Bir Field içinde maxLength ile FieldCounter yazdıkça sayar ve sınıra ulaşınca dürter.

import { Field, FieldCounter, FieldLabel } from "@/components/ui/field"
import { Textarea } from "@/components/ui/textarea"

export function TextareaCounter() {
  return (
    <Field className="w-full max-w-sm">
      <div className="flex items-baseline justify-between gap-3">
        <FieldLabel>Bio</FieldLabel>
        <FieldCounter />
      </div>
      <Textarea name="bio" maxLength={160} minRows={2} />
    </Field>
  )
}

Satırlar

minRows ve maxRows büyümenin nerede başlayıp bittiğini belirler.

import { Textarea } from "@/components/ui/textarea"

export function TextareaRows() {
  return (
    <div className="grid w-full max-w-md gap-4 sm:grid-cols-2">
      <Textarea
        aria-label="One to four rows"
        minRows={1}
        maxRows={4}
        placeholder="1–4 rows"
      />
      <Textarea
        aria-label="Five to fifteen rows"
        minRows={5}
        maxRows={15}
        placeholder="5–15 rows"
      />
    </div>
  )
}

Sabit boyut

autoResize={false} dikey yeniden boyutlandırma tutamacıyla sabit yüksekliği korur.

import { Textarea } from "@/components/ui/textarea"

export function TextareaFixed() {
  return (
    <Textarea
      aria-label="Notes"
      autoResize={false}
      minRows={4}
      placeholder="Fixed height. Drag the corner to resize."
      className="max-w-sm"
    />
  )
}

Durumlar

Devre dışı, salt okunur ve geçersiz. Geçersiz textarea'lar form gönderimi başarısız olduğunda sallanır.

import { Textarea } from "@/components/ui/textarea"

export function TextareaStates() {
  return (
    <div className="grid w-full max-w-md gap-4 sm:grid-cols-3">
      <Textarea
        aria-label="Disabled"
        disabled
        placeholder="Disabled"
        minRows={2}
      />
      <Textarea
        aria-label="Read-only"
        readOnly
        defaultValue="Read-only text you can select but not change."
        minRows={2}
      />
      <Textarea
        aria-label="Invalid"
        aria-invalid
        placeholder="Invalid"
        minRows={2}
      />
    </div>
  )
}

Sağdan sola

Metin, yer tutucu ve imleç okuma yönünü izler.

import { Textarea } from "@/components/ui/textarea"

export function TextareaRtl() {
  return (
    <div dir="rtl" className="w-full max-w-sm">
      <Textarea aria-label="رسالتك" placeholder="اكتب رسالتك هنا…" />
    </div>
  )
}
TuşAction
EnterYeni bir satır başlatır.
⌘EntersubmitOnShortcut ile formu gönderir. Windows ve Linux'ta Ctrl + Enter.
  • FieldLabel veya aria-label ile etiketleyin.
  • Dokunmatik ekranlarda metin en az 16px'tir, böylece odaklanınca iOS yakınlaştırmaz.
  • Bir giriş yöntemi kompozisyon yaparken kısayol bekler; böylece bir Japonca veya Çince sözcüğü onaylamak mesajı asla göndermez.
  • Azaltılmış harekette kutu anında yeniden boyutlanır.
PropTürVarsayılan
autoResizeSabit yükseklik yerine metinle birlikte büyür.
booleantrue
minRows
number3
maxRows
number10
submitOnShortcutÜst formu ⌘/Ctrl + Enter ile gönderir.
booleanfalse
shakeForm gönderimi onu geçersiz bulduğunda sallanır.
booleantrue
ÖznitelikAçıklama
data-slot="textarea"Textarea.
data-autoresizeMetniyle büyüdüğünde bulunur.
--textarea-min-rows / --textarea-max-rowsminRows ve maxRows değerlerinden ayarlanır.

Kullanıldığı bloklar

Textarea üzerine kurulan bloklar.