combobox: add stateless mode

This commit is contained in:
Elijah Duffy
2025-07-15 18:35:33 -07:00
parent 1ae9b3a34f
commit c8a7c37635
2 changed files with 17 additions and 13 deletions

View File

@@ -50,6 +50,8 @@
lazy?: boolean;
/** uses a compact layout for the search input with less padding and smaller text */
compact?: boolean;
/** allows the user to select an option without selecting a value (events are still triggered) */
stateless?: boolean;
notFoundMessage?: string;
class?: ClassValue | null | undefined;
use?: () => void;
@@ -77,6 +79,7 @@
loading = false,
lazy = false,
compact = false,
stateless = false,
notFoundMessage = 'No results found',
class: classValue,
use,
@@ -191,6 +194,13 @@
onclose?.(); // trigger onclose event if defined
};
/** updates the value of the combobox and triggers any callbacks, including closing the picker */
const updateValue = (newValue: ComboboxOption) => {
if (!stateless) value = newValue;
closePicker();
onchange?.(newValue);
};
/** action to set the minimum width of the combobox based on the number of options */
const minWidth: Action<HTMLDivElement, { options: ComboboxOption[] }> = (
container,
@@ -290,10 +300,7 @@
export const setValueByString = (searchVal: string) => {
const item = options.find((opt) => opt.value === searchVal);
if (item) {
value = item;
searchValue = '';
closePicker();
onchange?.(item);
updateValue(item);
} else {
console.warn(`Combobox: No option found with value "${searchVal}"`);
}
@@ -393,7 +400,7 @@
aria-label={getLabel(item)}
aria-disabled={item.disabled}
class={[
'picker-item options-center mb-0.5 flex min-h-10 flex-wrap py-2.5 pr-1.5 pl-5',
'mb-0.5 flex min-h-10 flex-wrap items-center py-2.5 pr-1.5 pl-5',
'rounded-sm text-sm capitalize outline-hidden select-none',
'hover:bg-sui-accent-500/30 dark:hover:bg-sui-accent-700/30',
item.value === highlighted?.value && 'bg-sui-accent-500/80 dark:bg-sui-accent-700/80',
@@ -402,10 +409,8 @@
role="option"
onclick={() => {
if (item.disabled) return;
value = item;
closePicker();
updateValue(item);
searchInput?.focus();
onchange?.(item);
}}
onkeydown={() => {}}
tabindex="-1"
@@ -523,14 +528,12 @@
if (e.key === 'Tab' || e.key === 'Enter') {
if (open && highlighted && !highlighted.disabled && highlighted.value !== value?.value) {
value = highlighted;
onchange?.(highlighted);
updateValue(highlighted);
}
if (e.key === 'Enter') {
closePicker();
e.preventDefault();
}
closePicker();
return;
} else if (e.key === 'Escape') {
closePicker();

View File

@@ -136,7 +136,8 @@
<Combobox
loading
label="Loading state combobox"
label="Loading stateless combobox"
stateless
placeholder="Choose..."
options={[
{ value: 'option1', label: 'Option 1' },