Textarea
The multi-line counterpart to Input, with the same label, error and alignment behaviour.
'use client'
import * as React from 'react'
import { Textarea } from '@/components/custom/textarea'
const LIMIT = 140
export default function TextareaDemo() {
const [reason, setReason] = React.useState('')
const tooLong = reason.length > LIMIT
return (
<div className="w-full max-w-sm">
<Textarea
label="Reason for leave"
required
placeholder="A sentence or two is plenty."
value={reason}
onChange={(event) => setReason(event.target.value)}
error={tooLong}
errorMessage={`${reason.length}/${LIMIT} characters — trim it down.`}
/>
</div>
)
}Installation
pnpm dlx shadcn@latest add https://kiotapay-ui-staging.staging.kiotapay.com/r/textarea.jsonnpx shadcn@latest add https://kiotapay-ui-staging.staging.kiotapay.com/r/textarea.jsonyarn dlx shadcn@latest add https://kiotapay-ui-staging.staging.kiotapay.com/r/textarea.jsonbunx --bun shadcn@latest add https://kiotapay-ui-staging.staging.kiotapay.com/r/textarea.jsonUsage
'use client'
import { Textarea } from '@/components/custom/textarea'
export function ReasonField({ form }) {
return (
<Textarea
label="Reason for leave"
required
rows={5}
placeholder="A sentence or two is plenty."
{...form.register('reason')}
error={Boolean(form.formState.errors.reason)}
errorMessage={form.formState.errors.reason?.message}
/>
)
}Props
Extends React.ComponentProps<'textarea'>.
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | — | Required. Rendered above the field and wired to it by id. |
mode | 'left' | 'center' | 'right' | 'left' | Aligns label, control and error together. |
error | boolean | false | Switches the border and ring to the danger ramp. |
errorMessage | ReactNode | — | Shown only while error is true. |
rows | number | 4 | Initial height. |
Behaviour notes
The label does not float. A floating label has to hide itself once the field has content, so the field's purpose disappears exactly when someone is deep enough in the text to have forgotten it — and while empty it occupies the same space as the placeholder, leaving one of the two permanently invisible.
Resizing is vertical only. Horizontal resize breaks out of the form's column on every layout that has one.