Logo

Combobox

Searchable single and multi-value selection with composable slots.

Preview

Usage

TS

import { FrComboboxModule } from '@frame-ui-ng/components/combobox';

HTML

<div frCombobox autoHighlight showClear>
  <input frComboboxInput placeholder="Search frameworks" />

  <button frComboboxClear aria-label="Clear selection">
    <ng-icon name="tablerX" size="14" />
  </button>

  <ng-template frComboboxContent>
    <div frComboboxPanel>
      <p frComboboxEmpty>No frameworks found.</p>

      <div frComboboxCollection>
        <section frComboboxGroup>
          <p frComboboxLabel>Frontend</p>

          <div frComboboxList>
            <button frComboboxItem value="next" label="Next.js">
              <span frComboboxItemIndicator>
                <ng-icon name="tablerCheck" size="14" />
              </span>
              Next.js
            </button>
          </div>
        </section>
      </div>
    </div>
  </ng-template>
</div>

Examples

Searchable input

Use the input variant when people should filter a long option set as they type and clear the current query or selection quickly.

Grouped collections

Use collection, group, and label primitives to break large menus into smaller sections without losing keyboard navigation or filtering behavior.

Trigger button

Use the trigger primitive when the selected value should read more like a compact picker or assignment control than a free-typing search field.

Multiple values with chips

Switch to the chips primitives when a combobox should collect several selected values while keeping search input available in the same field.

Next.js Astro

Invalid state

Use Angular Reactive Forms to drive the invalid state so the combobox reflects real validation rules.

Custom Styling

Override combobox tokens on a local wrapper when a picker needs a different density, a more branded panel, or custom chip styling without changing the combobox structure itself.

Next.js Nuxt

Token Inspector

Hover the control, clear action, panel, option rows, or group labels to inspect the tokens that shape the combobox surface. Click a region to pin the popover while you compare the current values.

Frontend

Design Tokens

Use these CSS custom properties to tune the combobox field, overlay panel, option rows, muted labels, chips, and validation treatment without changing the component markup.

SCSS


  --frame-combobox-control-height: 2.5rem;
  --frame-combobox-control-radius: var(--frame-radius-md);
  --frame-combobox-control-bg: var(--frame-surface);
  --frame-combobox-control-color: var(--frame-surface-foreground);
  --frame-combobox-control-border: var(--frame-border);
  --frame-combobox-control-font-size: 0.875rem;
  --frame-combobox-control-padding-inline: 0.875rem;
  --frame-combobox-control-disabled-bg: color-mix(in srgb, var(--frame-surface) 78%, var(--frame-muted));
  --frame-combobox-control-disabled-color: var(--frame-muted-foreground);
  --frame-combobox-control-disabled-opacity: 0.6;
  --frame-combobox-control-focus-border: color-mix(in srgb, var(--frame-ring) 70%, var(--frame-border));
  --frame-combobox-control-focus-shadow: 0 0 0 3px color-mix(in srgb, var(--frame-ring) 22%, transparent);
  --frame-combobox-control-invalid-border: color-mix(in srgb, var(--frame-destructive) 65%, var(--frame-border));
  --frame-combobox-control-invalid-shadow: 0 0 0 3px color-mix(in srgb, var(--frame-destructive) 14%, transparent);
  --frame-combobox-control-transition-duration: 150ms;
  --frame-combobox-clear-offset: 0.375rem;
  --frame-combobox-panel-max-height: min(18rem, 50vh);
  --frame-combobox-panel-radius: var(--frame-radius-md);
  --frame-combobox-panel-bg: var(--frame-surface);
  --frame-combobox-panel-color: var(--frame-surface-foreground);
  --frame-combobox-panel-border: var(--frame-border);
  --frame-combobox-panel-shadow: var(--frame-shadow-md);
  --frame-combobox-panel-padding: 0.25rem;
  --frame-combobox-motion-duration: 140ms;
  --frame-combobox-motion-easing: cubic-bezier(0.16, 1, 0.3, 1);
  --frame-combobox-motion-distance: 0.2rem;
  --frame-combobox-motion-scale: 0.98;
  --frame-combobox-list-gap: 0.125rem;
  --frame-combobox-item-height: 2rem;
  --frame-combobox-item-gap: 0.5rem;
  --frame-combobox-item-radius: calc(var(--frame-radius-md) - 0.125rem);
  --frame-combobox-item-font-size: 0.875rem;
  --frame-combobox-item-padding: 0.375rem 0.5rem 0.375rem 2rem;
  --frame-combobox-item-indicator-offset: 0.625rem;
  --frame-combobox-item-disabled-opacity: 0.5;
  --frame-combobox-muted-font-size: 0.8125rem;
  --frame-combobox-muted-padding: 0.5rem;
  --frame-combobox-separator-margin: 0.25rem -0.25rem;
  --frame-combobox-separator-bg: var(--frame-border);
  --frame-combobox-chip-gap: 0.25rem;
  --frame-combobox-chip-height: 1.375rem;
  --frame-combobox-chip-radius: 999px;
  --frame-combobox-chip-bg: var(--frame-primary);
  --frame-combobox-chip-color: var(--frame-primary-foreground);
  --frame-combobox-chip-font-size: 0.75rem;
  --frame-combobox-chip-font-weight: 600;
  --frame-combobox-chip-padding-block: 0.1875rem;
  --frame-combobox-chip-padding-inline: 0.625rem 0.25rem;
  --frame-combobox-chip-remove-size: 1rem;
  --frame-combobox-chip-remove-radius: 999px;
  --frame-combobox-chip-remove-bg: color-mix(in srgb, currentColor 12%, transparent);
  --frame-combobox-chip-remove-hover-bg: color-mix(in srgb, currentColor 20%, transparent);
  --frame-combobox-chips-gap: 0.375rem;
  --frame-combobox-chips-padding: 0.375rem;
  --frame-combobox-chips-input-min-width: 8rem;
  --frame-combobox-chips-input-padding: 0.25rem;
  --frame-combobox-error-color: var(--frame-destructive);
  --frame-combobox-error-font-size: 0.8125rem;