Skip to main content

Overview

The Textarea component provides a multi-line text input with support for auto-resizing, leading/trailing icons, different variants, and seamless integration with Form components.

Basic Usage

<script setup lang="ts">
import { ref } from 'vue'

const message = ref('')
</script>

<template>
  <UTextarea v-model="message" placeholder="Enter your message..." />
</template>

Auto-resize

<template>
  <!-- Auto-resize based on content -->
  <UTextarea
    v-model="message"
    autoresize
    placeholder="This will grow as you type"
  />
  
  <!-- With max rows -->
  <UTextarea
    v-model="message"
    autoresize
    :rows="3"
    :maxrows="10"
    placeholder="Grows up to 10 rows"
  />
</template>

With Icons

<template>
  <!-- Leading icon -->
  <UTextarea
    leading-icon="i-heroicons-chat-bubble-left"
    placeholder="Enter your comment..."
  />
  
  <!-- Trailing icon -->
  <UTextarea
    trailing-icon="i-heroicons-check"
    placeholder="Your bio"
  />
</template>

Rows

<template>
  <!-- Default 3 rows -->
  <UTextarea placeholder="3 rows" />
  
  <!-- Custom rows -->
  <UTextarea :rows="5" placeholder="5 rows" />
  
  <!-- Many rows -->
  <UTextarea :rows="10" placeholder="10 rows" />
</template>

Colors

<template>
  <UTextarea color="primary" placeholder="Primary" />
  <UTextarea color="secondary" placeholder="Secondary" />
  <UTextarea color="success" placeholder="Success" />
  <UTextarea color="warning" placeholder="Warning" />
  <UTextarea color="error" placeholder="Error" />
  <UTextarea color="neutral" placeholder="Neutral" />
</template>

Variants

<template>
  <UTextarea variant="outline" placeholder="Outline" />
  <UTextarea variant="soft" placeholder="Soft" />
  <UTextarea variant="ghost" placeholder="Ghost" />
  <UTextarea variant="none" placeholder="None" />
</template>

Sizes

<template>
  <UTextarea size="xs" placeholder="Extra Small" />
  <UTextarea size="sm" placeholder="Small" />
  <UTextarea size="md" placeholder="Medium" />
  <UTextarea size="lg" placeholder="Large" />
  <UTextarea size="xl" placeholder="Extra Large" />
</template>

States

<template>
  <!-- Disabled -->
  <UTextarea disabled placeholder="Disabled" />
  
  <!-- Required -->
  <UTextarea required placeholder="Required field" />
  
  <!-- Highlighted -->
  <UTextarea highlight placeholder="Highlighted" />
  
  <!-- Loading -->
  <UTextarea loading placeholder="Loading..." />
</template>

Model Modifiers

<script setup lang="ts">
import { ref } from 'vue'

const trimmed = ref('')
const nullable = ref(null)
</script>

<template>
  <!-- Trim whitespace -->
  <UTextarea v-model.trim="trimmed" />
  
  <!-- Nullable (empty = null) -->
  <UTextarea v-model.nullable="nullable" />
  
  <!-- Optional (empty = undefined) -->
  <UTextarea v-model.optional="optional" />
  
  <!-- Lazy (update on change, not input) -->
  <UTextarea v-model.lazy="lazy" />
</template>

Autofocus

<template>
  <!-- Immediate autofocus -->
  <UTextarea autofocus placeholder="Focused on mount" />
  
  <!-- Delayed autofocus -->
  <UTextarea autofocus :autofocus-delay="500" placeholder="Focused after 500ms" />
</template>

With Form

<script setup lang="ts">
import { z } from 'zod'
import { ref } from 'vue'

const schema = z.object({
  bio: z.string().min(10, 'Bio must be at least 10 characters'),
  notes: z.string().max(500, 'Notes cannot exceed 500 characters')
})

const state = ref({
  bio: '',
  notes: ''
})
</script>

<template>
  <UForm :schema="schema" :state="state">
    <UFormField label="Bio" name="bio">
      <UTextarea
        v-model="state.bio"
        autoresize
        placeholder="Tell us about yourself"
      />
    </UFormField>
    
    <UFormField label="Notes" name="notes">
      <UTextarea
        v-model="state.notes"
        :rows="5"
        placeholder="Additional notes"
      />
    </UFormField>
  </UForm>
</template>

Character Count

<script setup lang="ts">
import { ref, computed } from 'vue'

const message = ref('')
const maxLength = 280
const remaining = computed(() => maxLength - message.value.length)
</script>

<template>
  <UFormField label="Message" :hint="`${remaining} characters remaining`">
    <UTextarea
      v-model="message"
      :maxlength="maxLength"
      placeholder="What's on your mind?"
    />
  </UFormField>
</template>

Props

modelValue
string | number | null
The controlled value. Can be bound with v-model.
defaultValue
string | number | null
The default value when initially rendered.
placeholder
string
Placeholder text when the textarea is empty.
name
string
The name attribute for the textarea.
id
string
The id attribute for the textarea.
rows
number
default:"3"
Number of visible text rows.
maxrows
number
default:"0"
Maximum number of rows when autoresize is enabled (0 = unlimited).
autoresize
boolean
Enable automatic height adjustment based on content.
autoresizeDelay
number
default:"0"
Delay in milliseconds before initial auto-resize.
color
'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'neutral'
default:"primary"
Color variant of the textarea.
variant
'outline' | 'soft' | 'ghost' | 'none'
default:"outline"
Visual variant of the textarea.
size
'xs' | 'sm' | 'md' | 'lg' | 'xl'
default:"md"
Size variant of the textarea.
leadingIcon
string
Icon name to display at the start.
trailingIcon
string
Icon name to display at the end.
avatar
AvatarProps
Avatar configuration to display at the start.
loading
boolean
Show loading indicator.
disabled
boolean
Disable the textarea.
required
boolean
Mark the textarea as required.
highlight
boolean
Highlight the ring color like a focus state.
fixed
boolean
Keep the mobile text size on all breakpoints.
autofocus
boolean
Automatically focus the textarea on mount.
autofocusDelay
number
default:"0"
Delay in milliseconds before autofocus.
modelModifiers
{ trim?: boolean, lazy?: boolean, nullable?: boolean, optional?: boolean }
Model modifiers for value transformation.
as
any
default:"div"
The element or component this component should render as.
class
any
Additional CSS classes.
ui
object
UI customization object for styling slots.

Events

@update:modelValue
(value: string | number | null) => void
Emitted when the textarea value changes.
@blur
(event: FocusEvent) => void
Emitted when the textarea loses focus.
@change
(event: Event) => void
Emitted when the textarea value is committed.

Slots

leading
{ ui: object }
Custom content for the leading slot.
trailing
{ ui: object }
Custom content for the trailing slot.
default
{ ui: object }
Default slot (rarely used, textarea is the main element).

Exposed

textareaRef
Ref<HTMLTextAreaElement>
Reference to the underlying textarea element.

Build docs developers (and LLMs) love