- Combobox includes Default, Hover, Focus, Focus Visible, and Locked states.
- Focus Visible is triggered by keyboard navigation using the Tab key.
- Focus is shown while the Combobox is open with a mouse click.
- The Invalid validation state can only have Default and Hover states. When the user clicks on an Invalid Combobox, the validation is cleared and the component transitions to the Focus state. Pressing Tab instead transitions it to the Focus Visible state.
Combobox
Molecule
The Combobox Component is a form input component that allows users to either select an option from a predefined list or input a new value if the desired option is not available. It combines the functionality of Select with search and the ability to create new entries. Use this component in scenarios where the list of options may be extensive or incomplete.
Playground
<
Combobox
options
=
"[
{
"text": "Option 1",
"value": 1
},
{
"text": "Option 4",
"value": 4
},
{
"text": "Option 7 gets a longer text for title impl. check",
"value": 7
},
{
"text": "Option 2",
"value": 2
},
{
"text": "",
"value": null
}
]"
stringOptions
=
"[
{
"text": "some option",
"value": "some option"
},
{
"text": "another option",
"value": "you name it"
},
{
"text": "",
"value": null
}
]"
label
=
"Label"
labelCategory
=
"large"
placeholder
=
"Select an option"
hint
=
"will be added"
canNotAddHint
=
"Option can not be added"
noOfOptionsToShow
/>
Anatomy
- Container - contains placeholder text when empty, and the selected or user-input option. The whole area is clickable to display options menu.
- Label - is a Form label component.
- Placeholder, Keyword search or Selected/Input option display - Selected option/s is/are displayed after user made selection. If not, a helpful placeholder (that contains an example input or informative, helping text regarding the input requested) or a keyword search (that indicates that the Combobox component has search feature) is displayed. If the contents of the placeholder or selected option are longer than the width of the container, the text will get truncated.
- Arrow - is a nested Icon component (chevron).
- Dropdown menu - is a nested Option List component. The general rule of thumb is that only 6 to 10 Options should be visible in the Dropdown menu. The rest would be visible when the user scrolls up or down with a scrollbar.
- Option - is one of the options in the Dropdown menu. If the contents of any Option are longer than the width of the container, then the text will get truncated and a Title attribute (a native HTML element like Tooltip) will display user the full text that is being hidden.
- Divider - is an optional element in the dropdown menu to divide Options in groups, for example to visually separate locked Options.
- Hint text - informs user that they can add a new option just by typing in the value and clicking outside the container.
- Action button - is a nested Icon Button component and it is an optional feature for each individual Option in the Dropdown menu of the component. Usually in Combobox it can be used to delete a user-created option from the options list but this behavior shall be customized in the project level.
- Icon (optional) - is a nested Icon component.
- Help text (optional) - is a nested Help text component.
- Scrollbar - is a Scrollbar component nested inside Combobox component. Scrollbar is used only when we have more options than those visible in a dropdown menu.
States
Variants
Display
- Placeholder
- Selected
- Searching/Creating
- When a user inputs a new value and this value doesn’t exist in the options list, then by pressing Enter or by just closing/leaving the component with new input value, user creates a new option — with newly input value — in the Option list.
Menu
- Can be open or closed.
- Clicking outside the component (or pressing Esc) when the dropdown is open, will close the dropdown.
Menu Direction
- Can open Down or Up.
FormLabel
- Show or hide Form Label.
HelpText + Validation
- Show or hide Help Text.
- The Combobox supports two validation states: None and Invalid. When validation is applied, the Help Text communicates the current validation result.
- If the Combobox has informational Help Text and a validation state is triggered, the validation message replaces the original informational message. Validation feedback always takes priority over informational Help Text.
- Combobox does not have a Validated state. Whether the user selects an existing option or creates a new one, the accepted value is immediately reflected in the field — this visual confirmation makes explicit positive validation feedback redundant.
Properties
ts
export interface ComboboxProps<T extends string | number> extends FormLabelOptionalProps {
options: ComboboxOption<T>[];
placeholder?: string;
modelValue: T | null;
hint?: string;
canNotAddHint?: string;
wrongInputTypeHint?: string;
restrictTypeToNumber?: boolean;
icon?: IconName;
noOfOptionsToShow?: number;
groupDisabledOptions?: boolean;
searchOptions?: ComboboxSearchOptions<T>;
sortOptions?: SelectGenericProps<T>['sortOptions'];
/** if set the user input will not be transformed to camelCase for `value` and `id`
* and will not be capitalized for `text`
*/
noNewOptionInputTransform?: boolean;
}
export interface ComboboxOption<T extends string | number> {
text: string | number;
value: T | null;
id?: string;
isDisabled?: boolean;
ignoreSearch?: boolean;
}
export interface ComboboxSearchOptions<T extends string | number> {
caseSensitive?: boolean;
// placeholder?: string;
searchFunction?: (options: ComboboxOption<T>[]) => ComboboxOption<T>[];
}ts
export interface SelectGenericProps<T extends string | number> extends FormLabelOptionalProps {
modelValue: T | null;
options: SelectOptionGeneric<T>[];
placeholder?: string;
disabled?: boolean;
id?: string;
icon?: IconName;
action?: SelectActionGeneric<T>;
// if set to 0, all options will be shown, default: 0
noOfOptionsToShow?: number;
// If true, disabled options will be grouped and shown at the end of the list
groupDisabledOptions?: boolean;
sortOptions?: SortOptions<'alphabetical' | 'numerical'>;
searchOptions?: SearchOptions<T>;
openToTop?: boolean;
}
export interface SortOptions<T extends 'alphabetical' | 'numerical'> {
type: T;
order?: 'asc' | 'ascending' | 'desc' | 'descending';
target?: 'text' | 'value';
ignoreCase?: T extends 'alphabetical' ? boolean : never;
}
export interface SearchOptions<T extends number | string> {
enableSearch: boolean;
caseSensitive?: boolean;
placeholder?: string;
searchFunction?: (options: SelectOptionGeneric<T>[]) => SelectOptionGeneric<T>[];
}ModelValues
For more information on ModelValues please have a look to the Vue's Data Binding section.
ts
const newOptions = defineModel<ComboboxOption<T>[]>('newOptions', { required: true });
const searchString = defineModel<string>('searchString', { required: true });Developer notes
- The container becomes a text input field once clicked. As the user starts typing, the dropdown filters and shows only the filtered options.
- The search by keyword is conducted on sub-string level.
- When a user inputs a new value and this value doesn’t exist in the options list, then by pressing
Enteror by just closing/leaving the component with new input value, user creates a new option in the options list and selects it. - Pressing
Tabwill trigger:focusstate of the component. PressingEnterwhen focused will open the Dropdown menu and usingArrow keyswill browse through the Options while focus stays on the trigger. PressingEnterwhile an option is highlighted will select the highlighted Option, close the Dropdown, and keep focus on the trigger. - Pressing
Tabagain when a Combobox component is focused will navigate and focus the next component in the UI. - Pressing
Shift+Tabwhile browsing the Options will focus the container of the Combobox component back again.
vue
<script setup>
import { computed, ref } from 'vue';
import { Combobox } from '@pohlcon/design-system';
const modelValue = ref('');
const newOptions = ref([]);
const searchString = ref('');
const options = computed(() => ([
{ text: 'Option 1', value: 'option1' },
{ text: 'Option 2', value: 'option2' },
{ text: 'Option 3', value: 'option3' },
]));
</script>
<template>
<Combobox
v-model="modelValue"
v-model:newOptions="newOptions"
v-model:searchString="searchString"
:options="options"
label="Combobox 1"
labelPosition="labelAbove"
placeholder="Select an option"
hint="option will be added"
/>
</template>