Textarea

Multi-line text input field for longer user input.

import { TextArea } from 'ui-lab-components/textarea';
 
export function Example() {
  return (
    <TextArea
      placeholder="Enter your text here..."
      rows={4}
    />
  );
}

textarea/01-textarea-basic-textarea

TextArea with a character limit and submit button — disabled until the user types.

Loading interactive preview
"use client";
 
import { useState } from 'react';
import { TextArea } from 'ui-lab-components/textarea'
import { Flex } from 'ui-lab-components/flex'
import { Button } from 'ui-lab-components/button';
 
export const metadata = {
  title: 'Feedback Form',
  description: 'TextArea with a character limit and submit button — disabled until the user types.'
};
 
export default function Example() {
  const [value, setValue] = useState("");
 
  return (
    <Flex direction="column" gap="sm" style={{ width: 380 }}>
      <TextArea
        placeholder="Tell us what you think..."
        value={value}
        onChange={(e) => setValue(e.target.value)}
        showCharacterCount
        maxCharacters={300}
        rows={4}
      />
      <Button variant="primary" disabled={value.trim().length === 0} className="self-end">
        Submit
      </Button>
    </Flex>
  );
}
 

textarea/02-textarea-bio-settings

Fixed-height settings textarea with a 160-character cap and save/clear actions.

Loading interactive preview
"use client";
 
import { useState } from 'react';
import { TextArea } from 'ui-lab-components/textarea'
import { Flex } from 'ui-lab-components/flex'
import { Button } from 'ui-lab-components/button';
 
export const metadata = {
  title: 'Profile Bio',
  description: 'Fixed-height settings textarea with a 160-character cap and save/clear actions.'
};
 
export default function Example() {
  const [bio, setBio] = useState("UI designer & developer building minimal tools.");
 
  return (
    <Flex direction="column" gap="sm" style={{ width: 380 }}>
      <TextArea
        value={bio}
        onChange={(e) => setBio(e.target.value)}
        showCharacterCount
        maxCharacters={160}
        rows={3}
        resizable={false}
      />
      <Flex justify-end gap="sm">
        <Button size="sm" variant="ghost" onClick={() => setBio("")}>Clear</Button>
        <Button size="sm" variant="primary">Save</Button>
      </Flex>
    </Flex>
  );
}
 

textarea/03-textarea-error-state

Error styling triggered when the input is non-empty but below a minimum length.

Loading interactive preview
"use client";
 
import { useState } from 'react';
import { TextArea } from 'ui-lab-components/textarea'
import { Flex } from 'ui-lab-components/flex';
 
export const metadata = {
  title: 'Validation Error',
  description: 'Error styling triggered when the input is non-empty but below a minimum length.'
};
 
export default function Example() {
  const [value, setValue] = useState("");
  const hasError = value.trim().length > 0 && value.trim().length < 20;
 
  return (
    <Flex direction="column" gap="sm" style={{ width: 380 }}>
      <TextArea
        placeholder="Describe the issue in detail..."
        value={value}
        onChange={(e) => setValue(e.target.value)}
        error={hasError}
        rows={4}
      />
      {hasError && (
        <span style={{ fontSize: "0.75rem", var(--color-destructive)" }}>
          Description must be at least 20 characters.
        </span>
      )}
    </Flex>
  );
}
 

textarea/04-textarea-disabled-readonly

Side-by-side disabled and read-only states to compare their visual treatment.

Loading interactive preview
import { TextArea } from 'ui-lab-components/textarea'
import { Flex } from 'ui-lab-components/flex';
 
export const metadata = {
  title: 'Disabled & Read-only',
  description: 'Side-by-side disabled and read-only states to compare their visual treatment.'
};
 
export default function Example() {
  return (
    <Flex direction="column" gap="md" style={{ width: 380 }}>
      <TextArea
        value="This field is disabled and cannot be edited."
        disabled
        rows={2}
        resizable={false}
      />
      <TextArea
        value="This is a read-only note visible to all team members."
        readOnly
        rows={2}
        resizable={false}
      />
    </Flex>
  );
}
 

textarea/05-textarea-scrolling

TextArea bounded by a max height — content scrolls once it overflows.

Loading interactive preview
"use client";
 
import { useState } from 'react';
import { TextArea } from 'ui-lab-components/textarea'
import { Flex } from 'ui-lab-components/flex';
 
export const metadata = {
  title: 'Scrollable with maxHeight',
  description: 'TextArea bounded by a max height — content scrolls once it overflows.'
};
 
export default function Example() {
  const [value, setValue] = useState(
    "Line 1\nLine 2\nLine 3\nLine 4\nLine 5\nLine 6\nLine 7\nLine 8"
  );
 
  return (
    <Flex direction="column" gap="sm" style={{ width: 380 }}>
      <TextArea
        value={value}
        onChange={(e) => setValue(e.target.value)}
        maxHeight="120px"
        resizable={false}
      />
    </Flex>
  );
}
 
UI Lab