Skip to content

Combobox

Usage

Combobox allows users to either select a single option from a list or input a new value if the desired option is not available. This component is similar to Select with search functionality, but with the additional capability of adding new values to the options list. Use this component only when necessary, in dropdowns where there are too many options.

Types

  • Combobox can be either of Number input or Text input types.
  • Form Label (compact) in Combobox component can be placed either Label Up or Label Left, creating two variations of component usage.

Anatomy and Behavior

  1. Container - contains placeholder text when empty, and the selected or user-input option. The whole area is clickable to display options menu.

  2. Label - Is a Form label (compact) component.

  3. Placeholder, Keyword search or Selected option/s 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.

  4. Arrow - is a nested Icon component (chevron)

  5. Dropdown menu - 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.

  6. Option - is one of the options in the Dropdown menu. If the contents of the option are longer than the width of the container, 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.

  7. Divider - is an optional element in the dropdown menu to divide Options in groups, for example to visually separate disabled Options.

  8. Hint Text - informs user that they can add a new option just by typing in the value and clicking outside the container.

  9. Action Button is a nesting Icon Button (compact) 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.

  10. Scrollbar - is a Scrollbar (tiny) component nested inside Combobox component. Scrollbar is used only when we have more options than those visible in in a dropdown menu.

Behavior

  • 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
  • Clicking outside the component when the dropdown is open, will close the dropdown.
  • 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 the newly input value) in the options list and selects it
  • Pressing Tab will trigger :focus state of the component, pressing Enter when focused will open the Dropdown menu and using Arrow keys will browse through the Options in the Dropdown menu. Pressing Enter while an option is highlighted will select the highlighted Option and close the Dropdown
  • Pressing Tab again when a Select component is focused, will navigate and focus the next component in the UI
  • Pressing Shift+Tab while browsing the Options will focus the container of the Select component back again.

States

  • Combobox can be Open or Closed.
  • Container has :hover, :active, :focus, Disabled states in Closed state and only :hover and :active in Open state.
  • Focusing on component (:focus state) opens the dropdown and allows typing.
  • Option within the Dropdown menu can be :hover, :active, :focus, Disabled and Selected.

Gaps and Sizes

Container width: Fill the parent container it is in

Container height: XL+ (always fixed)

Gap between container and dropdown menu: 2XS

Arrow width and height: M

Arrow: Right-aligned

Gap between contents (Placeholder/Selected option and Arrow): max: space between, min: S

Container padding: S

Dropdown menu width: Fills the container width.

Dropdown menu height: Defined by designer

Option width: Fills the dropdown menu width.

Option height: L+

Option Internal vertical padding: XS

Option Internal horizontal padding: S

Divider width: Fill container

Divider height: Unit

Divider vertical padding: XSDivider horizontal padding: S

Hint text bottom padding: XS

Hint text horizontal padding: S

Recommendations for Designers

Minimum container width: 5XL

Tokens

SCSS Variable
Value
$combobox-bgColor
--color-grey-93
$combobox-arrow-color
--bds-brand-primary-color
$combobox-arrow-color--locked
--color-grey-70
$combobox-dropdown-bgColor
--color-grey-93
$combobox-option-color--locked
--color-grey-70
$combobox-option-bgColor--selected
--primary-bgColor-selected
$combobox-option-bgColor--hover
--color-grey-90
$combobox-selected-color
--color-grey-25
$combobox-placeholder-color
--color-grey-70
$combobox-placeholder-color--locked
--color-grey-80
$combobox-outline-color--focus
--color-azure-45
$combobox-outline-color--locked
--color-grey-86
$combobox-divider-color
--color-grey-80
$combobox-hinttext-color
--color-grey-54
$combobox-dropdown-boxShadow
--elevation-4
$combobox-boxShadow
--debossed-1--grey-95
$combobox-boxShadow--hover
--debossed-2--grey-95
$combobox-boxShadow--locked
none
$combobox-padding
--gutter-s

Properties

ts
export interface ComboboxProps<T extends string | number> extends FormLabelOptionalProps, TooltipProps {
  options: ComboboxOption<T>[];
  placeholder?: string;
  disabled?: boolean;
  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>;
}

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.

vue
const newOptions = defineModel<ComboboxOption<T>[]>('newOptions', { required: true });

const searchString = defineModel<string>('searchString', { required: true });

Developer notes

vue
<script>
import { Combobox } from '@pohlcon/design-system';


const modelValue = ref('');
const newOptions = 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"
    labelCategory="compact"
    placeholder= "Select an option"
    hint="option will be added"
  />

</template>
Component on the labelPosition="labelAbove

Component on the labelPosition="labelLeading"

The newOptions modelValue will contain all the new options added by the user:

newOptions=[]