## Feature Examples

### Size
- description: Adjust the component size using the `size` prop. It supports 3 sizes: - `large` is best for onboarding flows, where input needs emphasis. - `medium` (default) – use for most cases. - `small` is appropriate for dense and narrow layouts.
- example:
```jsx
() => {
  const options = [
    { id: 1, value: 'tag 1' },
    { id: 2, value: 'tag 2' },
    { id: 3, value: 'tag 3' },
  ];

  const renderMultiSelect = ({ size, tagSize }) => {
    const [tags, setTags] = React.useState([
      {
        size: tagSize,
        id: '1',
        label: 'tag 1',
      },
      {
        size: tagSize,
        id: '2',
        label: 'tag 2',
      },
    ]);

    const handleOnSelect = (tag) =>
      setTags([...tags, { id: tag.id, label: tag.value, size: tagSize }]);

    const handleOnRemoveTag = (tagId) =>
      setTags(tags.filter((currTag) => currTag.id !== tagId));

    return (
      <MultiSelect
        size={size}
        options={options}
        tags={tags}
        onSelect={handleOnSelect}
        onRemoveTag={handleOnRemoveTag}
      />
    );
  };

  return (
    <StorybookComponents.Stack flexDirection="column">
      <FormField label="Large">
        {renderMultiSelect({ size: 'large', tagSize: 'medium' })}
      </FormField>
      <FormField label="Medium">
        {renderMultiSelect({ size: 'medium', tagSize: 'small' })}
      </FormField>
      <FormField label="Small">
        {renderMultiSelect({ size: 'small', tagSize: 'tiny' })}
      </FormField>
    </StorybookComponents.Stack>
  );
};
```

### Border
- description: Style the component using the `border` prop. It supports 4 styles: - For forms and most common cases, use `default`. - When component is used to filter data, use `round`. - Use `bottomLine` to create an editable, underlined title field. - When a component provides its own hover and focus styles, such as a table or spreadsheet cells, use `none`.
- example:
```jsx
() => {
  const options = [
    { 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' },
  ];

  return (
    <StorybookComponents.Stack flexDirection="column">
      <MultiSelect
        border="standard"
        placeholder="Standard"
        options={options}
        mode="select"
      />
      <MultiSelect
        border="round"
        placeholder="Round"
        options={options}
        mode="select"
      />
      <MultiSelect
        border="bottomLine"
        placeholder="Bottom line"
        options={options}
        mode="select"
      />
      <MultiSelect
        border="none"
        placeholder="None"
        options={options}
        mode="select"
      />
    </StorybookComponents.Stack>
  );
};
```

### Status
- description: Control the component status using a `status` prop. It supports 3 states: - `error` demonstrates that a required input is missing something or the entry was invalid. - `warning` highlights a value that might have a significant impact to a user. - `loading` shows when a value is being uploaded to the server.
- example:
```jsx
() => {
  const options = [
    { 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' },
  ];

  return (
    <StorybookComponents.Stack flexDirection="column">
      <MultiSelect status="error" placeholder="Error" options={options} />
      <MultiSelect status="warning" placeholder="Warning" options={options} />
      <MultiSelect 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 component 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 = [
    { 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' },
  ];

  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.">
          <MultiSelect placeholder="See message below" options={options} />
        </FormField>
      </StorybookComponents.Stack>
      <StorybookComponents.Stack flexDirection="column" gap="12px">
        <Text secondary>For narrow layouts only:</Text>
        <MultiSelect
          status="error"
          placeholder="Hover on status icon"
          statusMessage="This is an error message."
          options={options}
        />
      </StorybookComponents.Stack>
    </StorybookComponents.Stack>
  );
};
```

### Read-only and disabled
- description: Multi select can also be made read-only or disabled entirely. - `readOnly` disables adding or editing, but allows the user to copy the current value. Use it to display URLs, code, etc. - `disabled` removes all interactions and creates a disabled component state. Use it to highlight functions that are unavailable.
- example:
```jsx
() => {
  const options = [
    { 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' },
  ];

  return (
    <StorybookComponents.Stack flexDirection="column">
      <MultiSelect value="Read Only" readOnly />
      <MultiSelect
        placeholder="Disabled"
        mode="select"
        options={options}
        disabled
      />
    </StorybookComponents.Stack>
  );
};
```

### Action
- description: Encourage user engagement by displaying the call to action. To add a [`<TextButton/>`](#/component/textbutton), use the `customSuffix` property.
- example:
```jsx
() => {
  const [tags, setTags] = React.useState([]);

  const handleOnSelect = (tag) =>
    setTags([...tags, { id: tag.id, label: tag.value }]);

  const handleOnRemoveTag = (tagId) =>
    setTags(tags.filter((currTag) => currTag.id !== tagId));

  return (
    <MultiSelect
      tags={tags}
      options={[
        { id: '1', value: 'tag 1' },
        { id: '2', value: 'tag 2' },
        { id: '3', value: 'tag 3' },
      ]}
      customSuffix={
        <Box>
          <TextButton prefixIcon={<Icons.Add />}>Add Tag</TextButton>
        </Box>
      }
      onSelect={handleOnSelect}
      onRemoveTag={handleOnRemoveTag}
    />
  );
};
```

### Select mode
- description: Allow users to select only options that are listed with `mode` prop.
- example:
```jsx
() => {
  const [tags, setTags] = React.useState([]);

  const handleOnSelect = (tag) =>
    setTags([...tags, { id: tag.id, label: tag.value }]);

  const handleOnRemoveTag = (tagId) =>
    setTags(tags.filter((currTag) => currTag.id !== tagId));

  return (
    <MultiSelect
      tags={tags}
      options={[
        { id: '1', value: 'tag 1' },
        { id: '2', value: 'tag 2' },
        { id: '3', value: 'tag 3' },
      ]}
      mode="select"
      placeholder="Select tags from a list"
      onSelect={handleOnSelect}
      onRemoveTag={handleOnRemoveTag}
    />
  );
};
```

### Manual input
- description: Allow users to enter their own tags using the keyboard with `onManuallyInput` property.
- example:
```jsx
() => {
  const [tags, setTags] = React.useState([]);

  const handleManualInput = (tag) =>
    setTags([...tags, { id: Math.random(), label: tag[0] }]);

  const handleOnRemoveTag = (tagId) =>
    setTags(tags.filter((currTag) => currTag.id !== tagId));

  return (
    <MultiSelect
      tags={tags}
      placeholder="Type custom tags and separate them with the Enter key"
      onManuallyInput={handleManualInput}
      onRemoveTag={handleOnRemoveTag}
    />
  );
};
```

### Predicate
- description: Build autocomplete features using the `predicate` property.
- example:
```jsx
() => {
  const [value, setValue] = React.useState('');
  const [tags, setTags] = React.useState([]);

  const options = [
    { value: 'Alabama', id: 'AL' },
    { value: 'California', id: 'CA' },
    { value: 'North Carolina', id: 'NC' },
    { value: 'Colorado', id: 'CO' },
    { value: 'Connecticut', id: 'CT' },
  ];

  const handleOnChange = (event) => setValue(event.target.value);

  const predicate = (option) =>
    option.value && option.value.toLowerCase().includes(value.toLowerCase());

  const handleOnSelect = (tag) =>
    setTags([...tags, { id: tag.id, label: tag.value }]);

  const handleOnRemoveTag = (tagId) =>
    setTags(tags.filter((currTag) => currTag.id !== tagId));

  return (
    <MultiSelect
      predicate={predicate}
      tags={tags}
      value={value}
      options={options}
      onChange={handleOnChange}
      placeholder="Start typing a state to find a match"
      onSelect={handleOnSelect}
      onRemoveTag={handleOnRemoveTag}
    />
  );
};
```

### Reorder
- description: Use the `onReorder` property to allow users to change the order in which keywords are displayed.
- example:
```jsx
() => {
  const [tags, setTags] = React.useState([
    { id: '1', label: 'One' },
    { id: '2', label: 'Two' },
    { id: '3', label: 'Three' },
  ]);

  const options = [
    { id: '1', value: 'One' },
    { id: '2', value: 'Two' },
    { id: '3', value: 'Three' },
  ];

  const handleOnSelect = (tag) =>
    setTags([...tags, { id: tag.id, label: tag.value }]);

  const handleOnRemoveTag = (tagId) =>
    setTags(tags.filter((currTag) => currTag.id !== tagId));

  return (
    <MultiSelect
      tags={tags}
      options={options}
      onReorder={({ addedIndex, removedIndex }) => {
        const nextTags = tags.slice();
        nextTags.splice(addedIndex, 0, ...nextTags.splice(removedIndex, 1));
        setTags(nextTags);
      }}
      onSelect={handleOnSelect}
      onRemoveTag={handleOnRemoveTag}
    />
  );
};
```

## Common Use Case Examples

### Enter contact emails
- description: Multiselect input can be useful for entering contacts or emails. If combined with advanced list item props, multiselect can provide explicit information, therefore, making multiple keyboard entries easier.
- example:
```jsx
() => {
  const [value, setValue] = React.useState('');
  const [tags, setTags] = React.useState([]);

  const contacts = [
    { name: 'River Watts', email: 'riverw@wix.com', id: 1 },
    { name: 'Jesse Neimus', email: 'jessen@wix.com', id: 2 },
    { name: 'Morgan James', email: 'morganj@wix.com', id: 3 },
    { name: 'Reese Whiteman', email: 'reesew@wix.com', id: 4 },
  ];

  const options = contacts.map((contact) => ({
    ...contact,
    ...listItemSelectBuilder({
      prefix: (
        <Avatar
          size="size30"
          imgProps={{ src: `AvatarExample${contact.id}.jpg` }}
        />
      ),
      id: contact.id,
      title: contact.name,
      subtitle: contact.email,
    }),
  }));

  const handleOnSelect = (option) => {
    const { name, email, id } = option;
    setTags([...tags, { id, label: name ? `${email} (${name})` : email }]);
  };

  const handleOnRemoveTag = (tagId) =>
    setTags(tags.filter((currTag) => currTag.id !== tagId));

  const handleOnChange = (event) => setValue(event.target.value);

  const predicate = (option) =>
    (option.name + option.email).toLowerCase().includes(value.toLowerCase());

  return (
    <MultiSelect
      value={value}
      options={options}
      tags={tags}
      onChange={handleOnChange}
      onSelect={handleOnSelect}
      onRemoveTag={handleOnRemoveTag}
      placeholder="Start typing a name to find a match"
      predicate={predicate}
    />
  );
};
```
