Textbereich
Mehrzeiliger Text, der mit dem Inhalt wächst, mit Zähler, Fußzeile und Fehler als Text.
Eine von 9 Components in Forms und Inputs
Details
Was Textbereich mitbringt, aus Registry und Quellcode gelesen.
- Kategorie
- Forms und Inputs
- Bereich
- Elements
- Variants
- 2
- Version
- 1.0.0 · seit 1.0.0
- Datei
- components/ui/textarea.tsx
- Bringt mit
- utilskitinput
- npm-Pakete
- Keine
- Sprachen
- Englisch und Deutsch, 2 eigene Texte
- Studio
- Im Code anpassen
- Mit KI bauen
- Per MCP in Claude, Cursor, Copilot und Codex
Props
Die Schnittstelle TextareaProps aus components/ui/textarea.tsx. Beschreibungen stammen aus den Kommentaren im Code und sind auf Englisch. Nimmt außerdem alle Props von FieldOwnProps, Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'maxLength'> an.
autoResizeoptionalbooleanGrows with its content between minRows and maxRows (CSS field-sizing, falls back to rows)
minRowsoptionalnumbermaxRowsoptionalnumbermaxLengthoptionalnumberShows a counter. Going over is allowed while typing and shown as an error, so nothing gets cut off silently.
footeroptionalReact.ReactNodeSomething in the footer row, e.g. formatting hints or an attach button
invalidoptionalbooleanrefoptionalReact.Ref<HTMLTextAreaElement>
Eingebaute Texte
Diese Texte schreibt Textbereich selbst. Die Sprache folgt dem KitProvider, über die Prop labels ersetzt du einzelne.
Alle 2 Texte anzeigen
| Schlüssel | Englisch | Deutsch |
|---|---|---|
| left | Englisch characters left | Deutsch Zeichen übrig |
| over | Englisch characters too many | Deutsch Zeichen zu viel |
Barrierefreiheit
Aus dem Quellcode der Component abgeleitet.
- Setzt aria-describedby und aria-invalid, damit Screenreader Zweck und Zustand ansagen.
- Ergänzt Text für Screenreader, wo Icons und Grafiken allein stehen.
- Der Server rendert den Startzustand vollständig, JavaScript ergänzt nur die Interaktion.
Bewegung
- Ohne Animationen, sie steht sofort ruhig da.
Quellcode
Die Datei, die aiw add in dein Projekt legt. Sie gehört danach dir.
Datei anzeigen, 86 Zeilen
'use client';
import { useRef, useState } from 'react';
import { cn, useLocale, useTexts } from '@/lib/kit';
import { controlBox, useControl, useShake, withField, type FieldOwnProps } from '@/components/ui/input';
const TEXTS = {
en: { left: 'characters left', over: 'characters too many' },
de: { left: 'Zeichen übrig', over: 'Zeichen zu viel' },
};
export interface TextareaProps extends FieldOwnProps, Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'maxLength'> {
/** Grows with its content between minRows and maxRows (CSS field-sizing, falls back to rows) */
autoResize?: boolean;
minRows?: number;
maxRows?: number;
/** Shows a counter. Going over is allowed while typing and shown as an error, so nothing gets cut off silently. */
maxLength?: number;
/** Something in the footer row, e.g. formatting hints or an attach button */
footer?: React.ReactNode;
invalid?: boolean;
ref?: React.Ref<HTMLTextAreaElement>;
labels?: Partial<(typeof TEXTS)['en']>;
className?: string;
}
function TextareaBox({ autoResize = true, minRows = 3, maxRows = 10, maxLength, footer, invalid, labels, className, value, defaultValue, onChange, ref, ...rest }: Omit<TextareaProps, keyof FieldOwnProps>) {
const t = useTexts(TEXTS, labels);
const locale = useLocale();
const c = useControl({ ...rest, invalid });
const [inner, setInner] = useState(String(defaultValue ?? ''));
const text = value !== undefined ? String(value) : inner;
const over = maxLength !== undefined && text.length > maxLength;
const left = maxLength !== undefined ? maxLength - text.length : 0;
const fmt = (n: number) => n.toLocaleString(locale === 'de' ? 'de-DE' : 'en-US');
const showFooter = maxLength !== undefined || footer;
const boxRef = useRef<HTMLDivElement>(null);
// One shake when the text goes over the limit or the field turns invalid
useShake(boxRef, c.invalid || over);
return (
<div ref={boxRef} data-invalid={c.invalid || over || undefined} data-disabled={c.disabled || undefined} className={cn('flex w-full flex-col overflow-hidden rounded-lg', controlBox, className)}>
<textarea
{...rest}
ref={ref}
id={c.id}
value={value}
defaultValue={value === undefined ? defaultValue : undefined}
onChange={(e) => {
setInner(e.target.value);
onChange?.(e);
}}
disabled={c.disabled}
required={c.required}
aria-invalid={c.invalid || over || undefined}
aria-describedby={c['aria-describedby']}
rows={minRows}
style={{ minHeight: `calc(${minRows} * 1.5em + 1.25rem)`, maxHeight: `calc(${maxRows} * 1.5em + 1.25rem)` }}
className={cn(
'w-full resize-none bg-transparent px-3.5 py-2.5 text-base leading-[1.5] text-inherit outline-none placeholder:text-subtle-foreground disabled:cursor-not-allowed sm:text-sm sm:leading-[1.5]',
autoResize ? '[field-sizing:content]' : 'resize-y',
'kit-scrollbar',
)}
/>
{showFooter && (
<div className="flex min-h-10 items-center justify-between gap-3 px-2 pb-2 ps-3.5">
<div className="flex min-w-0 flex-1 items-center gap-1">{footer}</div>
{maxLength !== undefined && (
<p className={cn('ms-auto shrink-0 text-xs tabular-nums transition-colors duration-300', over ? 'font-medium text-destructive' : left <= maxLength * 0.1 ? 'text-foreground' : 'text-subtle-foreground')}>
<span aria-hidden>{over ? `−${fmt(-left)}` : `${fmt(text.length)} / ${fmt(maxLength)}`}</span>
<span className="sr-only">{over ? `${fmt(-left)} ${t.over}` : `${fmt(left)} ${t.left}`}</span>
</p>
)}
</div>
)}
</div>
);
}
/**
* Multi-line text that grows with its content, with an optional counter and footer.
* <Textarea label="Message" maxLength={500} hint="We reply within a day." />
*/
export function Textarea({ label, hint, error, optional, labelAction, className, ...rest }: TextareaProps) {
const wrapped = Boolean(label || hint || error);
return withField({ label, hint, error, optional, labelAction, id: rest.id, required: rest.required, disabled: rest.disabled, className }, <TextareaBox {...rest} className={wrapped ? undefined : className} />);
}Häufige Fragen
Wie installiere ich Textbereich?
Mit aiw add @ai-website/textarea. Der Befehl legt die Datei components/ui/textarea.tsx in dein Projekt, der Code gehört danach dir. Mit dabei sind input. Weitere npm-Pakete braucht sie nicht.
Welche Varianten hat Textbereich?
2 Varianten, Zustände und Eingabebox.
Kann ich die Texte von Textbereich übersetzen?
Ja. Textbereich bringt 2 eigene Texte auf Deutsch und Englisch mit, etwa „Zeichen übrig“ und „Zeichen zu viel“. Die Sprache folgt dem KitProvider, einzelne Texte ersetzt du über die Prop labels.
Kann ein KI-Assistent Textbereich einbauen?
Ja. Über den MCP-Server der aiw CLI finden Claude, Cursor, GitHub Copilot, Windsurf, Codex und Gemini Textbereich mit aiw_components und installieren sie mit aiw_add @ai-website/textarea.