Combobox

Things left to do:

Single Select Editable Combobox Examples

List Autocomplete Combobox

“list” autocomplete will show the list and guide the user to the item in the list based on the string provided in the input.

Inline Autocomplete Combobox

Inline autocomplete will prefill the closest match for the user.

Autocomplete List & Inline Combobox (both)

A list + inline (“both”) combobox will both highlight the value in the input and select the item in the combobox list.

Editable Combobox no autocomplete with values

A combobox with autocomplete="off" is editable, but will not guide the user along the popup list of options and will not prefill the input. If you use value attributes on the options, and the text matches, it will use the value.

Editable Combobox no autocomplete

A combobox with autocomplete="off" is editable, but will not guide the user along the popup list of options and will not prefill the input.

Filtering Results

When using autocomplete, you may want to filter results that don’t match and only show matching results.

Disabling options

Options can be disabled by passing the disabled attribute to the <role-option> element.

Multiple select comboboxes

Multiple combobox with value-type="formdata" and autocomplete="both"

Multiple combobox with autocomplete="both"

Multiple combobox with filtered results

Multiple combobox hiding already selected options from the list

We can hide options from the list that have already been selected by doing:

<role-combobox hide-selected-options>

Editable Multi select combobox with autocomplete “off”

Editable Multi select combobox with filtering

Using a “manual” selection type + allow-custom-values for multi-select.

Using a “manual” selection type for multiple selection with filtering

There are 2 types of multiple-selection-types. automatic, which is the default, and manual, which requires manually selecting the option and will not automatically add it to the list of selected options.

API Reference

Imports

Script
HTML
<!-- Auto registers as <role-combobox> -->
<script type="module" src="https://cdn.jsdelivr.net/npm/role-components/exports/components/combobox/combobox-register.js"></script>
CDN
HTML
<script type="module">
  // Auto registers as <role-combobox>
  import "https://cdn.jsdelivr.net/npm/role-components/exports/components/combobox/combobox-register.js"

  // Manual Register
  import RoleCombobox from "https://cdn.jsdelivr.net/npm/role-components/exports/components/combobox/combobox.js"
  RoleCombobox.define()
  // => Registers as <role-combobox>
</script>
Bundler
JavaScript
// Auto registers as <role-combobox>
import "role-components/exports/components/combobox/combobox-register.js"

// Manual Register
import RoleCombobox "role-components/exports/components/combobox/combobox.js"
RoleCombobox.define()
// => Registers as <role-combobox>

Slots

Name Description
prefix

The prefix slot before the trigger

trigger

the input / form control to use to “trigger” the combobox

suffix

the suffix slot for after the trigger.

options

the slot holding all possible <role-option> elements

no-result

The slot that appears when no results are found and show-empty-results is provided.

Attributes

Name Description Reflects Type Default
[Attribute + Property]
placement

The preferred placement of the popover. Note that the actual placement will vary as configured to keep the panel inside of the viewport.

'top' | 'top-start' | 'top-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'right' | 'right-start' | 'right-end' | 'left' | 'left-start' | 'left-end'
-
[Attribute + Property]
current-placement

The currentPlacement property / current-placement attribute are where Floating UI actually positions the popup.

'top' | 'top-start' | 'top-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'right' | 'right-start' | 'right-end' | 'left' | 'left-start' | 'left-end' | null
-
[Attribute + Property]
strategy

Determines how the popover is positioned. Because you native “popover” API uses a fixed strategy, we use it as the default.

Strategy
-
[Attribute + Property]
distance

The distance in pixels from which to offset along the “main axis”. Usually its equivalent to offsetY

number
-
[Attribute + Property]
skidding

The distance in pixels from which to offset along the “cross axis”. Usually its equivalent to offsetX.

number
-
[Attribute + Property]
arrow

Attaches an arrow to the popover. The arrow’s size and color can be customized using the --arrow-size and --background-color custom properties. For additional customizations, you can also target the arrow using ::part(arrow) in your stylesheet.

boolean
-
[Attribute + Property]
arrow-placement

The placement of the arrow. The default is anchor, which will align the arrow as close to the center of the anchor as possible, considering available space and arrow-padding. A value of start, end, or center will align the arrow to the start, end, or center of the popover instead.

'start' | 'end' | 'center' | 'anchor'
-
[Attribute + Property]
arrow-padding

The amount of padding between the arrow and the edges of the popover. If the popover has a border-radius, for example, this will prevent it from overflowing the corners.

number
-
[Attribute + Property]
flip

When set, placement of the popover will flip to the opposite site to keep it in view. You can use flipFallbackPlacements to further configure how the fallback placement is determined.

boolean
-
[Attribute + Property]
flip-fallback-placements

If the preferred placement doesn’t fit, popover will be tested in these fallback placements until one fits. Must be a string of any number of placements separated by a space, e.g. “top bottom left”. If no placement fits, the flip fallback strategy will be used instead.

string
-
[Attribute + Property]
flip-fallback-strategy

When neither the preferred placement nor the fallback placements fit, this value will be used to determine whether the popover should be positioned using the best available fit based on available space or as it was initially preferred.

'best-fit' | 'initial'
-
[Attribute + Property]
flip-padding

The amount of padding, in pixels, to exceed before the flip behavior will occur.

number
-
[Attribute + Property]
shift

Moves the popover along the axis to keep it in view when clipped.

boolean
-
[Attribute + Property]
shift-padding

The amount of padding, in pixels, to exceed before the shift behavior will occur.

number
-
[Attribute + Property]
auto-size

When set, this will cause the popover to automatically resize itself to prevent it from overflowing.

null | 'horizontal' | 'vertical' | 'both'
-
[Attribute + Property]
sync

Syncs the popover’s width or height to that of the anchor element.

null | 'width' | 'height' | 'both'
-
[Attribute + Property]
auto-size-padding

The amount of padding, in pixels, to exceed before the auto-size behavior will occur.

number
-
[Attribute + Property]
hover-bridge

When a gap exists between the anchor and the popover element, this option will add a “hover bridge” that fills the gap using an invisible element. This makes listening for events such as mouseenter and mouseleave more sane because the pointer never technically leaves the element. The hover bridge will only be drawn when the popover is active.

boolean
-
[Attribute]


[Property]
multiple

Whether to allow multiple selections.

boolean false
[Attribute]


[Property]
value
-
-
-
[Attribute]


[Property]
wrap-selection
-
boolean false
[Attribute]


[Property]
search-buffer-delay

Delay before the search buffer returns to an empty string

number 600
[Attribute]


[Property]
value-type

Used for multiple selects. You can either have a string, or submit as multiple parameters in FormData like a native <select>. The default is a “string”.

"formdata" | "string" "string"
[Attribute]


[Property]
autocomplete

Any autocompletes of type "off", "inline", "list", or "both" will automatically make the triggerElement editable.

'' | "off" | "inline" | "list" | "both" ''
[Attribute]


[Property]
editable

If true, the <input> element provided is not treated as readonly, and rather as an editable input. This can be omitted if you use any of the possible autocomplete attributes. Do not use this to check if the combobox is editable. instead, use this.isEditable to check if the triggerElement is editable.

boolean false
[Attribute]


[Property]
filter-results

Whether or not to filter results based on what is typed into the combobox.

boolean false
[Attribute]


[Property]
hide-selected-options

Will hide already selected options via display: none;, from the selectable list of options in a combobox.

boolean false
[Attribute]


[Property]
delimiter

Used for multiple select comboboxes that use value-type="string". The default is a comma.

string ','
[Attribute]


[Property]
spacer

Used for multiple select comboboxes that use value-type="string". The default is a space.

string " "
[Attribute]


[Property]
show-empty-results

If true, or show-empty-results attribute is present, it will show the “no-results-found” slot.

boolean false
[Attribute]


[Property]
allow-custom-values

When multiple-selection-type="manual", this allows users to see a custom <role-option> with the current value inside the combobox.

boolean false
[Attribute]


[Property]
multiple-selection-type

If set to “automatic” (default), it will be one single text input with delimited values. If set to “manual”, you will only enter 1 option at a time, and then need to confirm selection, and then the input will clear, and then you will add another selection.

"automatic" | "manual" "automatic"

Events

Name Description
change
-
input
-
role-selected

The event that fires when an option is selected.

Functions

Name Description Parameters
focus()
-
args
handleInput()
-
event: InputEvent
splitValue()
-
value: string
handleMultipleEditableInput()
-
event: InputEvent, triggerElement: HTMLButtonElement | HTMLInputElement
__shouldSelectSuggestedOption()
-
finalString: string, event: InputEvent
__findSuggestedOption()
-
finalString: string, event: InputEvent, newSelectedOptions: typeof this.selectedOptions
__handleConfirmInput()
-
event: InputEvent, triggerElement: HTMLButtonElement | HTMLInputElement
__handleAutomaticInput()
-
event: InputEvent, triggerElement: HTMLButtonElement | HTMLInputElement
handleSingleEditableInput()
-
event: InputEvent, triggerElement: typeof this.triggerElement
optionElementToOptionObject()
-
el: RoleOption
handleOptionFocus()
-
event: {target: null | RoleOption}
handleInputClick()
-
e: Event
handleOutsideClick()
-
e: Event
assignRandomId()

Users dont always provide ids on elements, and we need to make sure the id isn’t already taken.

el: HTMLElement, id
updateListboxElement()

Adds proper attributes to the slotted listbox element

-
handleInputFocus()
-
e: Event
updateTriggerElement()

Adds proper attributes to the slotted input element

-
renderSelectedOptions()
-
-
liveRegionStatus()
-
-
formResetCallback()
-
-
setCurrent()
-
option: OptionObject
removeCurrent()
-
option: OptionObject
findOptionElement()
-
option: OptionObject
handleOptionClick()
-
evt: PointerEvent
handleOptionHover()
-
evt: Event
handleKeyUp()

Reset range when shiftKey goes up

evt: KeyboardEvent
handleKeyDown()
-
evt: KeyboardEvent
handleCurrentOptionSelected()
-
-
selectFromClosestSelectedToCurrent()

Finds the closest selected option prior to the current option

-
selectFromRangeStartToCurrent()
-
-
selectRange()

Selects all options in a range and deselects all options not in the range

{ from, to }, options: Range
selectFromStartToCurrent()
-
startIndex: number
selectFromCurrentToEnd()
-
endIndex: number
escapeRegexChars()

Escape characters for regex matching.

str: string
stringToRegex()
-
str: string
focusElementFromSearchBuffer()
-
-
select()
-
option: OptionObject
deselect()
-
option: OptionObject
selectAll()

Mark every element with [aria-selected=”true”]

-
deselectAll()

Mark every element with [aria-selected=”false”]

updateOptions
toggleSelected()
-
option: OptionObject
focusCurrent()
-
-
updateLiveRegion()
-
-
focusAt()
-
index: number
focusNext()
-
-
focusPrevious()
-
-
focusFirst()
-
-
focusLast()
-
-
scrollOptionIntoView()
-
selectedOption: OptionObject
scrollOptionElementIntoView()
-
optionElement: HTMLElement
isSelected()
-
option: OptionObject
updateOptions()
-
-
updateMultipleValue()

Updates formData / combobox.value

force: boolean
updateCustomOption()
-
-
updateTriggerElementTextContentAndValue()
-
str: string
getOrAssignId()

Assign a random UUID with a prefix if no id is found. Will return the “id” of the element if its already assigned.

prefix: string, force: boolean
getTextDirection()
-
-
debounce()
-
callback: (...args: any[]) => any, options: { key: any, wait: number }
setAria()
-
key: T, value: ARIAMixin[T]

Parts

Name Description
selected-options

A list of selected options that are buttons a user can click to remove in a multiple select.

selected-option

a list item containing a button to remove a selected option in a multiple select.

remove-button

A button for removing a selected option in a multiple select.

selected-option-display-value

The displayed text for the selected option

remove-icon

The icon to use for the “x” next to the selected option.

base

The base div wrapping everything

anchored-region

The “popup” that will contain the list of possible options.

popover

forwarded from role-anchored-region

popover--active

forwarded from role-anchored-region

popover--fixed

forwarded from role-anchored-region

popover--has-arrow

forwarded from role-anchored-region

arrow

forwarded from role-anchored-region

hover-bridge

forwarded from role-anchored-region

hover-bridge--visible

forwarded from role-anchored-region

anchor

the div wrapping the trigger used for “anchoring” the popup.

listbox

the container holding the options