Inspector Textarea

The family's block row: the same surface and tones, but the label sits above a multi-line field whose height comes from the text, with a character count whenever there is a limit to see. Collapsible, so a paragraph written once can be folded down to the height of a row without leaving the form.

Installation

Adds the component and everything it depends on to your project.

npx shadcn add https://ui.beste.co/component/r-base/inspector-textarea

New here? Read the installation guide.

Usage

The import and the props worth knowing about, in one place.

import { InspectorTextarea } from "@/components/beste/component/inspector-textarea";

// Uncontrolled. The whole block is a label, so a press anywhere puts the caret in.
<InspectorTextarea label="Description" defaultValue="A short line about the section." />

// Controlled, with a separate commit for expensive work
<InspectorTextarea
  label="Alt text"
  value={alt}
  onValueChange={setAlt}                                // every keystroke
  onValueCommit={(value) => console.log("persist", value)} // on blur, if it changed
  placeholder="Describe the image"
  rows={4}
/>

// A limit brings a count with it, since a limit nobody can see is a trap
<InspectorTextarea label="Summary" maxLength={160} value={summary} onValueChange={setSummary} />

<InspectorTextarea
  label="Custom CSS"
  icon={Code}            // optional leading icon
  rows={6}
  fixedHeight            // stay at `rows` and scroll, rather than growing
  tone="outline"         // "muted" (default) | "outline" | "ghost"
  size="sm"              // padding preset; the height comes from `rows`
  value={css}
  onValueChange={setCss}
/>

// Read-only, and taking part in a form
<InspectorTextarea label="Notes" name="notes" value={notes} onValueChange={setNotes} />
<InspectorTextarea label="Generated" value={output} readOnly />

// Folded away when it is not being written. Closed, the block measures exactly what
// a row of the family measures, and any character count stays in the header.
<InspectorTextarea label="Description" collapsible defaultOpen={false} onOpenChange={(open) => console.log("open:", open)} />

Playground

Turn the props on the right; the snippet under them is what you would write to get what you see.

Usage
import { InspectorTextarea } from "@/components/beste/component/inspector-textarea";

<InspectorTextarea
  label="Description"
  className="w-72"
  collapsible
  defaultValue="A short line about the section, shown under the heading."
  placeholder="Optional"
  maxLength={160}
/>

Props

Read from the component's own type, so this cannot drift from what it accepts.

PropTypeDefaultDescription
label*stringLabel rendered above the field, inside the block.
iconLucideIconOptional leading icon shown before the label.
valuestringControlled value. Pair it with `onValueChange`.
defaultValuestringInitial value in uncontrolled mode.
onValueChange(value: string) => voidFires on every keystroke.
onValueCommit(value: string) => voidFires once the edit is finished — leaving the field — and only when the value actually changed. Use it for work too expensive to run per keystroke.
placeholderstringGhost text shown while the field is empty.
rowsnumber3Lines the field opens at. It grows past this as text is typed, where the browser supports sizing a field to its content.
fixedHeightbooleanKeep the field at `rows` and scroll instead of growing.
collapsiblebooleanLet the block be folded away, leaving its header. A paragraph is several rows tall and usually written once, so the panel around it is otherwise mostly a scroll past something nobody is editing.
openbooleanControlled open state. Pair it with `onOpenChange`.
defaultOpenbooleantrueWhether it starts open in uncontrolled mode.
onOpenChange(open: boolean) => void
maxLengthnumberLongest the value may be. Setting it also puts a count beside the label, which is the only reason a reader can tell how much room is left.
disabledbooleanBlock interaction and dim the block.
readOnlybooleanShow the value but refuse edits.
tone"muted" | "outline" | "ghost""muted"Surface treatment: filled (default), hairline outline, or bare until focus.
size"sm" | "default" | "lg""default"Padding preset.
namestringName of the field, so the block can take part in a form.
idstringId of the field. One is generated when it is not given.
classNamestring
aria-labelstringAccessible name. Falls back to the visible label.

More Inspector components

View all Inspector

Inspector Code

Settings block for a snippet: a monospaced field with a language chip and a line count, Tab indenting instead of leaving, and a fixed height so a pasted stylesheet cannot push the rest of the drawer out of reach. Collapsible, since a snippet is the tallest thing in a drawer and the least often touched; folded, it measures exactly what a row measures and still reports its line count.

landing pagesaaspricing

Inspector Tags

Settings block for a list of short strings: tags are typed one after another and wrap under the label, a comma or a paste splits several at once, and Backspace on an empty field reaches back into the list. Collapsible, so a long list folds down to the height of a row with the count still on it.

Inspector Border

Settings row for a border: the row draws one exactly as described beside a summary of it, and opens an editor with the sides as icon toggles and the width, style and colour under them, each one a row of the family.

Inspector Input

Settings row with a label on the left and a plain text field on the right, sharing the family's pill: the whole row is the label, so pressing anywhere puts the caret in the field.

Inspector Align

Where the contents of a box sit in it: nine cells drawn in visual terms, mapped onto justify and align afterwards so the pair swapping places under a column direction is the component's problem and not the reader's. Direction, distribution and stretch sit under the pad as rows of the family, since each is a setting like any other.

Applies to every breakpoint.

Inspector Note

The line of prose that belongs between rows: what a setting is for, why one is switched off, what a value will cost. Four tones, each with its own mark, and the same text size as the rows around it.