Forms

Textarea

More room for ideas, with accessible labels.

OSCL StudioComponents, in context.Live preview
FOUNDATION / FORMS

Textarea

Interactive preview. Real components.View docs

Use it in your project

Install oscl-ui from npm and import oscl-ui/styles.css once. See installation.

textarea-example.tsx
import { Textarea } from "oscl-ui";

<Textarea label="Your idea" placeholder="Make it exist first…" />

Accessibility

Keep visible labels and keyboard focus. Supply an accessible name to icon-only actions. Try this preview with Tab, Enter, Space, and Escape where appropriate.

The source, in full

This is the actual source from the isolated OSCL package used by this website. Native props and TypeScript declarations are included in the npm package.

textarea.tsx
"use client";

import { forwardRef, useId } from "react";
import type { ReactNode, TextareaHTMLAttributes } from "react";

export interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {
  label: ReactNode;
  description?: string;
  error?: string;
}

export const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(function Textarea(
  { label, description, error, id, rows = 4, className = "", "aria-describedby": describedBy, ...props }, ref,
) {
  const generatedId = useId();
  const fieldId = id || generatedId;
  const descriptionIds = [describedBy, description && `${fieldId}-description`, error && `${fieldId}-error`].filter(Boolean).join(" ");
  return <div className={`oscl-field ${className}`}>
    <label className="oscl-label" htmlFor={fieldId}>{label}{props.required && <span aria-hidden="true"> *</span>}</label>
    <textarea {...props} ref={ref} id={fieldId} rows={rows} className="oscl-input oscl-textarea" aria-invalid={error ? true : props["aria-invalid"]}
      aria-describedby={descriptionIds || undefined} />
    {description && <p className="oscl-description" id={`${fieldId}-description`}>{description}</p>}
    {error && <p className="oscl-error" id={`${fieldId}-error`}>{error}</p>}
  </div>;
});