Components

Textarea

A form textarea that auto-grows to fit its content, with optional rows and a max-rows cap.

php artisan blatui:add textarea
<div class="w-full max-w-sm">
    <x-ui.textarea placeholder="Type your message here." />
</div>

Autosize

Starts at two rows and grows to six before it scrolls.

{{-- Set maxRows to auto-grow with the content, then scroll once it hits the cap. --}}
<div class="grid w-full max-w-sm gap-2">
    <x-ui.label for="autosize-message">Your message</x-ui.label>
    <x-ui.textarea
        id="autosize-message"
        name="message"
        :rows="2"
        :max-rows="6"
        placeholder="Grows up to 6 rows as you type, then scrolls…"
    />
    <p class="text-muted-foreground text-sm">Starts at two rows and grows to six before it scrolls.</p>
</div>

Character Count

characters left

{{-- Live "characters left" counter backed by maxlength. --}}
<div x-data="{ text: '', max: 200 }" class="w-full max-w-md space-y-2">
    <x-ui.label for="ta-feedback">Your feedback</x-ui.label>
    <x-ui.textarea
        id="ta-feedback"
        x-model="text"
        maxlength="200"
        placeholder="Leave us some feedback…"
        aria-describedby="ta-count"
    />
    <p id="ta-count" class="text-muted-foreground text-right text-xs">
        <span x-text="max - text.length"></span> characters left
    </p>
</div>

Disabled

<div class="w-full max-w-sm">
    <x-ui.textarea placeholder="Type your message here." disabled />
</div>

Invalid

<div class="grid w-full max-w-sm gap-2">
    <x-ui.label for="bio-invalid">Bio</x-ui.label>
    <x-ui.textarea id="bio-invalid" aria-invalid="true" aria-describedby="bio-invalid-hint" placeholder="Tell us a little about yourself" />
    <p id="bio-invalid-hint" role="alert" class="text-destructive text-sm">Bio must be at least 10 characters.</p>
</div>

No Resize

{{-- Lock the manual resize handle with resize-none. --}}
<x-ui.textarea class="w-full max-w-md resize-none" placeholder="This textarea can't be resized." />

Read Only

{{-- A non-editable textarea. --}}
<x-ui.textarea readonly aria-label="Read-only content" class="bg-muted w-full max-w-md">The quick brown fox jumps over the lazy dog. This content is read-only and cannot be edited.</x-ui.textarea>

Sizes

{{-- size sets the min-height, padding and text size: sm · default · lg. --}}
<div class="grid w-full max-w-sm gap-4">
    <x-ui.textarea size="sm" placeholder="Small" />
    <x-ui.textarea placeholder="Default" />
    <x-ui.textarea size="lg" placeholder="Large" />
</div>

Utility Class

{{-- Raw <textarea> styled by the .blat-textarea foundations utility — native submit, no JS, and
     safe to nest inside another anonymous component's slot (no nested slot-component to compile). --}}
<textarea class="blat-textarea w-full max-w-sm" rows="3" placeholder="Your message…"></textarea>

With Button

<div class="grid w-full max-w-sm gap-2">
    <x-ui.label for="ta-send">Your message</x-ui.label>
    <x-ui.textarea id="ta-send" placeholder="Type your message here." />
    <x-ui.button class="w-fit">Send message</x-ui.button>
</div>

With Color

{{-- color brands the focus ring and text selection locally — focus the field to see it. --}}
<div class="grid w-full max-w-sm gap-2">
    <x-ui.label for="colored-note">Note</x-ui.label>
    <x-ui.textarea id="colored-note" color="#7c3aed" placeholder="Focus me to see the violet ring." />
</div>

With Label

<div class="grid w-full max-w-sm gap-2">
    <x-ui.label for="message">Your message</x-ui.label>
    <x-ui.textarea id="message" placeholder="Type your message here." />
</div>

With Text

Your message will be shared with the support team.

<div class="grid w-full max-w-sm gap-2">
    <x-ui.label for="ta-feedback">Your message</x-ui.label>
    <x-ui.textarea id="ta-feedback" placeholder="Type your message here." />
    <p class="text-muted-foreground text-sm">Your message will be shared with the support team.</p>
</div>

Using with Livewire

wire:model

The examples above are the frontend (Blade + Alpine) usage. Inside a Livewire component, bind wire:model for two-way state — same component, no wrappers. Full Livewire guide →

app/Livewire/Demo.php
use Livewire\Component;

class Demo extends Component
{
    public string $bio = '';

    public function render()
    {
        return view('livewire.demo');
    }
}
resources/views/livewire/demo.blade.php
<x-ui.textarea wire:model="bio" placeholder="About you" />

API Reference

Props, slots and exposed methods for <x-ui.textarea>.

Props

Prop Type Default Description
size string 'default' Minimum height, padding and text size of the field.
sm default lg
color string CSS color that brands the focus ring and text selection locally, overriding the default ring/primary tokens.
rows int Initial number of visible text rows (the native rows attribute). Unset uses the size-based min-height.
maxRows int Caps auto-growth at this many rows, then scrolls. When set, the field switches from native field-sizing-content auto-grow to an Alpine-driven height that shrinks and grows with the content. Unlimited (native auto-grow) when not set.

Slots

Slot Description
default Initial text content rendered inside the textarea.