Menu


Text area


A text box for several lines: the input well grown tall, with a grip at its corner to make it taller.

Customize the preview


Flags
View

Options


Text area options
ChoiceValuesDefaultWhat it does
errorsmbk-text-area--errorOn or offOff
The value is invalid. Draws the danger border, kept while focused, and the error icon at the top end; the control also carries aria-invalid.

Partssmbk-text-area__controlsmbk-text-area__grip

Examples


Usage

Two rows tall, with the grip in the corner to make it taller.

Filled

With a value that wraps over several lines.

Error

The danger border and the warning icon at the top end say the value is invalid.

Read only

Flat on the page, with no grip: the text can be read and copied, not changed.

Disabled

Dimmed and out of reach.

Taller

More rows to start with, for longer answers.

Guidelines


Purpose

A text box for answers that run to sentences: a message, a description, a note. It is the input's well grown tall, so it looks and reacts exactly like the input, with a grip in its corner that the reader can drag to make it taller. For a single short value, use the input.

When to use

  • Free text likely to wrap or hold several sentences: a support request, a comment, a project description.

When not to use

  • A name, an email, a number or any other short value. Use the input; a tall box asks for more than is wanted.
  • Rich text with formatting. That needs an editor, which this system does not have.
  • A choice from known values. Use the select, radios or checkboxes.

Usage rules

Do

  • Set the starting rows to the length of answer expected, so the box says how much to write.
  • Say any length limit before the reader starts, in the field's help text.

Don't

  • Use it for a short single value.
  • Clear what the reader wrote when the form shows an error.
  • Round it into a capsule. Its corner is a control corner, as every field's is; a capsule reads as a one-line search or a tag.
Do

Use a text area for answers that run to sentences, so the reader sees what they have written.

Don't

A one-line answer such as a name or an email belongs in an input; a tall box asks for more than is wanted.

Anatomy

  • The block, the well. It always sits on the input's block, which draws the sunken surface, the hairline highlight edge, the inset shadow and every state.
  • The control part, the native textarea, carrying the input's control part as well. It holds the padding, so the browser's resize handle sits in the well's corner.
  • The grip part, the notches icon a hairline step in from the corner. It only draws; the browser's handle under it takes the pointer.
  • In error, the input's error icon, a warning sign at the top end, on the first line.

Behavior

It starts two rows tall, the height Figma draws, and takes any other number of rows. The reader can drag the corner to make it taller; its width follows the layout. Text longer than the box scrolls inside it with the system's scrollbar: a thin, see-through bar over its text that takes no room and shows while the mouse is over it or it scrolls, stopping short of the corner the reader drags. The text is the input's body text. Hover lifts the well to the raised surface, focus draws the field focus border, and the error flag draws the danger border, which stays while focused, puts the warning icon at the top end with the text stopping short of it, and marks the control invalid. A read-only text area sits flat on the page with a faint edge, has no grip and cannot be resized; its text can be selected and copied. A disabled text area grays the well, cannot be typed in and cannot be resized. All of these are the input's own looks, so a change to the input reaches the text area.

Firefox cannot hide its own resize handle, so there the grip is not drawn and Firefox's handle shows in the corner instead.

Accessibility


What it does for you

  • It is the browser's own textarea, so typing, pasting, undo, selection and line breaks behave as everywhere else.
  • The error flag sets aria-invalid.
  • The grip is decorative and hidden from assistive technology; the browser's own handle does the resizing.

What you must do

  • Give it a label: the field component around it gives one, or the label component with the for attribute. In development, a text area with no name logs a warning in the console.
  • Let the field link the message that explains an error.
  • Never use placeholder text as a label: it disappears when typing starts.

How to test

  • Tab to it: the focus border shows, in both themes and in a forced-color mode. Type, paste, undo and break lines as in any text box.
  • With a screen reader, it is read as a text box by its label, and an error as invalid with its message.
  • With text at 200% and the page 320 pixels wide, the box follows the width the layout gives it and long text scrolls inside it.

Keyboard

Text area keys
KeyWhat it does
Tab
Moves focus to the text area, and on from it.
Enter
Starts a new line.

Source


The files the text area is made of. Its folder on GitHub (opens in a new tab) holds them with its wrapper and its document.

Stylesheet
text-area.css
/* smbk-text-area — Text area. Figma "TextArea" 4800:64744.
 * Built on the input: the block always sits on an smbk-input well and the
 * textarea is the input's control, so the well's chrome, its text style and
 * its hover, focus, error, read-only and disabled looks are the input's own
 * and follow any change to it. Figma binds the same fills, borders, shadows
 * and text in every state. This stylesheet adds only what several lines need:
 * the well grows with the control instead of keeping the control height, the
 * error icon sits at the top end, and a grip at the corner shows the box can
 * be made taller. */

.smbk-input.smbk-text-area {
  position: relative;
  align-items: stretch;
  height: auto;
  padding: 0;
}

/* The padding is on the control, so the browser's own resize handle sits in
   the well's corner. */
.smbk-text-area__control {
  box-sizing: border-box;
  display: block;
  width: 100%;
  min-height: calc(1lh + 2 * var(--smbk-space-inset-lg));
  margin: 0;
  padding: var(--smbk-space-inset-lg);
  resize: vertical;
  /* The system's scrollbar: thin, in the subtle border color, on a clear track. */
  scrollbar-width: thin;
  scrollbar-color: var(--smbk-color-border-subtle) transparent;
}

.smbk-text-area__control:disabled,
.smbk-text-area__control[readonly] {
  resize: none;
}

/* In error the text stops short of the icon at the top end, which stays on the first line's middle
   while the text scrolls under it. */
.smbk-input--error .smbk-text-area__control {
  padding-inline-end: calc(var(--smbk-space-inset-lg) + var(--smbk-size-icon-md));
}

.smbk-text-area .smbk-input__error-icon {
  position: absolute;
  inset-block-start: var(--smbk-space-inset-lg);
  inset-inline-end: var(--smbk-space-inset-lg);
  height: calc(var(--smbk-typography-body-md-font-size) * var(--smbk-typography-body-md-line-height));
  pointer-events: none;
}

/* Figma's grip, the notches icon, a hairline step in from the corner. It only
   draws: the browser's resize handle underneath takes the pointer. Where the
   browser cannot hide its own handle (Firefox), its own handle shows instead. */
.smbk-text-area__grip {
  display: none;
  position: absolute;
  inset-block-end: var(--smbk-space-inset-xs);
  inset-inline-end: var(--smbk-space-inset-xs);
  color: var(--smbk-color-text-subtlest);
  font-size: var(--smbk-size-icon-xs);
  pointer-events: none;
}

@supports selector(::-webkit-resizer) {
  .smbk-text-area__control::-webkit-resizer {
    background: transparent;
  }

  .smbk-text-area__grip {
    display: block;
  }
}

.smbk-text-area:has(.smbk-input__control:disabled) .smbk-text-area__grip {
  color: var(--smbk-color-text-disabled);
}

/* The scrollbar drawn over the control (scrollbar.ts) stops short of the corner, where the grip and the browser's
   resize handle are. */
.smbk-text-area > .smbk-scrollbar .smbk-scrollbar__track--y {
  inset-block-end: calc(var(--smbk-space-inset-xs) + var(--smbk-size-icon-xs));
}

/* A read-only text area cannot be made taller, so it has no grip, as Figma draws it. */
.smbk-text-area:has(.smbk-input__control[readonly]) .smbk-text-area__grip {
  display: none;
}
Tokens it reads
Text area tokens
Token and CSSValuePreviewFoundation
space.inset.lg--smbk-space-inset-lgcomfortable: 12pxcompact: 8pxchanges with densitySpacing
color.border.subtle--smbk-color-border-subtlelight: #c4cdd8dark: #2d3237changes with themeColor
size.icon.md--smbk-size-icon-md20pxSize
typography.body-md--smbk-typography-body-md-font-family--smbk-typography-body-md-font-size--smbk-typography-body-md-font-weight--smbk-typography-body-md-line-height--smbk-typography-body-md-letter-spacing--smbk-typography-body-md-text-transformfontFamily: Geist, Geist Fallback, system-ui, sans-seriffontSize: 16pxfontWeight: 400lineHeight: 1.5letterSpacing: 0px

The quick brown fox

Typography
space.inset.xs--smbk-space-inset-xs4pxSpacing
color.text.subtlest--smbk-color-text-subtlestlight: #606a75dark: #7c8692changes with themeColor
size.icon.xs--smbk-size-icon-xs12pxSize
color.text.disabled--smbk-color-text-disabledlight: #7c8692dark: #606a75changes with themeColor
Manifest
text-area.manifest.json
{
  "name": "text-area",
  "block": "smbk-text-area",
  "summary": "A text box for several lines: the input well grown tall, with a grip at its corner to make it taller.",
  "adapt": "css",
  "axes": {},
  "flags": {
    "error": {
      "description": "The value is invalid. Draws the danger border, kept while focused, and the error icon at the top end; the control also carries aria-invalid."
    }
  },
  "parts": [
    "control",
    "grip"
  ],
  "figmaNodeId": "4800:64744"
}