Skills — multiple with removable badges

setDefaultChipClass("badge primary") renders each chip as a real .badge. Focus a chip and press Delete/Backspace to remove it.

Autocomplete — a native input that looks like one

An input + datalist sits next to a plain Actual .input — same height, radius, border, focus and typography (search="includes" gives an accent-insensitive substring match).

Plain Actual input
Enhanced combobox

Single select — progressive enhancement

The native <select> stays the value owner. A separate unnamed filter input drives the picker; the placeholder option is never an offer.

Optgroups + fuzzy search

Order-preserving subsequence matching: type bnn and Banana surfaces. Group headers and catalogue order come straight from the native <optgroup>s.

Duplicate values are distinct choices

Three options share value="2". Each is its own chip; the native <select> remains the source of truth and submits the serialized values below.

Submitted values:

[]

States

Disabled, required and invalid are reflected from the native source — submit the form to see the required field turn --danger.

Normal
Disabled
Required
Invalid

Theme bridge

This page adds no Actual CSS package, no compatibility layer and no JS. Fewer than sixty lines of CSS map the combobox --cb-* tokens onto the Actual visible vocabulary.

.actual-combobox {
  --cb-bg: var(--control-default-bg, var(--surface));
  --cb-color: var(--text);
  --cb-border-color: var(--form-invalid-border, var(--border));
  --cb-border-radius: var(--radius);
  --cb-focus-color: var(--focus);
  --cb-muted-color: var(--text-muted);
  --cb-error-color: var(--danger);
  --cb-control-height: var(--control-size);
  --cb-option-min-height: var(--control-size);
}

.actual-combobox :is(.cb-text-control:focus-visible, .cb-control:has(.cb-input:focus-visible)) {
  border-color: var(--form-invalid-border, var(--cb-border-color));
  outline: var(--focus-ring-width) solid var(--form-invalid-border, var(--focus));
  outline-offset: calc(var(--focus-ring-width) * -1);
  box-shadow: var(--control-shadow, none);
}

.actual-combobox :is(.cb-text-control[aria-invalid="true"], .cb-control:has([aria-invalid="true"])) {
  --form-invalid-border: var(--danger);
}

:where(.actual-combobox) combo-box {
  border-radius: var(--cb-border-radius);
}

.actual-combobox :is(.cb-control, .cb-text-control) {
  border-width: var(--border-width);
  border-radius: inherit;
  box-shadow: var(--control-shadow, none);
}

.actual-combobox :is(.cb-control, .cb-text-control):hover {
  border-color: var(--form-invalid-border, var(--control-hover-border, var(--text-subtle)));
}

.cb-popover {
  --cb-picker-bg: var(--surface-raised);
  border-color: var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-popout);
}

.cb-option:is(:hover, [data-active]) {
  background: var(--hover-overlay);
  color: var(--text);
}

.cb-option[aria-selected="true"] {
  background: color-mix(in oklab, var(--surface) var(--soft-bg-mix), var(--primary));
}