#Overview
Dropdowns are used with Forms (Code).
Show codeHide code
export const DropdownFieldDemo = () => {
const form = useForm<{ fruits: ISelectOption<string> | null }>();
return (
<form onSubmit={form.handleSubmit(() => {})}>
<DropdownField
form={form}
name="fruits"
label="Favourite Fruit"
items={fruitOptions}
options={{
required: {
value: true,
message: "Please provide a value",
},
}}
/>
<ButtonGroup>
<Button onClick={() => form.reset()}>Reset value</Button>
<Button variant="primary" type="submit">
Send
</Button>
</ButtonGroup>
</form>
);
};
| Name | Type | Default | Description |
|---|---|---|---|
| form * | UseFormReturn<TFieldValues> | - | The connected form that the form field is part of |
| items * | Array<ISelectOption> | - | The selectable items |
| value * | ISelectOption | null | undefined | - | The value of the input field |
| dialogDescription | string | - | The description that is shown in the dialog option |
| dialogLabel | ReactNode | - | The title that is shown in the dialog option |
| disabled | boolean | - | If true, the input field is disabled |
| hasError | boolean | - | If true, turns the border red |
| helpText | ReactNode | - | A help text that can be displayed below the dropdown field |
| hideHelpAndValidation | boolean | - | Hides the help text and validation message |
| id | string | - | The id of the dropdown |
| labelOptionalAppendix | ReactNode | - | Marker inside the label, when the field is optional |
| labelRequiredAppendix | ReactNode | - | Marker inside the label, when the field is required |
| listboxOffset | number |
| |
| listboxPlacement | "end" | "start" |
| |
| name | string | - | The name of the dropdown |
| noWrap | boolean | - | |
| onBlur | FocusEventHandler<HTMLDropdownElement> | - | Callback the field is blurred |
| onChange | ChangeEventHandler<HTMLDropdownElement> | - | Callback when the selected item changes |
| onMenuClose | () => void | - | Callback when the menu closes |
| onMenuOpen | () => void | - | Callback when the menu opens |
| onSelect | ChangeEventHandler<HTMLDropdownElement> | - | Callback when the selected item changes |
| options | UseControllerProps<TFieldValues, TFieldName>["rules"] |
| The options that can be set for the registration of the field |
| placeholder | string | - | A hint for the expected value |
| ref | Ref<HTMLButtonElement> | - | Ref of the dropdown |
#Interface ISelectOption
The interface ISelectOption<T> is used to define the items of the dropdown. It is generic typed and will receive the interface of your actual data definition.
It has the following properties:
| Name | Type | Default | Description |
|---|---|---|---|
| label * | string | - | The label of the option |
| value * | T | - | The value of the option |
| description | string | - | Description underneath the label on mobile viewports |
| disabled | boolean | - | If the option is disabled |
| icon | ReactNode | - | Icon in front of the label |
#Customize item rendering
You can add an additional icon and a description for mobile viewports to the dropdown items.
import { LightModeIcon } from "@blocks/icons/LightMode";
import type { ISelectOption } from "@segments/dropdown";
const items: ISelectOption[] = [
{
label: "Light",
description: "Always use the light design",
value: "light",
icon: <LightModeIcon />,
},
// ...
];
#Styling
Dropdowns are generic components, generic props are exposed for each to style them and preserve their type.
import { Dropdown, type GenericDropdownProps } from "@segments/dropdown";
import { type GenericYakComponentOf, styled } from "next-yak";
const StyledDropdown = styled(Dropdown)`
margin-bottom: ${spacing[8]};
` as GenericYakComponentOf<GenericDropdownProps>;
#Autocomplete Dropdown
A Dropdown that lets you search for items by keyboard input.
Show codeHide code
export const AutocompleteDropdownFieldDemo = () => {
const form = useForm<{ fruits: ISelectOption<string> | null }>();
const [result, setResult] = useState<ISelectOption<string> | null>(null);
return (
<>
<form
onSubmit={form.handleSubmit(() => {
setResult(form.getValues().fruits);
})}
>
<AutocompleteDropdownField
clearable
form={form}
name="fruits"
label="Favourite Fruit"
items={fruitOptions}
options={{
required: {
value: true,
message: "Please provide a value",
},
}}
/>
<ButtonGroup>
<Button onClick={() => form.reset()}>Reset value</Button>
<Button variant="primary" type="submit">
Send
</Button>
</ButtonGroup>
</form>
{result && <div>{`Submitted: ${result.value}`}</div>}
</>
);
};
| Name | Type | Default | Description |
|---|---|---|---|
| form * | UseFormReturn<TFieldValues> | - | The connected form that the form field is part of |
| items * | Array<ISelectOption> | - | The selectable items |
| value * | ISelectOption | null | undefined | - | The value of the input field |
| clearable | boolean | - | If a selected item can be cleared again, default false |
| createNewValueMessage | string | - | The label that is shown above the creatable option |
| dialogLabel | ReactNode | - | The title that is shown in the dialog option |
| disabled | boolean | - | If true, the input field is disabled |
| hasError | boolean | - | If true, turns the border red |
| helpText | ReactNode | - | A help text that can be displayed below the input field |
| hideHelpAndValidation | boolean | - | Hides the help text and validation message |
| id | string | - | The id of the dropdown |
| labelOptionalAppendix | ReactNode | - | Marker inside the label, when the field is optional |
| labelRequiredAppendix | ReactNode | - | Marker inside the label, when the field is required |
| name | string | - | The name of the dropdown |
| noItemsMessage | string | - | The message that will show when there are no results left after filtering |
| noWrap | boolean | - | |
| onBlur | ChangeEventHandler<HTMLDropdownElement> | - | Callback when the dropdown is blurred |
| onChange | ChangeEventHandler<HTMLDropdownElement> | - | Callback when the selected item changes and when dropdown changes |
| onCreateItem | (inputValue: string) => Promise<ISelectOption | undefined | void> | - | Async callback to create new items. An option for that is shown when the user types something that is not present as an item |
| onInputValueChange | (inputValue: string) => Promise<void> | - | An optional callback to filter items asynchronous - useful to fetch an API again |
| onMenuClose | () => void | - | Callback when the menu closes |
| onMenuOpen | () => void | - | Callback when the menu opens |
| onSelect | ChangeEventHandler<HTMLDropdownElement> | - | Callback when the selected item changes |
| options | UseControllerProps<TFieldValues, TFieldName>["rules"] |
| The options that can be set for the registration of the field |
| placeholder | string | - | A hint for the expected value |
| ref | Ref<HTMLButtonElement> | - | Ref of the dropdown |
| showDialogBackButton | boolean | - | if true, the back button is shown in the dialog on mobile and tablet viewports |
#Creating new items
When you pass an onCreateItem callback function, users can create and add new items to the dropdown that don't exist in the original list. This is useful for fields where users might need custom values.
Show codeHide code
export const CreatableAutocompleteDropdownFieldDemo = () => {
const [creatableOptions, setCreatableOptions] = useState(fruitOptions);
const [result, setResult] = useState<ISelectOption<string> | null>(null);
const form = useForm<{ fruits: ISelectOption<string> }>();
return (
<>
<form
onSubmit={form.handleSubmit(() => {
setResult(form.getValues().fruits);
})}
>
<AutocompleteDropdownField
form={form}
name="fruits"
label="Favourite Fruit"
items={creatableOptions}
onCreateItem={async (inputValue: string) => {
const newValue = { label: inputValue, value: inputValue };
setCreatableOptions([...fruitOptions, newValue]);
return newValue;
}}
options={{
required: {
value: true,
message: "Please provide a value",
},
}}
/>
<Button type="submit">Send</Button>
</form>
{result && <div>{`Submitted: ${result.value}`}</div>}
</>
);
};
#Lazy loading items
If you're using an <AutocompleteDropdown /> or <MultiselectDropdown />, then you can implement the callback onInputValueChange to filter/fetch items.
This is useful for data sources that can't be fully loaded initially.
So you can use this callback to fetch the items with a new API request. The callback will be called on every keystroke - so it is recommended
to implement this with a debounce function to avoid too many requests.
#Multiselect Dropdown
A Dropdown that let you select multiple items and also search for them by keyboard input.
Show codeHide code
export const MultiSelectDropdownFieldDemo = () => {
const form = useForm<{ fruits: ISelectOption[] }>();
const [result, setResult] = useState<ISelectOption[] | null>(null);
return (
<>
<form
onSubmit={form.handleSubmit(() => {
setResult(form.getValues().fruits);
})}
>
<MultiSelectDropdownField
form={form}
name="fruits"
label="Favourite Fruit"
items={fruitOptions}
options={{
required: {
value: true,
message: "Please provide a value",
},
}}
/>
<ButtonGroup>
<Button onClick={() => form.reset()}>Reset value</Button>
<Button variant="primary" type="submit">
Send
</Button>
</ButtonGroup>
</form>
{result && (
<div>{`Submitted: ${result.map((item) => item.value).join(", ")}`}</div>
)}
</>
);
};
| Name | Type | Default | Description |
|---|---|---|---|
| form * | UseFormReturn<TFieldValues> | - | The connected form that the form field is part of |
| items * | Array<ISelectOption> | - | The selectable items |
| value * | Array<ISelectOption> | null | undefined | - | The value of the mutli select dropdown |
| createNewValueMessage | string | - | The label that is shown above the creatable option |
| dialogLabel | ReactNode | - | The title that is shown in the dialog option |
| disabled | boolean | - | If true, the input field is disabled |
| hasError | boolean | - | If true, turns the border red |
| helpText | ReactNode | - | A help text that can be displayed below the input field |
| hideHelpAndValidation | boolean | - | Hides the help text and validation message |
| id | string | - | The id of the dropdown |
| labelOptionalAppendix | ReactNode | - | Marker inside the label, when the field is optional |
| labelRequiredAppendix | ReactNode | - | Marker inside the label, when the field is required |
| name | string | - | The name of the dropdown |
| noItemsMessage | string | - | The message that will show when there are no results left after filtering |
| noOptionsMessage | string | - | The message that will show when all items have been selected |
| noWrap | boolean | - | |
| onBlur | FocusEventHandler<HTMLMultiSelectDropdownElement> | - | Callback when the input field is blurred |
| onChange | ChangeEventHandler<HTMLMultiSelectDropdownElement> | - | Callback when the selected item changes and when input changes |
| onCreateItem | (inputValue: string) => Promise<ISelectOption | undefined | void> | - | Async callback to create new items. An option for that is shown when the user types something that is not present as an item |
| onInputValueChange | (inputValue: string) => Promise<void> | - | An optional callback to filter items asynchronous - useful to fetch an API again |
| options | UseControllerProps<TFieldValues, TFieldName>["rules"] |
| The options that can be set for the registration of the field |
| placeholder | string | - | A hint for the expected value |
| ref | Ref<HTMLButtonElement> | - | the ref of the mutli select dropdown |
| showDialogBackButton | boolean | - | if true, the back button is shown in the dialog on mobile and tablet viewports |
#Outside of a form
#Dropdown
| Name | Type | Default | Description | Controls |
|---|---|---|---|---|
| items * | Array<ISelectOption> | - | The selectable items | - |
| value * | ISelectOption | null | undefined | - | The value of the input field | - |
| dialogDescription | string | - | The description that is shown in the dialog option | |
| dialogLabel | ReactNode | - | The title that is shown in the dialog option | - |
| disabled | boolean | - | If true, the input field is disabled | |
| hasError | boolean | - | If true, turns the border red | |
| id | string | - | The id of the dropdown | |
| listboxOffset | number |
| ||
| listboxPlacement | "end" | "start" |
| ||
| name | string | - | The name of the dropdown | |
| onBlur | FocusEventHandler<HTMLDropdownElement> | - | Callback the field is blurred | - |
| onChange | ChangeEventHandler<HTMLDropdownElement> | - | Callback when the selected item changes | - |
| onMenuClose | () => void | - | Callback when the menu closes | - |
| onMenuOpen | () => void | - | Callback when the menu opens | - |
| onSelect | ChangeEventHandler<HTMLDropdownElement> | - | Callback when the selected item changes | - |
| placeholder | string | - | A hint for the expected value | |
| ref | Ref<HTMLButtonElement> | - | Ref of the dropdown | - |
#Autocomplete Dropdown
| Name | Type | Default | Description | Controls |
|---|---|---|---|---|
| items * | Array<ISelectOption> | - | The selectable items | - |
| value * | ISelectOption | null | undefined | - | The value of the input field | - |
| clearable | boolean | - | If a selected item can be cleared again, default false | |
| createNewValueMessage | string | - | The label that is shown above the creatable option | |
| dialogLabel | ReactNode | - | The title that is shown in the dialog option | - |
| disabled | boolean | - | If true, the input field is disabled | |
| hasError | boolean | - | If true, turns the border red | |
| id | string | - | The id of the dropdown | |
| name | string | - | The name of the dropdown | |
| noItemsMessage | string | - | The message that will show when there are no results left after filtering | |
| onBlur | ChangeEventHandler<HTMLDropdownElement> | - | Callback when the dropdown is blurred | - |
| onChange | ChangeEventHandler<HTMLDropdownElement> | - | Callback when the selected item changes and when dropdown changes | - |
| onCreateItem | (inputValue: string) => Promise<ISelectOption | undefined | void> | - | Async callback to create new items. An option for that is shown when the user types something that is not present as an item | - |
| onInputValueChange | (inputValue: string) => Promise<void> | - | An optional callback to filter items asynchronous - useful to fetch an API again | - |
| onMenuClose | () => void | - | Callback when the menu closes | - |
| onMenuOpen | () => void | - | Callback when the menu opens | - |
| onSelect | ChangeEventHandler<HTMLDropdownElement> | - | Callback when the selected item changes | - |
| placeholder | string | - | A hint for the expected value | |
| ref | Ref<HTMLButtonElement> | - | Ref of the dropdown | - |
| showDialogBackButton | boolean | - | if true, the back button is shown in the dialog on mobile and tablet viewports |
#Multiselect Dropdown
| Name | Type | Default | Description | Controls |
|---|---|---|---|---|
| items * | Array<ISelectOption> | - | The selectable items | - |
| value * | Array<ISelectOption> | null | undefined | - | The value of the mutli select dropdown | - |
| createNewValueMessage | string | - | The label that is shown above the creatable option | |
| dialogLabel | ReactNode | - | The title that is shown in the dialog option | - |
| disabled | boolean | - | If true, the input field is disabled | |
| hasError | boolean | - | If true, turns the border red | |
| id | string | - | The id of the dropdown | |
| name | string | - | The name of the dropdown | |
| noItemsMessage | string | - | The message that will show when there are no results left after filtering | |
| noOptionsMessage | string | - | The message that will show when all items have been selected | |
| onBlur | FocusEventHandler<HTMLMultiSelectDropdownElement> | - | Callback when the input field is blurred | - |
| onChange | ChangeEventHandler<HTMLMultiSelectDropdownElement> | - | Callback when the selected item changes and when input changes | - |
| onCreateItem | (inputValue: string) => Promise<ISelectOption | undefined | void> | - | Async callback to create new items. An option for that is shown when the user types something that is not present as an item | - |
| onInputValueChange | (inputValue: string) => Promise<void> | - | An optional callback to filter items asynchronous - useful to fetch an API again | - |
| placeholder | string | - | A hint for the expected value | |
| ref | Ref<HTMLButtonElement> | - | the ref of the mutli select dropdown | - |
| showDialogBackButton | boolean | - | if true, the back button is shown in the dialog on mobile and tablet viewports |
#Colors
- Token name
LABEL_TEXT#0009#fffb#0009#fffbFIELD_BORDER#bbb#fff4#bbb#fff4VALUE_TEXT#0004#fff4#0004#fff4ICONAFTER_BACKGROUND#000d#fffb#000d#fffbCHEVRON#000d#fffb#000d#fffbICON_SHAPE#000d#fffb#000d#fffbFIELD_BACKGROUND#fff#111#fff#111HELP_TEXT#0009#fffb#0009#fffbLABEL_TEXT_FOCUS#0009#fffb#0009#fffbFIELD_BORDER_FOCUS#555#fff#059#fffVALUE_TEXT_FOCUS#0004#fff4#0004#fff4ICONAFTER_BACKGROUND_FOCUS#000d#fffb#000d#fffbFIELD_BACKGROUND_FOCUS#fff#111#fff#111HELP_TEXT_FOCUS#0009#fffb#0009#fffbLABEL_TEXT_DISABLED#0009#fffb#0009#fffbFIELD_BACKGROUND_DISABLED#0000#fff1#0000#fff1FIELD_BORDER_DISABLED#0001#fff1#0001#fff1VALUE_TEXT_DISABLED#0004#fff4#0004#fff4ICONAFTER_BACKGROUND_DISABLED#0004#fff4#0004#fff4CHEVRON_DISABLED#0004#fff4#0004#fff4ICON_SHAPE_DISABLED#0004#fff4#0004#fff4HELP_TEXT_DISABLED#0009#fffb#0009#fffbLABEL_TEXT_ERROR#0009#fffb#0009#fffbFIELD_BORDER_ERROR#f75#f75#e02#f55VALUE_TEXT_ERROR#0004#fff4#0004#fff4ICONAFTER_BACKGROUND_ERROR#000d#fffb#000d#fffbCHEVRON_ERROR#000d#fffb#000d#fffbICON_SHAPE_ERROR#000d#fffb#000d#fffbFIELD_BACKGROUND_ERROR#fff#111#fff#111HELP_TEXT_ERROR#c42#f75#e02#f44LABEL_TEXT_FILLED#0009#fffb#0009#fffbFIELD_BORDER_FILLED#555#fff#059#fffVALUE_TEXT_FILLED#000#fff#000#fffICONAFTER_BACKGROUND_FILLED#000d#fffb#000d#fffbCHEVRON_FILLED#000d#fffb#000d#fffbICON_SHAPE_FILLED#000d#fffb#000d#fffbFIELD_BACKGROUND_FILLED#fff#111#fff#111HELP_TEXT_FILLED#0009#fffb#0009#fffb