## Feature Examples

### Size
- description: Adjust the component size using the size prop. - `large` emphasize fields in onboarding flows. - `medium` is the default size used in most cases. - `small` should be used in compact layouts. - `tiny` should be used in very dense layouts. Avoid using this size when possible.
- example:
```jsx
() => {
  const options = [
    { id: 0, value: 'Option 1' },
    { id: 1, value: 'Option 2' },
    { id: 2, value: 'Option 3' },
  ];
  return (
    <StorybookComponents.Stack flexDirection="column">
      <Dropdown size="large" placeholder="Large" options={options} />
      <Dropdown size="medium" placeholder="Medium" options={options} />
      <Dropdown size="small" placeholder="Small" options={options} />
      <Dropdown size="tiny" placeholder="Tiny" options={options} />
    </StorybookComponents.Stack>
  );
};
```

### Border
- description: Style the component using the border prop which supports four styles: - For forms, use `standard`. - When the component is used to filter, use `round`. - For titles that can be edited on click, use `bottomLine`. - In the Content Manager's spreadsheet, use `none`.
- example:
```jsx
() => {
  const options = [
    { id: 0, value: 'Option 1' },
    { id: 1, value: 'Option 2' },
    { id: 2, value: 'Option 3' },
  ];
  return (
    <StorybookComponents.Stack flexDirection="column">
      <Dropdown border="standard" placeholder="Standard" options={options} />
      <Dropdown border="round" placeholder="Round" options={options} />
      <Dropdown
        border="bottomLine"
        placeholder="Bottom Line"
        options={options}
      />
      <Dropdown border="none" placeholder="None" options={options} />
    </StorybookComponents.Stack>
  );
};
```

### Status
- description: Use the `status` prop to control component status. - `error` highlights an invalid selection. - `warning` highlights a value that can't be validated or impacts a user's business. - `loading` shows that the value is loading. Hide the status suffix and indicate the state with a border color by setting `hideStatusSuffix`to true.
- example:
```jsx
() => {
  const options = [
    { id: 0, value: 'Option 1' },
    { id: 1, value: 'Option 2' },
    { id: 2, value: 'Option 3' },
  ];
  return (
    <StorybookComponents.Stack flexDirection="column">
      <Dropdown status="error" placeholder="Error" options={options} />
      <Dropdown status="warning" placeholder="Warning" options={options} />
      <Dropdown status="loading" placeholder="Loading" options={options} />
    </StorybookComponents.Stack>
  );
};
```

### Status message
- description: Add text that explains the status or what action the user should take with the `statusMessage` prop. Showing the status message inline, directly below the dropdown is preferred in all default cases. - To add an accessible inline message, wrap the component in a `<FormField/>` and add the `statusMessage`. - To add a status message in a tooltip that requires users to hover on the icon, use the `statusMessage` prop. Control tooltip placement with `tooltipPlacement` prop. View more inline status message examples in `<FormField/>`.
- example:
```jsx
() => {
  const options = [
    { id: 0, value: 'Option 1' },
    { id: 1, value: 'Option 2' },
    { id: 2, value: 'Option 3' },
  ];
  return (
    <StorybookComponents.Stack flexDirection="column">
      <StorybookComponents.Stack flexDirection="column" gap="12px">
        <Text secondary>For all default cases:</Text>
        <FormField status="error" statusMessage="This is an error message.">
          <Dropdown
            placeholder="See message below"
            tooltipPlacement="top-end"
            options={options}
          />
        </FormField>
      </StorybookComponents.Stack>
      <StorybookComponents.Stack flexDirection="column" gap="12px">
        <Text secondary>For narrow layouts only:</Text>
        <Dropdown
          placeholder="Hover on status icon"
          status="error"
          statusMessage="This is an error message."
          tooltipPlacement="top-end"
          options={options}
        />
      </StorybookComponents.Stack>
    </StorybookComponents.Stack>
  );
};
```

### Disabled
- description: Disable all input interactions with the `disabled` prop. Use it to highlight unavailable functions.
- example:
```jsx
() => {
  const options = [
    { id: 0, value: 'Option 1' },
    { id: 1, value: 'Option 2' },
    { id: 2, value: 'Option 3' },
  ];
  return <Dropdown disabled placeholder="Disabled" options={options} />;
};
```

### Affix
- description: Add additional information to `prefix` and `suffix` props (e.g. text, icons, buttons) to support the dropdown value.
- example:
```jsx
() => {
  const discountSuffixOptions = [
    { id: 0, value: '5' },
    { id: 1, value: '10' },
    { id: 2, value: '15' },
  ];
  const discountAffixOptions = [
    { id: 0, value: '10' },
    { id: 1, value: '20' },
    { id: 2, value: '30' },
  ];
  const languageOptions = [
    { id: 0, value: 'English' },
    { id: 1, value: 'French' },
    { id: 2, value: 'Spanish' },
  ];
  const employeeOptions = [
    { id: 0, value: 'Employee 1' },
    { id: 1, value: 'Employee 2' },
    { id: 2, value: 'Employee 3' },
  ];

  return (
    <StorybookComponents.Stack flexDirection="column">
      <Dropdown
        placeholder="Select discount size"
        suffix={<Input.Affix>%</Input.Affix>}
        options={discountSuffixOptions}
      />
      <Dropdown
        placeholder="Select discount size"
        prefix={<Input.Affix>$</Input.Affix>}
        options={discountAffixOptions}
      />
      <Dropdown
        placeholder="Select language"
        prefix={
          <Input.IconAffix>
            <Icons.Languages />
          </Input.IconAffix>
        }
        options={languageOptions}
      />
      <Dropdown
        placeholder="Select employee"
        prefix={
          <Input.Affix>
            <Avatar size="size18" />
          </Input.Affix>
        }
        options={employeeOptions}
      />
    </StorybookComponents.Stack>
  );
};
```

### Clear button
- description: Enable a button that clears the dropdown value by using the `clearButton` prop. Show it when the field value is optional or has to be cleared often.
- example:
```jsx
() => {
  const [selectedOption, setSelectedOption] = React.useState(0);
  const options = [
    { id: 0, value: 'Click clear button to remove selection' },
    { id: 1, value: 'Option 2' },
    { id: 2, value: 'Option 3' },
  ];

  return (
    <Dropdown
      placeholder="Select"
      clearButton
      onClear={() => setSelectedOption(null)}
      onSelect={(option) => setSelectedOption(Number(option.id))}
      selectedId={selectedOption}
      options={options}
    />
  );
};
```

### Fixed header and footer
- description: Add related actions to `fixedFooter` or `fixedHeader` areas. These headers and footers keep their position on scroll.
- example:
```jsx
() => {
  const options = [
    { id: 1, value: 'Option 1' },
    { id: 2, value: 'Option 2' },
    { id: 3, value: 'Option 3' },
    { id: 4, value: 'Option 4' },
    { id: 5, value: 'Option 5' },
    { id: 6, value: 'Option 6' },
    { id: 7, value: 'Option 7' },
    { id: 8, value: 'Option 8' },
    { id: 9, value: 'Option 9' },
  ];
  return (
    <Dropdown
      placeholder="Select"
      fixedHeader={<ListItemAction title="Fixed Header" />}
      fixedFooter={<ListItemAction title="Fixed Footer" />}
      options={options}
    />
  );
};
```

### List item builders
- description: Use three props to build custom layouts: - `listItemSectionBuilder` groups items into sections by type. - `listItemActionBuilder` adds a text button for related list actions. - `listItemSelectBuilder` builds custom list designs.
- example:
```jsx
() => {
  const listItemSectionOptions = [
    listItemSectionBuilder({
      id: 0,
      type: 'title',
      title: 'Group Title',
    }),
    { id: 1, value: 'Option 1' },
    { id: 2, value: 'Option 2' },
    { id: 3, value: 'Option 3' },
    listItemSectionBuilder({
      id: 3,
      type: 'divider',
    }),
    { id: 4, value: 'Option 4' },
  ];

  const listItemActionOptions = [
    listItemActionBuilder({
      id: 0,
      title: 'Action',
    }),
    { id: 1, value: 'Option 1' },
    { id: 2, value: 'Option 2' },
    { id: 3, value: 'Option 3' },
  ];

  const listItemSelectOptions = [
    listItemSelectBuilder({
      id: 0,
      prefix: <Avatar size="size30" />,
      title: 'Title',
      subtitle: 'Subtitle',
      suffix: 'Suffix',
    }),
    listItemSelectBuilder({
      id: 1,
      prefix: <Avatar size="size30" />,
      title: 'Title',
      subtitle: 'Subtitle',
      suffix: 'Suffix',
    }),
    listItemSelectBuilder({
      id: 2,
      prefix: <Avatar size="size30" />,
      title: 'Title',
      subtitle: 'Subtitle',
      suffix: 'Suffix',
    }),
  ];
  return (
    <StorybookComponents.Stack flexDirection="column">
      <Dropdown
        placeholder="List Item Section"
        options={listItemSectionOptions}
      />
      <Dropdown
        placeholder="List Item Action"
        options={listItemActionOptions}
      />
      <Dropdown
        placeholder="List Item Select"
        options={listItemSelectOptions}
      />
    </StorybookComponents.Stack>
  );
};
```

### List container dimensions
- description: Control the container size for the list of options with these props: - `maxHeightPixels` specifies the maximum height for longer lists. - `dropdownWidth` matches content width or specifies pixels. Set width to 'auto' or 'max-content.' - `minWidthPixels` manually increases dropdown popover width. By default, the dropdown matches the input field width.
- example:
```jsx
() => {
  const options = [
    { id: 0, value: 'Option 1' },
    { id: 1, value: 'Option 2' },
    { id: 2, value: 'Option 3' },
    { id: 3, value: 'Option 4' },
    { id: 4, value: 'Option 5' },
    { id: 5, value: 'Option 6' },
    { id: 6, value: 'Option 7' },
    { id: 7, value: 'Option 8' },
  ];

  return (
    <StorybookComponents.Stack>
      <Dropdown
        placeholder="Look at proportions"
        maxHeightPixels="200px"
        dropdownWidth="auto"
        minWidthPixels="400px"
        options={options}
        popoverProps={{
          placement: 'bottom-start',
        }}
      />
    </StorybookComponents.Stack>
  );
};
```

### Marked option
- description: Once the dropdown is opened, use the `markedOption` to highlight the option.
- example:
```jsx
<Dropdown
  placeholder="Select an option"
  markedOption={1}
  options={[
    { id: 0, value: 'Option 1' },
    { id: 1, value: 'Option 2' },
    { id: 2, value: 'Option 3' },
  ]}
/>;
```

### Native support
- description: Switch to `native` support for mobile usage. Avoid using it for desktop applications.
- example:
```jsx
() => {
  const options = [
    { id: 0, value: 'Option 1' },
    { id: 1, value: 'Option 2' },
    { id: 2, value: 'Option 3' },
    { id: 3, value: 'Option 4' },
  ];
  return <Dropdown options={options} placeholder="Select as native" native />;
};
```

### Text overflow
- description: Control text overflow in the field with the `textOverflow`. Apply `clip` or `ellipsis`. Dropdown list options wrap by default. To apply ellipsis, select the items to be displayed with the `listItemSelectBuilder`. This isn't recommended.
- example:
```jsx
() => {
  const options = [
    { id: 0, value: 'Option 1' },
    { id: 1, value: 'Option 2' },
    { id: 2, value: 'Option 3' },
    { id: 3, value: 'Option 4' },
  ];
  const longOptions = [
    {
      id: 0,
      value: 'This is a long value that make dropdown layout grow',
    },
    {
      id: 1,
      value: 'This is a long value that make dropdown layout grow',
    },
    {
      id: 2,
      value: 'This is a long value that make dropdown layout grow',
    },
  ];
  const longOptionsWithEllipsis = [
    listItemSelectBuilder({
      id: 0,
      title: 'This is a long value that make dropdown layout grow',
      ellipsis: true,
    }),
    listItemSelectBuilder({
      id: 0,
      title: 'This is a long value that make dropdown layout grow',
      ellipsis: true,
    }),
    listItemSelectBuilder({
      id: 0,
      title: 'This is a long value that make dropdown layout grow',
      ellipsis: true,
    }),
  ];

  return (
    <StorybookComponents.Stack flexDirection="column">
      <StorybookComponents.Stack>
        <FormField label="Input value with ellipsis::">
          <Dropdown
            options={options}
            placeholder="This field is showing ellipsis at the end of this line"
            textOverflow="ellipsis"
          />
        </FormField>
        <FormField label="Input value clipped:">
          <Dropdown
            options={options}
            placeholder="This field is clipping content at the end of this line"
            textOverflow="clip"
          />
        </FormField>
      </StorybookComponents.Stack>
      <StorybookComponents.Stack>
        <FormField label="Options wrapped:">
          <Dropdown options={longOptions} placeholder="Select wrapped option" />
        </FormField>
        <FormField label="Options with ellipsis:">
          <Dropdown
            options={longOptionsWithEllipsis}
            placeholder="Select clipped option"
          />
        </FormField>
      </StorybookComponents.Stack>
    </StorybookComponents.Stack>
  );
};
```

## Developer Examples

### Lazy loading
- description: Gradually load items with `infiniteScroll`, `loadMore` and `hasMore` props.
- example:
```jsx
() => {
  const [data, setData] = React.useState([]);
  const fetchMoreData = () =>
    Promise.resolve(
      fetch(`/api/dropdown?limit=${5}&offset=${data.length}`),
    ).then((results) => setData([...data, ...results]));

  React.useEffect(() => {
    fetchMoreData();
  }, []);

  return (
    <Dropdown
      placeholder="Select"
      options={data}
      infiniteScroll
      hasMore={true}
      loadMore={fetchMoreData}
    />
  );
};
```

### Controlled
- description: Component can be used in controlled mode by passing `selectedId` and `onSelect` props.
- example:
```jsx
() => {
  const [selectedId, setSelected] = React.useState(0);

  const options = [
    listItemSelectBuilder({
      id: 0,
      prefix: (
        <Box>
          <Icons.Home />
        </Box>
      ),
      title: 'Home address',
      label: 'Home address',
    }),
    listItemSelectBuilder({
      id: 1,
      title: 'Work address',
      label: 'Work address',
      prefix: (
        <Box>
          <Icons.Toolbox />
        </Box>
      ),
    }),
    listItemSelectBuilder({
      id: 2,
      title: 'Mailing address',
      label: 'Mailing address',
      prefix: (
        <Box>
          <Icons.Email />
        </Box>
      ),
    }),
    listItemSelectBuilder({
      id: 3,
      title: 'Shipping address',
      label: 'Shipping address',
      prefix: (
        <Box>
          <Icons.Archive />
        </Box>
      ),
    }),
    listItemSelectBuilder({
      id: 4,
      title: 'Other',
      label: 'Other',
      prefix: (
        <Box>
          <Icons.Category />
        </Box>
      ),
    }),
  ];

  return (
    <Dropdown
      placeholder="Select"
      selectedId={selectedId}
      valueParser={(option) => option.label}
      onSelect={(e) => setSelected(Number(e.id))}
      options={options}
    />
  );
};
```

## Common Use Case Examples

### Settings panel
- description: Use dropdown to let users select a single item from a predefined list of options in a settings panel.
- example:
```jsx
() => {
  const [selectedOption, setSelectedOption] = React.useState(0);
  const [value, setValue] = React.useState(2);

  const options = [
    { id: 0, value: 'Image' },
    { id: 1, value: 'Video' },
    { id: 2, value: 'Image and video' },
    { id: 3, value: 'Document' },
    { id: 4, value: 'Audio' },
  ];
  return (
    <SidePanel maxHeight="576px" width="288px" skin="floating">
      <SidePanel.Header title="Upload Settings" />
      <SidePanel.Content noPadding>
        <SidePanel.Field>
          <FormField label="Supported file type">
            <Dropdown
              placeholder="Select"
              size="small"
              options={options}
              onSelect={(option) => setSelectedOption(Number(option.id))}
              selectedId={selectedOption}
            />
          </FormField>
        </SidePanel.Field>
        <SidePanel.Field>
          <FieldSet
            gap="small"
            legend="Max number of files"
            columns="auto 60px"
          >
            <Slider
              onChange={(newValue) => setValue(Number(newValue))}
              min={0}
              max={10}
              value={value}
              displayMarks={false}
            />
            <Input
              size="small"
              value={value}
              onChange={(e) => setValue(Number(e.target.value))}
            />
          </FieldSet>
        </SidePanel.Field>
        <SidePanel.Field>
          <FormField label="This field is">
            <Checkbox size="small" checked>
              Required
            </Checkbox>
          </FormField>
        </SidePanel.Field>
        <SidePanel.Section title="Display settings">
          <SidePanel.Field>
            <FormField label="Field title">
              <Input size="small" placeholder="Enter field title" />
            </FormField>
          </SidePanel.Field>
          <SidePanel.Field>
            <FormField label="Button text">
              <Input size="small" value="Choose file" />
            </FormField>
          </SidePanel.Field>
        </SidePanel.Section>
      </SidePanel.Content>
    </SidePanel>
  );
};
```

### Prefix icon
- description: Use `listItemSelectBuilder` to create custom layouts for options in the dropdown. For example, use avatars, icons or images as prefix icons.
- example:
```jsx
() => {
  const options = [
    listItemSelectBuilder({
      id: 0,
      prefix: (
        <Box>
          <Icons.Home />
        </Box>
      ),
      title: 'Home address',
      label: 'Home address',
    }),
    listItemSelectBuilder({
      id: 1,
      title: 'Work address',
      label: 'Work address',
      prefix: (
        <Box>
          <Icons.Toolbox />
        </Box>
      ),
    }),
    listItemSelectBuilder({
      id: 2,
      title: 'Mailing address',
      label: 'Mailing address',
      prefix: (
        <Box>
          <Icons.Email />
        </Box>
      ),
    }),
    listItemSelectBuilder({
      id: 3,
      title: 'Shipping address',
      label: 'Shipping address',
      prefix: (
        <Box>
          <Icons.Archive />
        </Box>
      ),
    }),
    listItemSelectBuilder({
      id: 4,
      title: 'Other',
      label: 'Other',
      prefix: (
        <Box>
          <Icons.Category />
        </Box>
      ),
    }),
  ];

  return (
    <FormField label="Address type">
      <Dropdown
        placeholder="Select"
        valueParser={(option) => option.label}
        options={options}
      />
    </FormField>
  );
};
```

### Grouping
- description: Use `listItemSectionBuilder` within the drop down to group options into categories.
- example:
```jsx
<Layout>
  <Cell span={12}>
    <FormField label="Product">
      <Dropdown
        placeholder="Select"
        options={[
          listItemSectionBuilder({
            id: 'most-popular',
            title: 'Most popular',
          }),
          { id: 1, value: 'Wix Stores' },
          { id: 2, value: 'Wix Bookings' },
          { id: 3, value: 'Wix Blog' },
          listItemSectionBuilder({
            id: 'other',
            title: 'Other',
          }),
          { id: 4, value: 'Wix Events' },
          { id: 5, value: 'Wix Forum' },
          { id: 6, value: 'Wix Restaurants' },
        ]}
      />
    </FormField>
  </Cell>
  <Cell span={12}>
    <FormField label="Role">
      <Dropdown
        placeholder="Select"
        options={[
          listItemSectionBuilder({
            id: 'general',
            title: 'General',
            type: 'subheader',
            suffix: 'Edit',
          }),
          { id: 0, value: 'Website manager' },
          { id: 1, value: 'Website designer' },
          { id: 2, value: 'Back office manager' },
          listItemSectionBuilder({
            id: 'content-manager-roles',
            title: 'Content manager roles',
            type: 'subheader',
            suffix: 'Edit',
          }),
          { id: 3, value: 'Content collection manager' },
          listItemSectionBuilder({
            id: 'blog-roles',
            title: 'Blog roles',
            type: 'subheader',
            suffix: 'Edit',
          }),
          { id: 4, value: 'Blog editor' },
          { id: 5, value: 'Blog writer' },
          { id: 6, value: 'Guest writer' },
          listItemSectionBuilder({
            id: 'booking-roles',
            title: 'Booking roles',
            type: 'subheader',
            suffix: 'Edit',
          }),
          { id: 7, value: 'Bookings admin' },
          { id: 8, value: 'Bookings staff member' },
        ]}
      />
    </FormField>
  </Cell>
</Layout>;
```
