Primitives
Textarea
A field for text on more than one line.
The description shows on the project page.
import { Field, Textarea } from 'ferry-ui'
export default function TextareaHero() {
return (
<Field label="Description" optional hint="The description shows on the project page." className="w-full max-w-md">
<Textarea placeholder="What is this project for?" />
</Field>
)
}mono is for content that looks like code, such as JSON. To edit real code, use an editor component.aria-label.Import the component. A textarea has one part.
import { Textarea } from 'ferry-ui'
<Textarea />A textarea grows with its content. The minimum height is 80px.
Add a max-h-* class to set a maximum height. The textarea then scrolls.
import { Field, Textarea } from 'ferry-ui'
const RELEASE_NOTES = [
'- Invoices: the list loads faster.',
'- Invoices: a filter by status.',
'- Members: an owner can change a role from the list.',
'- Members: an invitation stays valid for seven days.',
'- API keys: each key shows the date of its last use.',
'- Orders: the export contains the customer email.',
'- Projects: the search finds archived projects.',
'- Settings: a new page for the billing address.',
'- Fixed: the total of an order with a discount.',
'- Fixed: the date format in the exports.',
].join('\n')
export default function TextareaMaxHeight() {
return (
<Field label="Release notes" className="w-full max-w-md">
<Textarea className="max-h-40" defaultValue={RELEASE_NOTES} />
</Field>
)
}Add the field-sizing-fixed class to stop the growth. Then set the height with rows or with an h-* class.
import { Field, Textarea } from 'ferry-ui'
export default function TextareaFixed() {
return (
<Field label="Short note" className="w-full max-w-md">
<Textarea className="field-sizing-fixed" rows={3} placeholder="Three rows, always" />
</Field>
)
}Set mono for content that looks like code: JSON, a certificate or a list of keys.
The app sends this JSON to your endpoint.
import { Field, Textarea } from 'ferry-ui'
const PAYLOAD = `{
"event": "invoice.paid",
"invoice": "INV-2041",
"amount": 1280,
"currency": "eur"
}`
export default function TextareaMono() {
return (
<Field label="Test payload" hint="The app sends this JSON to your endpoint." className="w-full max-w-md">
<Textarea mono defaultValue={PAYLOAD} />
</Field>
)
}disabled stops all input. aria-invalid shows the error border. Field sets it when you pass error.
Enter 10 characters or more.
import { Field, Textarea } from 'ferry-ui'
export default function TextareaStates() {
return (
<div className="flex w-full max-w-md flex-col gap-5">
<Field label="Notes">
<Textarea disabled defaultValue="You cannot edit an archived project." />
</Field>
<Field label="Reason" error="Enter 10 characters or more.">
<Textarea defaultValue="Too short" />
</Field>
</div>
)
}A textarea holds its value by default. Use defaultValue for the first value.
To control the value, pass value and onChange. This example counts the characters that the user can add.
280 characters left
import * as React from 'react'
import { Field, Textarea } from 'ferry-ui'
const MAX_LENGTH = 280
export default function TextareaControlled() {
const [message, setMessage] = React.useState('')
return (
<Field label="Feedback" hint={`${MAX_LENGTH - message.length} characters left`} className="w-full max-w-md">
<Textarea
placeholder="What must we change on the billing page?"
maxLength={MAX_LENGTH}
value={message}
onChange={(event) => setMessage(event.target.value)}
/>
</Field>
)
}aria-describedby. Field does this for you.Textarea also accepts each attribute of the <textarea> element.
| Prop | Type | Default |
|---|---|---|
mono | boolean | false |
Monospace face at 13px with relaxed line height. Use for code-like content (JSON, config snippets, certificates, lists of keys); keep prose in sans. | ||