{
  "tag": "ed-select",
  "kind": "component",
  "summary": "Lets the user pick one value, or several, from a dropdown list of predefined options in a form or filter.",
  "status": "experimental",
  "level": "atom",
  "since": "1.0",
  "docs": "https://test-apps.eurodata.de/a/eurodata-ui/docs/components/select/",
  "usage": "https://test-apps.eurodata.de/a/eurodata-ui/docs/components/select/usage/",
  "playwright": "getByTestId('…').getByRole('combobox')",
  "dependencies": [
    "ed-icon",
    "ed-popup",
    "ed-badge",
    "ed-option"
  ],
  "use": [
    "Choosing one option — or, in multiple mode, several — from a fixed set of predefined, mutually understood choices",
    "Form fields, filters, and settings pickers where showing every option inline would clutter the layout",
    "A field with about 5 to 15 predefined options where no typing search is needed"
  ],
  "notFor": [
    {
      "when": "2 to 4 fixed, short, stable choices",
      "instead": "[Radio Group](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/radio-group) (its button appearance for compact rows)"
    },
    {
      "when": "Users must see and compare all options at a glance before choosing",
      "instead": "[Radio Group](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/radio-group)"
    },
    {
      "when": "Long lists (roughly 15+) or any list users would filter by typing",
      "instead": "[Combobox](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/combobox)"
    },
    {
      "when": "Toggling several independent on/off settings that are not mutually exclusive",
      "instead": "[Checkbox Group](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/checkbox-group)"
    },
    {
      "when": "Triggering actions or commands rather than picking a value",
      "instead": "[Dropdown](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/dropdown)"
    }
  ],
  "rules": [
    {
      "id": "select/combobox-for-long-lists",
      "rule": "Use a [Combobox](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/combobox) instead for lists of roughly 15 or more options, or any list users would want to narrow by typing.",
      "why": "This select shows a fixed option list with no search field — typing only jumps to a matching option, it does not filter the list. Forcing users to scroll a long, unfiltered list is one of the highest interaction costs you can impose.",
      "check": "warning"
    },
    {
      "id": "select/read-value-after-options",
      "rule": "Read `value` after the options render: a value set before its options are in the DOM reads `null` until they are — an empty array with `multiple`."
    },
    {
      "id": "select/placeholder-or-default",
      "rule": "Show a \"Please select…\" style placeholder when there is no meaningful default and a choice is required, and pre-select a genuine default instead when one value is correct for most users. Never leave a required select empty with no placeholder and no default, and never arbitrarily pre-select the first option as though the user had chosen it.",
      "why": "An empty required select with neither gives users no signal that a choice is needed."
    },
    {
      "id": "select/sections",
      "rule": "Split options with natural categories into labeled sections separated by dividers so they are easier to scan — but never rely on the small section headings alone to carry meaning.",
      "why": "Most assistive technology does not announce them.",
      "check": "error"
    },
    {
      "id": "select/clear-button",
      "rule": "Offer the clear button when an empty selection is a valid, expected state — especially in multiple mode.",
      "check": "warning"
    },
    {
      "id": "select/explain-high-stakes",
      "rule": "Add a short preview or description of what a value means for high-stakes choices such as tax category, account code, or payroll period."
    },
    {
      "id": "select/disabled-options",
      "rule": "Disable an individual option only when it is temporarily unavailable but still worth showing."
    },
    {
      "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": "name",
        "property": "name",
        "type": "null | string",
        "default": "''",
        "description": "The name of the select, submitted as a name/value pair with form data."
      },
      {
        "name": "value",
        "property": "value",
        "description": "The select's value. This will be a string for single select or an array for multi-select."
      },
      {
        "name": "density",
        "property": "density",
        "type": "'compact' | 'default' | 'spacious'",
        "default": "'default'",
        "description": "Controls the component's spacing density without affecting font-size."
      },
      {
        "name": "placeholder",
        "property": "placeholder",
        "type": "string",
        "default": "''",
        "description": "Placeholder text to show as a hint when the select is empty."
      },
      {
        "name": "multiple",
        "property": "multiple",
        "type": "boolean",
        "default": "false",
        "description": "Allows more than one option to be selected."
      },
      {
        "name": "max-options-visible",
        "property": "maxOptionsVisible",
        "type": "number",
        "default": "3",
        "description": "The maximum number of selected options to show when `multiple` is true. After the maximum, \"+n\" will be shown to\nindicate the number of additional items that are selected. Set to 0 to remove the limit."
      },
      {
        "name": "readonly",
        "property": "readonly",
        "type": "boolean",
        "default": "false",
        "description": "Shows a value the user cannot change. Unlike `disabled`, the control stays focusable and its value is still\nsubmitted with the form; the listbox does not open, and nothing empties the value."
      },
      {
        "name": "with-clear",
        "property": "withClear",
        "type": "boolean",
        "default": "false",
        "description": "Adds a clear button when the select is not empty."
      },
      {
        "name": "open",
        "property": "open",
        "type": "boolean",
        "default": "false",
        "description": "Indicates whether or not the select is open. You can toggle this attribute to show and hide the menu, or you can\nuse the `show()` and `hide()` methods and this attribute will reflect the select's open state."
      },
      {
        "name": "pill",
        "property": "pill",
        "type": "boolean",
        "default": "false",
        "description": "Draws a pill-style select with rounded edges."
      },
      {
        "name": "label",
        "property": "label",
        "type": "string",
        "default": "''",
        "description": "The select'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 select's accessible name for when no visible label is set. Mirrored onto the internal\ndisplay input, where the combobox role lives — an aria-label left on the host alone would\nsit on a role-less element and be ignored by assistive tech. A visible label wins when both\nare present (aria-labelledby precedes aria-label in accessible-name computation)."
      },
      {
        "name": "placement",
        "property": "placement",
        "type": "'top' | 'bottom'",
        "default": "'bottom'",
        "description": "The preferred placement of the select's menu. Note that the actual placement may vary as needed to keep the listbox\ninside of the viewport."
      },
      {
        "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": "required",
        "property": "required",
        "type": "boolean",
        "default": "false",
        "description": "The select's required attribute."
      },
      {
        "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 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 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": "validationTarget",
        "type": "undefined | HTMLElement",
        "description": "Where to anchor native constraint validation"
      },
      {
        "name": "getTag",
        "type": "(option: EdOption, index: number) => TemplateResult | string | HTMLElement",
        "description": "A function that customizes the tags to be rendered when multiple=true. The first argument is the option, the second\nis the current tag's index. Return a Lit `TemplateResult`, an `HTMLElement`, or a string (strings render as text and\nare auto-escaped — to render rich content, return a `TemplateResult` or build an `HTMLElement` yourself). For React,\nwrap JSX with the `jsxToHtml()` helper. For non-Lit vanilla JS, use the re-exported `html` tag."
      },
      {
        "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."
      }
    ],
    "methods": [
      {
        "name": "show",
        "description": "Shows the listbox."
      },
      {
        "name": "hide",
        "description": "Hides the listbox."
      },
      {
        "name": "focus",
        "parameters": [
          {
            "name": "options",
            "type": "FocusOptions",
            "optional": true
          }
        ],
        "description": "Sets focus on the control."
      },
      {
        "name": "blur",
        "description": "Removes focus from the control."
      },
      {
        "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."
      }
    ],
    "events": [
      {
        "name": "input",
        "react": "onInput",
        "type": "InputEvent",
        "description": "Emitted when the control receives input."
      },
      {
        "name": "change",
        "react": "onChange",
        "type": "Event",
        "description": "Emitted when the control's value changes."
      },
      {
        "name": "focus",
        "react": "onFocus",
        "description": "Emitted when the control gains focus."
      },
      {
        "name": "blur",
        "react": "onBlur",
        "description": "Emitted when the control loses focus."
      },
      {
        "name": "ed-clear",
        "react": "onEdClear",
        "description": "Emitted when the control's value is cleared."
      },
      {
        "name": "ed-show",
        "react": "onEdShow",
        "description": "Emitted when the select's menu opens. Cancelable; calling `preventDefault()` keeps it closed."
      },
      {
        "name": "ed-after-show",
        "react": "onEdAfterShow",
        "description": "Emitted after the select's menu opens and all animations are complete."
      },
      {
        "name": "ed-hide",
        "react": "onEdHide",
        "description": "Emitted when the select's menu closes. Cancelable; calling `preventDefault()` keeps it open."
      },
      {
        "name": "ed-after-hide",
        "react": "onEdAfterHide",
        "description": "Emitted after the select's menu closes and all animations are complete."
      },
      {
        "name": "ed-invalid",
        "react": "onEdInvalid",
        "description": "Emitted when the form control has been checked for validity and its constraints aren't satisfied."
      }
    ],
    "slots": [
      {
        "name": "",
        "description": "The listbox options. Must be `<ed-option>` elements. You can use `<ed-divider>` to group items visually."
      },
      {
        "name": "label",
        "description": "The input's label. Alternatively, you can use the `label` attribute."
      },
      {
        "name": "start",
        "description": "An element, such as `<ed-icon>`, placed at the start of the combobox."
      },
      {
        "name": "end",
        "description": "An element, such as `<ed-icon>`, placed at the end of the combobox."
      },
      {
        "name": "clear-icon",
        "description": "An icon to use in lieu of the default clear icon."
      },
      {
        "name": "expand-icon",
        "description": "The icon to show when the control is expanded and collapsed. Rotates on open and close."
      },
      {
        "name": "hint",
        "description": "Text that describes how to use the input. Alternatively, you can use the `hint` attribute."
      }
    ],
    "cssProperties": [
      {
        "name": "--ed-show-duration",
        "default": "var(--ed-transition-fast)",
        "description": "The duration of the show animation."
      },
      {
        "name": "--ed-hide-duration",
        "default": "var(--ed-transition-fast)",
        "description": "The duration of the hide animation."
      },
      {
        "name": "--ed-select-tag-max-size",
        "default": "10ch",
        "description": "When using `multiple`, the max size of tags before their content is truncated."
      },
      {
        "name": "--ed-select-width",
        "default": "100%",
        "description": "The width of the control. Defaults to filling its container."
      }
    ],
    "parts": [
      {
        "name": "form-control",
        "description": "The form control that wraps the label, input, and hint."
      },
      {
        "name": "form-control-label",
        "description": "The label's wrapper."
      },
      {
        "name": "form-control-input",
        "description": "The select's wrapper."
      },
      {
        "name": "message",
        "description": "The state message: an error, a warning, or the AI note."
      },
      {
        "name": "hint",
        "description": "The hint's wrapper."
      },
      {
        "name": "base",
        "description": "The bordered field box. An alias for `combobox`, so a selector written against another form control reaches the same element here."
      },
      {
        "name": "combobox",
        "description": "The container the wraps the start, end, value, clear icon, and expand button."
      },
      {
        "name": "start",
        "description": "The container that wraps the `start` slot."
      },
      {
        "name": "end",
        "description": "The container that wraps the `end` slot."
      },
      {
        "name": "display-input",
        "description": "The element that displays the selected option's label, an `<input>` element."
      },
      {
        "name": "panel",
        "description": "The floating surface holding the options. Carries the frame, background and shadow."
      },
      {
        "name": "tags",
        "description": "The container that houses option tags when `multiselect` is used."
      },
      {
        "name": "tag",
        "description": "The individual tags that represent each multiselect option."
      },
      {
        "name": "tag__base",
        "description": "The tag's exported `base` part, the badge's surface."
      },
      {
        "name": "tag__remove-icon",
        "description": "The tag's exported `remove-icon` part, the `<button>` that removes the option."
      },
      {
        "name": "clear-button",
        "description": "The clear button."
      },
      {
        "name": "expand-icon",
        "description": "The container that wraps the expand icon."
      }
    ],
    "states": [
      {
        "name": "blank",
        "description": "The select 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/select/select.js';",
  "react": {
    "component": "EdSelect",
    "import": "import EdSelect from '@eurodata/eurodata-ui/dist/react/select/index.js';"
  }
}
