Textarea field
Several lines of text, with optional addons.
Installation
npx shadcn@latest add @formdef/textarea-fieldRegister it under widgets in lib/formdef/index.tsx, as widgets: { textarea: TextareaField }.
The widget serves string values.
Usage
export const = createForm({
: .({ : .().(500, 'Keep it under 500 characters') }),
: { : '' },
fields: {
feedback: { : 'textarea', : { : 'Feedback', : 6, : 500 } },
},
})rows sets the starting height. maxLength stops typing at the limit; the schema's max is what
rejects a longer value, so a limit that matters belongs in both.
Like the text field, it takes addons inside its border. Above or
below
the text, align: 'block-start' or align: 'block-end' places them.
Props
Prop
Type
Source
import { type FieldOf, fieldParts } from '@formdef/core'
import type { ComponentProps } from 'react'
import { FieldFrame } from '@/components/formdef/field-frame'
import { InputGroup, InputGroupAddon, InputGroupTextarea } from '@/components/ui/input-group'
import { Textarea } from '@/components/ui/textarea'
import type { Addon } from '@/lib/formdef/addons'
import type { FieldLabels } from '@/lib/formdef/field-labels'
type Attrs = Pick<
ComponentProps<'textarea'>,
| 'className'
| 'placeholder'
| 'autoComplete'
| 'autoFocus'
| 'disabled'
| 'readOnly'
| 'required'
| 'maxLength'
| 'rows'
| 'spellCheck'
>
type TextareaFieldProps = FieldOf<string> &
FieldLabels &
Attrs & {
addons?: Addon[]
}
export const TextareaField = ({
field,
label,
labelAside,
description,
addons = [],
...attrs
}: TextareaFieldProps) => {
const parts = fieldParts(field, { description })
const value = field.state.value ?? ''
const hasAddons = addons.length > 0
const Control = hasAddons ? InputGroupTextarea : Textarea
const textarea = (
<Control
{...attrs}
{...parts.control}
value={value}
onChange={(event) => field.handleChange(event.target.value)}
/>
)
return (
<FieldFrame
parts={parts}
label={label}
labelAside={labelAside}
description={description}
disabled={attrs.disabled}
>
{hasAddons ? (
<InputGroup>
{textarea}
{addons.map((addon) => (
<InputGroupAddon key={addon.id} align={addon.align}>
{addon.content}
</InputGroupAddon>
))}
</InputGroup>
) : (
textarea
)}
</FieldFrame>
)
}