Skip to content
v1.4.2
Fit

Textarea

A multi-line text field. Vertically resizable, with the same border/focus/disabled treatment as Input and an optional invalid state.

bash
jlds add textarea

Usage

html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/jarooda/jlds@main/registry/css/index.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/jarooda/jlds@main/registry/css/textarea.css">

<textarea class="jl-textarea" placeholder="Write a message…"></textarea>
vue
<script setup lang="ts">
import { ref } from "vue"
import { Textarea } from "@/components/ui/textarea"

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

<template>
  <Textarea v-model="message" placeholder="Write a message…" />
</template>
tsx
import { Textarea } from "@/components/ui/textarea"

<Textarea placeholder="Write a message…" />

Invalid & disabled

Add invalid for error styling, or the native disabled attribute.

html
<textarea class="jl-textarea" aria-invalid="true">Too short</textarea>
<textarea class="jl-textarea" disabled>Disabled</textarea>
vue
<template>
  <Textarea invalid model-value="Too short" />
  <Textarea disabled model-value="Disabled" />
</template>
tsx
<Textarea invalid defaultValue="Too short" />
<Textarea disabled defaultValue="Disabled" />

Auto-resize & counter

autoResize grows the field to fit its content; showCount (with maxLength) renders a character counter that turns red past the limit.

html
<!-- needs the behavior layer (js/all.js) -->
<span class="jl-textarea-wrap">
  <textarea class="jl-textarea jl-textarea--auto" data-auto-resize maxlength="140">Deploys in ~40s.</textarea>
  <span class="jl-textarea__count">15/140</span>
</span>
vue
<template>
  <Textarea v-model="msg" auto-resize show-count :max-length="140" />
</template>
tsx
<Textarea autoResize showCount maxLength={140} value={msg} onChange={(e) => setMsg(e.target.value)} />

Props

React

Textarea extends React.TextareaHTMLAttributes<HTMLTextAreaElement>, so rows, placeholder, value, onChange, disabled, etc. all pass through.

PropTypeDefaultDescription
invalidbooleanfalseShow error styling
autoResizebooleanfalseGrow to fit content
showCountbooleanfalseCharacter counter (with maxLength)

Vue

Textarea supports v-model; other attributes (rows, placeholder, disabled, …) fall through to the inner <textarea>.

PropTypeDefaultDescription
invalidbooleanfalseShow error styling
autoResizebooleanfalseGrow to fit content
showCountbooleanfalseCharacter counter (with maxLength)
maxLengthnumberMax characters (drives the counter)
modelValuestringBound value (v-model)

CSS classes (HTML)

ClassPurpose
.jl-textareaThe textarea — always required (vertically resizable by default)
[aria-invalid="true"]Error styling