{
  "tag": "ed-textarea",
  "kind": "component",
  "summary": "Textareas collect data from the user and allow multiple lines of text.",
  "status": "experimental",
  "level": "atom",
  "since": "1.0",
  "docs": "https://test-apps.eurodata.de/a/eurodata-ui/docs/components/textarea/",
  "usage": "https://test-apps.eurodata.de/a/eurodata-ui/docs/components/textarea/usage/",
  "playwright": "getByTestId('…').getByRole('textbox')",
  "dependencies": [
    "ed-icon"
  ],
  "use": [
    "Genuinely multi-line, free-form text where the response may run to a sentence, a paragraph, or more — comments, descriptions, notes, message composition, and feedback",
    "Answers whose length the user cannot predict, where they need room to see and edit several lines at once",
    "A message or description field with a visible character count when the text has a length limit"
  ],
  "notFor": [
    {
      "when": "Short, single-line, bounded values such as a name, email, ZIP code, or reference number",
      "instead": "a single-line [Input](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/input)"
    },
    {
      "when": "On its own, text the user needs to format — bold, lists, headings, links, or other formatting",
      "instead": "a rich-text editor, or capture markdown and render it with the [Markdown](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/markdown) component"
    }
  ],
  "rules": [
    {
      "id": "textarea/instructions-in-hint",
      "rule": "Put instructions the user still needs after they start typing in the hint — never rely on placeholder text to carry them."
    },
    {
      "id": "textarea/starting-height",
      "rule": "Set the starting height to the length you realistically expect — a few lines for a short comment, more for long-form content.",
      "why": "Users are not forced to resize before they begin."
    },
    {
      "id": "textarea/auto-grow",
      "rule": "Let the field expand automatically as the user types when the content length is unpredictable.",
      "why": "Long entries stay fully visible without scrolling."
    },
    {
      "id": "textarea/character-count",
      "rule": "Enable the built-in character count when there is a genuine limit, so users see how much room remains before they reach it.",
      "check": "warning"
    },
    {
      "id": "textarea/advisory-limit",
      "rule": "Decide whether the limit is enforced or advisory, and never silently cut off or discard text the user has already typed or pasted when they exceed it. Leave `maxlength` off where the user has to be told rather than cut short — the count plus a validation message warns them and lets them shorten the text themselves.",
      "why": "With `maxlength` the browser stops further typing and truncates a paste without saying so, and the count reads as characters remaining.",
      "check": "warning"
    },
    {
      "id": "textarea/table-edit-mode",
      "rule": "Never make every cell of a data table a permanently editable textarea — require an explicit action to enter edit mode.",
      "check": "warning"
    },
    {
      "id": "form-controls/visible-label",
      "rule": "In a form, give every control a persistent, visible label — short, descriptive and in plain language — and never placeholder text in its place. Outside a form the container decides whether the label shows; where it does not, `aria-label` gives the control its name.",
      "why": "Placeholder text disappears the moment the user types, leaving no reminder of what the field expected.",
      "check": "error"
    },
    {
      "id": "form-controls/required",
      "rule": "Set `required` on a mandatory control and explain the required-marking convention once per form. Never add your own required indicator — the label picks it up."
    },
    {
      "id": "form-controls/error-timing",
      "rule": "Never show a validation error before the user has interacted with the control — not on page load, not on focus alone, not while they are still typing. Don't add your own timing: the control shows its errors after the user has left it or changed its value, and on submit.",
      "check": "error"
    },
    {
      "id": "form-controls/message-never-silenced",
      "rule": "Keep a message on every error. Write your own where the built-in wording does not fit — it replaces the built-in one — but never set `error` to an empty string or hide the message part: the error styling alone says that something is wrong, not what.",
      "check": "error"
    },
    {
      "id": "form-controls/readonly-not-disabled",
      "rule": "Use `readonly` for a value the user can never change — a calculated total, an assigned id — and `disabled` only while it could become editable under some condition.",
      "why": "Disabled implies the value could be unlocked, and a disabled control submits nothing; a read-only one submits its value."
    },
    {
      "id": "form-controls/min-width",
      "rule": "Keep a field at least 8.75rem (140px) wide, even for short values such as postal codes — and comfortably wider for prose.",
      "why": "The value, the label and any icons stay legible.",
      "check": "error",
      "covered": true
    },
    {
      "id": "form-controls/default-density",
      "rule": "Keep `density` at its default, and the same for every control in one row or form. Choose `compact` or `spacious` only where the user asks for it or the space leaves no other way — a form with many fields is no reason — and then for the whole layout, never to fine-tune spacing case by case. Where a container decides the density of the controls inside it, its rules say so.",
      "why": "The default is the intended spacing for almost every screen.",
      "check": "warning"
    },
    {
      "id": "form-controls/ai-suggested",
      "rule": "Set `ai` on a control whose value the system pre-filled, so users can tell it apart from their own entries; the state clears once they touch it."
    }
  ],
  "api": {
    "attributes": [
      {
        "name": "title",
        "property": "title",
        "type": "string",
        "default": "''"
      },
      {
        "name": "name",
        "property": "name",
        "type": "null | string",
        "default": "null",
        "description": "The name of the textarea, submitted as a name/value pair with form data."
      },
      {
        "name": "value",
        "property": "defaultValue",
        "type": "string",
        "description": "The default value of the form control. Primarily used for resetting the form control."
      },
      {
        "name": "density",
        "property": "density",
        "type": "'compact' | 'default' | 'spacious'",
        "default": "'default'",
        "description": "Controls the component's spacing density without affecting font-size."
      },
      {
        "name": "label",
        "property": "label",
        "type": "string",
        "default": "''",
        "description": "The textarea's label. If you need to display HTML, use the `label` slot instead."
      },
      {
        "name": "aria-label",
        "property": "ariaLabel",
        "type": "null | string",
        "default": "null",
        "description": "The textarea's accessible name for when no visible label is set. Mirrored onto the internal\ntextarea, where the textbox role lives — an aria-label left on the host alone would sit on\na role-less element and be ignored by assistive tech."
      },
      {
        "name": "placeholder",
        "property": "placeholder",
        "type": "string",
        "default": "''",
        "description": "Placeholder text to show as a hint when the input is empty."
      },
      {
        "name": "rows",
        "property": "rows",
        "type": "number",
        "default": "4",
        "description": "The number of rows to display by default."
      },
      {
        "name": "resize",
        "property": "resize",
        "type": "'auto' | 'both' | 'horizontal' | 'vertical' | 'none'",
        "default": "'vertical'",
        "description": "Controls how the textarea can be resized."
      },
      {
        "name": "readonly",
        "property": "readonly",
        "type": "boolean",
        "default": "false",
        "description": "Makes the textarea readonly."
      },
      {
        "name": "required",
        "property": "required",
        "type": "boolean",
        "default": "false",
        "description": "Makes the textarea a required field."
      },
      {
        "name": "minlength",
        "property": "minlength",
        "type": "number",
        "description": "The minimum length of input that will be considered valid."
      },
      {
        "name": "maxlength",
        "property": "maxlength",
        "type": "number",
        "description": "The maximum length of input that will be considered valid."
      },
      {
        "name": "autocapitalize",
        "property": "autocapitalize",
        "type": "'none' | 'off' | 'on' | 'sentences' | 'words' | 'characters'",
        "description": "Controls whether and how text input is automatically capitalized as it is entered by the user."
      },
      {
        "name": "autocorrect",
        "property": "autocorrect",
        "type": "boolean",
        "description": "Indicates whether the browser's autocorrect feature is on or off. When set as an attribute, use `\"off\"` or `\"on\"`.\nWhen set as a property, use `true` or `false`."
      },
      {
        "name": "autocomplete",
        "property": "autocomplete",
        "type": "string",
        "description": "Specifies what permission the browser has to provide assistance in filling out form field values. Refer to\n[this page on MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete) for available values."
      },
      {
        "name": "autofocus",
        "property": "autofocus",
        "type": "boolean",
        "description": "Indicates that the input should receive focus on page load."
      },
      {
        "name": "enterkeyhint",
        "property": "enterkeyhint",
        "type": "'next' | 'previous' | 'search' | 'send' | 'done' | 'enter' | 'go'",
        "description": "Used to customize the label or icon of the Enter key on virtual keyboards."
      },
      {
        "name": "spellcheck",
        "property": "spellcheck",
        "type": "boolean",
        "default": "true",
        "description": "Enables spell checking on the textarea."
      },
      {
        "name": "inputmode",
        "property": "inputmode",
        "type": "'search' | 'text' | 'numeric' | 'none' | 'email' | 'tel' | 'url' | 'decimal'",
        "description": "Tells the browser what type of data will be entered by the user, allowing it to display the appropriate virtual\nkeyboard on supportive devices."
      },
      {
        "name": "with-label",
        "property": "withLabel",
        "type": "boolean",
        "default": "false",
        "description": "Only required for SSR. Set to `true` if you're slotting in a `label` element so the server-rendered markup includes the label before the component hydrates on the client."
      },
      {
        "name": "with-hint",
        "property": "withHint",
        "type": "boolean",
        "default": "false",
        "description": "Only required for SSR. Set to `true` if you're slotting in a `hint` element so the server-rendered markup includes the hint before the component hydrates on the client."
      },
      {
        "name": "with-count",
        "property": "withCount",
        "type": "boolean",
        "default": "false",
        "description": "Shows a character count below the textarea. When `maxlength` is set, shows remaining characters instead."
      },
      {
        "name": "error",
        "property": "error",
        "type": "null | string",
        "default": "null",
        "description": "Draws an error-style input with danger colored border and icon. Set to an empty string (or use the bare attribute `<ed-input error>`) to render error styling without a visible message; submission is still blocked with a localized fallback validation message. Set to a non-empty string to additionally display that message in the message area, above the hint, and use it as the validation message. Set to `null` (the default) or `undefined`, or remove the attribute, to clear the error."
      },
      {
        "name": "warning",
        "property": "warning",
        "type": "null | string",
        "default": "null",
        "description": "Draws a warning-style input with warning colored border and icon. Set to an empty string (or use the bare attribute `<ed-input warning>`) to render warning styling without a visible message. Set to a non-empty string to additionally display that message in the message area, above the hint. Warnings do not block form submission. Set to `null` (the default) or `undefined`, or remove the attribute, to clear the warning."
      },
      {
        "name": "ai",
        "property": "ai",
        "type": "boolean",
        "default": "false",
        "description": "Draws an ai-style input with AI colored border and icon. Suppressed visually once\n`hasInteracted` flips, but the property and attribute are preserved so the styling\nreturns after `formResetCallback` clears `hasInteracted`."
      },
      {
        "name": "hint",
        "property": "hint",
        "type": "string",
        "default": "''",
        "description": "The form control's hint text. If you need to display HTML, use the `hint` slot instead."
      },
      {
        "name": "disabled",
        "property": "disabled",
        "type": "boolean",
        "description": "Disables the form control. HTML treats a control as disabled when either its own `disabled` is\nset or an ancestor `<fieldset>` is disabled, so reading this reports the combined state while\nwriting it sets only this element's own. Keeping the two apart is what lets a fieldset be\nre-enabled without clearing a disabled state the consumer set in the meantime."
      },
      {
        "name": "dir",
        "property": "dir",
        "type": "string"
      },
      {
        "name": "lang",
        "property": "lang",
        "type": "string"
      }
    ],
    "properties": [
      {
        "name": "value",
        "type": "string",
        "description": "The current value of the textarea, submitted as a name/value pair with form data. Empty is `''`,\nas on a native textarea — never `null`."
      },
      {
        "name": "form",
        "type": "HTMLFormElement | null",
        "description": "By default, form controls are associated with the nearest containing `<form>` element. This attribute allows you\nto place the form control outside of a form and associate it with the form that has this `id`. The form must be in\nthe same document or shadow root for this to work."
      },
      {
        "name": "validationTarget",
        "type": "undefined | HTMLElement",
        "description": "Override this to change where constraint validation popups are anchored."
      }
    ],
    "methods": [
      {
        "name": "focus",
        "parameters": [
          {
            "name": "options",
            "type": "FocusOptions",
            "optional": true
          }
        ],
        "description": "Sets focus on the textarea."
      },
      {
        "name": "blur",
        "description": "Removes focus from the textarea."
      },
      {
        "name": "select",
        "description": "Selects all the text in the textarea."
      },
      {
        "name": "scrollPosition",
        "parameters": [
          {
            "name": "position",
            "type": "{ top?: number; left?: number }",
            "optional": true
          }
        ],
        "returns": "{ top: number; left: number } | undefined",
        "description": "Gets or sets the textarea's scroll position."
      },
      {
        "name": "setSelectionRange",
        "parameters": [
          {
            "name": "selectionStart",
            "type": "number"
          },
          {
            "name": "selectionEnd",
            "type": "number"
          },
          {
            "name": "selectionDirection",
            "type": "'forward' | 'backward' | 'none'"
          }
        ],
        "description": "Sets the start and end positions of the text selection (0-based)."
      },
      {
        "name": "setRangeText",
        "parameters": [
          {
            "name": "replacement",
            "type": "string"
          },
          {
            "name": "start",
            "type": "number",
            "optional": true
          },
          {
            "name": "end",
            "type": "number",
            "optional": true
          },
          {
            "name": "selectMode",
            "type": "'select' | 'start' | 'end' | 'preserve'"
          }
        ],
        "description": "Replaces a range of text with a new string."
      },
      {
        "name": "setCustomValidity",
        "parameters": [
          {
            "name": "message",
            "type": "string"
          }
        ],
        "description": "Do not use this when creating a \"Validator\". This is intended for end users of components.\nWe track manually defined custom errors so we don't clear them on accident in our validators."
      },
      {
        "name": "resetValidity",
        "description": "Reset validity is a way of removing manual custom errors and native validation."
      },
      {
        "name": "getPropertyDescriptor",
        "static": true,
        "parameters": [
          {
            "name": "name",
            "type": "PropertyKey"
          },
          {
            "name": "key",
            "type": "string | symbol"
          },
          {
            "name": "options",
            "type": "PropertyDeclaration"
          }
        ],
        "returns": "PropertyDescriptor | undefined",
        "description": "Wraps the accessor of reflected properties so they always hold a valid value, as a native\nreflected IDL attribute does (`button.type = undefined` reads `submit`):\n\n- A property that declares `useDefault` takes the first value set on an element for its\n  default. That value is its field initializer's: the constructor has finished before markup,\n  a framework or any other code can set anything. Every later `null` or `undefined` means what\n  a dropped prop means on a native element — the attribute is removed: with the attribute\n  there, it is removed and Lit's `useDefault` restores the default without writing it; without\n  one, the property is set to the default. A value set and cleared again before the element\n  updates still writes the default once, from the pending reflection.\n- A Boolean is coerced with `Boolean()`, so `undefined` is `false`.\n\nLit's `useDefault` keeps the initial default out of the DOM. Setting the default explicitly\nwrites it, as `button.type = 'submit'` writes `type`."
      }
    ],
    "events": [
      {
        "name": "blur",
        "react": "onBlur",
        "description": "Emitted when the control loses focus."
      },
      {
        "name": "change",
        "react": "onChange",
        "description": "Emitted when an alteration to the control's value is committed by the user."
      },
      {
        "name": "focus",
        "react": "onFocus",
        "description": "Emitted when the control gains focus."
      },
      {
        "name": "input",
        "react": "onInput",
        "description": "Emitted when the control receives input."
      },
      {
        "name": "ed-invalid",
        "react": "onEdInvalid",
        "description": "Emitted when the form control has been checked for validity and its constraints aren't satisfied."
      }
    ],
    "slots": [
      {
        "name": "label",
        "description": "The textarea's label. Alternatively, you can use the `label` attribute."
      },
      {
        "name": "hint",
        "description": "Text that describes how to use the input. Alternatively, you can use the `hint` attribute."
      }
    ],
    "cssProperties": [],
    "parts": [
      {
        "name": "label",
        "description": "The label"
      },
      {
        "name": "message",
        "description": "The state message: an error, a warning, or the AI note."
      },
      {
        "name": "footer",
        "description": "The row below the control that holds the hint and the character count."
      },
      {
        "name": "hint",
        "description": "The hint's wrapper."
      },
      {
        "name": "base",
        "description": "The wrapper around the `<textarea>` control."
      },
      {
        "name": "textarea",
        "description": "The internal `<textarea>` control."
      },
      {
        "name": "count",
        "description": "The character count element, rendered when the `with-count` attribute is present."
      }
    ],
    "states": [
      {
        "name": "blank",
        "description": "The textarea is empty."
      },
      {
        "name": "disabled",
        "description": "The control is disabled, by its own attribute or by an ancestor fieldset."
      },
      {
        "name": "required",
        "description": "The control is required."
      },
      {
        "name": "optional",
        "description": "The control is not required."
      },
      {
        "name": "invalid",
        "description": "The value fails constraint validation, whether or not the user has touched the control yet."
      },
      {
        "name": "valid",
        "description": "The value passes constraint validation."
      },
      {
        "name": "user-invalid",
        "description": "Invalid, and the user has interacted with the control. This is the one to style for an error: it behaves like the platform's `:user-invalid`, so an untouched field is not marked wrong before the user has had a chance to fill it in."
      },
      {
        "name": "user-valid",
        "description": "Valid, and the user has interacted with the control."
      },
      {
        "name": "dirty",
        "description": "The user has interacted with the control."
      },
      {
        "name": "error",
        "description": "The `error` property is set, or the control is `user-invalid`."
      },
      {
        "name": "warning",
        "description": "The `warning` property is set."
      },
      {
        "name": "ai",
        "description": "The `ai` property is set and the user has not interacted with the control yet."
      }
    ]
  },
  "import": "import '@eurodata/eurodata-ui/dist/components/textarea/textarea.js';",
  "react": {
    "component": "EdTextarea",
    "import": "import EdTextarea from '@eurodata/eurodata-ui/dist/react/textarea/index.js';"
  }
}
