# Select

Ein Select ermöglicht es Usern, eine einzelne Option aus einer vordefinierten Liste auszuwählen.

## Overview

# Playground

  Verwendung mit dynamisch erstellten Options

    Wenn die `Select`-Komponente ohne ein `key` Prop und mit dynamisch
    erstellten `Options` betrieben wird, kann dies dazu führen, dass die
    Komponente einfriert oder nicht mehr reagiert. Verwende ein `key` Prop auf
    der `Select`-Komponente, welches sich mit den dynamischen `Options` ändert.

Verwende `<Select />`, um einen Select darzustellen. Ein zugehöriges `<Label />`
sowie die gewünschte Anzahl an `<Option />`-Elementen werden innerhalb der
Component eingefügt.

```tsx
import {
  Label,
  Option,
  Select,
} from "@mittwald/flow-react-components";

<Select>
  <Label>App</Label>
  <Option>WordPress</Option>
  <Option>TYPO3</Option>
  <Option>Contao</Option>
  <Option>Drupal</Option>
  <Option>Joomla!</Option>
  <Option>Matomo</Option>
</Select>
```

---

# Default-Wert

Mit `defaultSelectedKey` kann eine Default-Option angegeben werden, die dem User
standardmäßig zuerst angezeigt wird.

```tsx
import {
  Label,
  Option,
  Select,
} from "@mittwald/flow-react-components";

<Select defaultSelectedKey="wordpress" isRequired>
  <Label>App</Label>
  <Option value="wordpress">WordPress</Option>
  <Option value="typo3">TYPO3</Option>
</Select>
```

---

# Kombiniere mit ...

## FieldDescription

Um wichtige Hinweise zu den Auswahloptionen des Select bereitzustellen, kann
unterhalb eine `<FieldDescription />` eingebaut werden.

```tsx
import {
  FieldDescription,
  Label,
  Option,
  Select,
} from "@mittwald/flow-react-components";

<Select>
  <Label>App</Label>
  <Option>WordPress</Option>
  <Option>TYPO3</Option>
  <Option>Contao</Option>
  <Option>Drupal</Option>
  <Option>Joomla!</Option>
  <Option>Matomo</Option>
  <FieldDescription>Weitere Informationen</FieldDescription>
</Select>
```

## Align

Benutze die [Align](/04-components/structure/align/overview) Component, um
beispielsweise einen Button neben dem Select zu platzieren.

```tsx
import {
  Align,
  Button,
  Select,
  Label,
  Option,
} from "@mittwald/flow-react-components";

<Align>
  <Select>
    <Label>App</Label>
    <Option>WordPress</Option>
    <Option>TYPO3</Option>
    <Option>Contao</Option>
    <Option>Drupal</Option>
    <Option>Joomla!</Option>
    <Option>Matomo</Option>
  </Select>
  <Button>Hinzufügen</Button>
</Align>
```

## ContextualHelp

Benutze das [ContextualHelp](/04-components/overlays/contextual-help/overview),
um weitere Informationen bereitstellen zu können.

```tsx
import {
  Button,
  ContextualHelp,
  ContextualHelpTrigger,
  Heading,
  Label,
  Option,
  Select,
  Text,
} from "@mittwald/flow-react-components";

<Select>
  <Label>
    App
    <ContextualHelpTrigger>
      <Button />
      <ContextualHelp>
        <Heading>Weitere Informationen</Heading>
        <Text>
          Hier gibt es weitere Informationen, die zu lang
          für die FieldDescription sind.
        </Text>
      </ContextualHelp>
    </ContextualHelpTrigger>
  </Label>
  <Option>WordPress</Option>
  <Option>TYPO3</Option>
  <Option>Contao</Option>
  <Option>Drupal</Option>
  <Option>Joomla!</Option>
  <Option>Matomo</Option>
</Select>
```

## React Hook Form

```tsx
import {
  Label,
  Option,
  Section,
  Select,
} from "@mittwald/flow-react-components";
import { useForm } from "react-hook-form";
import {
  Form,
  SubmitButton,
  typedField,
} from "@mittwald/flow-react-components/react-hook-form";
import { sleep } from "@/content/04-components/actions/action/examples/lib";

export default () => {
  const form = useForm<{ app: string }>();
  const Field = typedField(form);

  return (
    <Section>
      <Form form={form} onSubmit={sleep}>
        <Field
          name="app"
          rules={{
            required: "Bitte wähle eine App aus",
          }}
        >
          <Select>
            <Label>App</Label>
            <Option value="wordpress">WordPress</Option>
            <Option value="typo3">TYPO3</Option>
          </Select>
        </Field>
        <SubmitButton>Speichern</SubmitButton>
      </Form>
    </Section>
  );
}
```


## Develop

# Properties

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `isReadOnly` | `boolean` | - | Whether the component is read only. |
| `id` | `string` | - | The element's unique identifier. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/id). |
| `translate` | `"yes" \| "no"` | - | - |
| `isOpen` | `boolean` | - | Sets the open state of the menu. |
| `defaultOpen` | `boolean` | - | Sets the default open state of the menu. |
| `style` | `StyleOrFunction<TooltipRenderProps>` | - | The inline [style](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style) for the element. A function may be provided to compute the style based on component state. |
| `render` | `DOMRenderFunction<"div", TooltipRenderProps>` | - | Overrides the default DOM element with a custom render function. This allows rendering existing components with built-in styles and behaviors such as router links, animation libraries, and pre-styled components. Requirements: - You must render the expected element type (e.g. if `<button>` is expected, you cannot render an `<a>`). - Only a single root DOM element can be rendered (no fragments). - You must pass through props and ref to the underlying DOM element, merging with your own prop as appropriate. |
| `dir` | `string` | - | - |
| `lang` | `string` | - | - |
| `hidden` | `boolean` | - | - |
| `inert` | `boolean` | - | - |
| `validationBehavior` | `"native" \| "aria"` | `'native'` | Whether to use native HTML form validation to prevent form submission when the value is missing or invalid, or mark the field as required or invalid via ARIA. |
| `isDisabled` | `boolean` | - | Whether the input is disabled. |
| `isRequired` | `boolean` | - | Whether user input is required on the input before form submission. |
| `isInvalid` | `boolean` | - | Whether the input value is invalid. |
| `validate` | `((value: TimeValue) => true \| ValidationError)` | - | A function that returns an error message if a given value is invalid. Validation errors are displayed to the user when the form is submitted if `validationBehavior="native"`. For realtime validation, use the `isInvalid` prop instead. |
| `autoFocus` | `boolean` | - | Whether the element should receive focus on render. |
| `value` | `TimeValue` | - | The current value (controlled). |
| `defaultValue` | `TimeValue` | - | The default value (uncontrolled). |
| `name` | `string` | - | The name of the input, used when submitting an HTML form. |
| `form` | `string` | - | The `<form>` element to associate the input with. The value of this attribute must be the id of a `<form>` in the same document. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input#form). |
| `slot` | `string` | - | A slot name for the component. Slots allow the component to receive props from a parent component. An explicit `null` value indicates that the local props completely override all props received from a parent. |
| `placeholder` | `string` | `'Select an item' (localized)` | Temporary text that occupies the select when it is empty. |
| `excludeFromTabOrder` | `boolean` | - | Whether to exclude the element from the sequential tab order. If true, the element will not be focusable via the keyboard by tabbing. This should be avoided except in rare scenarios where an alternative means of accessing the element or its functionality via the keyboard is available. |
| `autoComplete` | `string` | - | Describes the type of autocomplete functionality the input should provide if any. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefautocomplete). |
| `selectedKey` _(deprecated)_ | `Key` | - | The currently selected key in the collection (controlled). @deprecated |
| `defaultSelectedKey` _(deprecated)_ | `Key` | - | The initial selected key in the collection (uncontrolled). @deprecated |
| `disabledKeys` | `Iterable<Key>` | - | The item keys that are disabled. These items cannot be selected, focused, or otherwise interacted with. |
| `selectionMode` | `"single"` | `'single'` | Whether single or multiple selection is enabled. |
| `shouldCloseOnSelect` | `boolean` | - | Whether the Select should close when an item is selected. Defaults to true if selectionMode is single, false otherwise. |
| `allowsEmptyCollection` | `boolean` | - | Whether the select should be allowed to be open when the collection is empty. |
| `children` | `ReactNode` | - | - |
| `wrapWith` | `ReactElement<unknown, string \| JSXElementConstructor<any>>` | - | - |
| `ref` | `Ref<HTMLSpanElement>` | - | Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref). @see [React Docs](https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom) |
| `key` | `Key` | - | - |
| `className` | `string` | - | The elements class name. |

### Events

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `onChange` | `((value: Key) => void)` | - | Handler that is called when the selected value changes. |
| `onOpenChange` | `((isOpen: boolean) => void)` | - | Method that is called when the open state of the menu changes. |
| `onClick` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onClickCapture` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onAuxClick` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onAuxClickCapture` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onContextMenu` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onContextMenuCapture` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onDoubleClick` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onDoubleClickCapture` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseDown` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseDownCapture` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseEnter` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseLeave` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseMove` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseMoveCapture` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseOut` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseOutCapture` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseOver` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseOverCapture` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseUp` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseUpCapture` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onTouchCancel` | `TouchEventHandler<HTMLDivElement>` | - | - |
| `onTouchCancelCapture` | `TouchEventHandler<HTMLDivElement>` | - | - |
| `onTouchEnd` | `TouchEventHandler<HTMLDivElement>` | - | - |
| `onTouchEndCapture` | `TouchEventHandler<HTMLDivElement>` | - | - |
| `onTouchMove` | `TouchEventHandler<HTMLDivElement>` | - | - |
| `onTouchMoveCapture` | `TouchEventHandler<HTMLDivElement>` | - | - |
| `onTouchStart` | `TouchEventHandler<HTMLDivElement>` | - | - |
| `onTouchStartCapture` | `TouchEventHandler<HTMLDivElement>` | - | - |
| `onPointerDown` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerDownCapture` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerMove` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerMoveCapture` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerUp` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerUpCapture` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerCancel` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerCancelCapture` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerEnter` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerLeave` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerOver` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerOverCapture` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerOut` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerOutCapture` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onGotPointerCapture` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onGotPointerCaptureCapture` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onLostPointerCapture` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onLostPointerCaptureCapture` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onScroll` | `UIEventHandler<HTMLDivElement>` | - | - |
| `onScrollCapture` | `UIEventHandler<HTMLDivElement>` | - | - |
| `onWheel` | `WheelEventHandler<HTMLDivElement>` | - | - |
| `onWheelCapture` | `WheelEventHandler<HTMLDivElement>` | - | - |
| `onAnimationStart` | `AnimationEventHandler<HTMLDivElement>` | - | - |
| `onAnimationStartCapture` | `AnimationEventHandler<HTMLDivElement>` | - | - |
| `onAnimationEnd` | `AnimationEventHandler<HTMLDivElement>` | - | - |
| `onAnimationEndCapture` | `AnimationEventHandler<HTMLDivElement>` | - | - |
| `onAnimationIteration` | `AnimationEventHandler<HTMLDivElement>` | - | - |
| `onAnimationIterationCapture` | `AnimationEventHandler<HTMLDivElement>` | - | - |
| `onTransitionCancel` | `TransitionEventHandler<HTMLDivElement>` | - | - |
| `onTransitionCancelCapture` | `TransitionEventHandler<HTMLDivElement>` | - | - |
| `onTransitionEnd` | `TransitionEventHandler<HTMLDivElement>` | - | - |
| `onTransitionEndCapture` | `TransitionEventHandler<HTMLDivElement>` | - | - |
| `onTransitionRun` | `TransitionEventHandler<HTMLDivElement>` | - | - |
| `onTransitionRunCapture` | `TransitionEventHandler<HTMLDivElement>` | - | - |
| `onTransitionStart` | `TransitionEventHandler<HTMLDivElement>` | - | - |
| `onTransitionStartCapture` | `TransitionEventHandler<HTMLDivElement>` | - | - |
| `onFocus` | `((e: FocusEvent<Element, Element>) => void)` | - | Handler that is called when the element receives focus. |
| `onBlur` | `((e: FocusEvent<Element, Element>) => void)` | - | Handler that is called when the element loses focus. |
| `onFocusChange` | `((isFocused: boolean) => void)` | - | Handler that is called when the element's focus status changes. |
| `onKeyDown` | `((e: KeyboardEvent) => void)` | - | Handler that is called when a key is pressed. |
| `onKeyUp` | `((e: KeyboardEvent) => void)` | - | Handler that is called when a key is released. |
| `onSelectionChange` _(deprecated)_ | `((key: Key) => void)` | - | Handler that is called when the selection changes. @deprecated |

### Accessibility

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `aria-label` | `string` | - | Defines a string value that labels the current element. |
| `aria-labelledby` | `string` | - | Identifies the element (or elements) that labels the current element. |
| `aria-describedby` | `string` | - | Identifies the element (or elements) that describes the object. |
| `aria-details` | `string` | - | Identifies the element (or elements) that provide a detailed, extended description for the object. |


## Guidelines

# Grundlagen

## Best practices

Achte bei der Verwendung eines Selects darauf, dass ...

- das [Label](/04-components/content/label/overview) kurz und deutlich
  formuliert ist.
- ein Placeholder verwendet wird, wenn kein sinnvoller Default-Wert existiert
  oder der User aktiv eine Auswahl treffen soll. Der Placeholder sollte eine
  klare Handlungsaufforderung enthalten – zum Beispiel: „Sprache wählen“.
- die Optionen verständlich und konsistent benannt sind. Jeder Eintrag sollte
  mit einem Großbuchstaben beginnen; Satzzeichen wie Kommas oder Semikolons sind
  zu vermeiden.
- die Anzahl der Optionen überschaubar bleibt. Bei sehr vielen Einträgen kann
  z. B. eine [ComboBox](/04-components/form-controls/combo-box/overview) die
  bessere Wahl sein.
- die Optionen in einer sinnvollen, nachvollziehbaren Reihenfolge dargestellt
  werden, z. B. alphabetisch, thematisch oder nach Relevanz.

## Verwendung

Verwende ein Select, um ...

- eine Einfachauswahl bereitzustellen. Diese sollte aus mindestens zwei Optionen
  bestehen. Zu beachten ist, dass im geschlossenen Zustand immer nur eine Option
  für den User sichtbar ist. Wenn alle Optionen direkt sichtbar sein sollen,
  muss eine andere Component verwendet werden (z. B.
  [RadioGroup](/04-components/form-controls/radio-group/overview)).
- Platz zu sparen, wenn beispielsweise eine
  [RadioGroup](/04-components/form-controls/radio-group/overview) oder ein
  [SegmentedControl](/04-components/form-controls/segmented-control/overview) zu
  viel Raum einnehmen würde.
- Usern ausschließlich gültige Auswahlmöglichkeiten anzubieten – im Gegensatz
  zur freien Texteingabe im
  [TextField](/04-components/form-controls/text-field/overview).
- in Formularen eine klare Entscheidung aus mehreren Alternativen einzufordern.

