Select composes field, dropdown, option, and the native input select directive.

select.ts
import {
  KuiDropdown,
  KuiField,
  KuiOption,
  KuiSelect,
  provideKuiDefaults,
} from '@kikita-labs/ui';

Bind value with Angular signals and keep option markup explicit.

Pick one role for the user

<kui-field label="Role" hint="Pick one role for the user">
  <input kuiSelect [(value)]="role" placeholder="Select a role..." [clearable]="true" />
  <kui-dropdown>
    <div kuiOption value="engineer">Software Engineer</div>
    <div kuiOption value="designer">Designer</div>
    <div kuiOption value="manager">Product Manager</div>
  </kui-dropdown>
</kui-field>

Set multiple when the value is an array. Selected values render as field chips by default.

Software Engineer

Multiple mode renders selected values as chips

<kui-field label="Roles" hint="Multiple mode renders selected values as chips">
  <input
    kuiSelect
    multiple
    [(value)]="roles"
    [kuiLabelFn]="roleLabel"
    [maxVisibleChips]="3"
    placeholder="Select roles..."
    [clearable]="true"
  />
  <kui-dropdown>
    @for (role of roleOptions; track role.value) {
      <div kuiOption [value]="role.value">{{ role.label }}</div>
    }
  </kui-dropdown>
</kui-field>

Select works with object values. Map the selected object to its display text with kuiLabelFn; options keep the object as their value.

Object values are shown through kuiLabelFn

<kui-field label="Role" hint="Object values are shown through kuiLabelFn">
  <input kuiSelect [(value)]="role" [kuiLabelFn]="roleLabel" placeholder="Select a role..." />
  <kui-dropdown>
    @for (role of roles; track role.id) {
      <div kuiOption [value]="role">{{ role.label }}</div>
    }
  </kui-dropdown>
</kui-field>

Default multiple mode renders removable kuiChip values. Use ng-template[kuiSelectValue] only when the selected value needs custom markup, per-item appearance or a different remove affordance. The template receives item, label and remove, and hidden values still collapse into the default +N chip.

Software EngineerDesigner

A kuiSelectValue template replaces the default chip

<kui-field label="Roles" hint="A kuiSelectValue template replaces the default chip">
  <input kuiSelect multiple [(value)]="roles" [kuiLabelFn]="roleLabel" />

  <ng-template kuiSelectValue let-label="label" let-remove="remove">
    <span kuiChip appearance="primary" size="sm">
      <span class="kui-chip-label">{{ label }}</span>
      <button kuiChipRemove type="button" [attr.aria-label]="'Remove ' + label" (click)="remove()">
        x
      </button>
    </span>
  </ng-template>

  <kui-dropdown>
    @for (role of roleOptions; track role.value) {
      <div kuiOption [value]="role.value">{{ role.label }}</div>
    }
  </kui-dropdown>
</kui-field>

Set defaults.select once for the application or for a subtree. Each option resolves as local input > defaults.select.<option> > built-in default.

import { provideKikitaUi } from '@kikita-labs/ui';

export const appConfig: ApplicationConfig = {
  providers: [
    provideKikitaUi({
      defaults: {
        select: {
          /* options below */
        },
      },
    }),
  ],
};
NameTypeDefaultDescription
clearableboolean — When true, field controls with clear affordances show a clear button by default.
multipleDisplay'chips' | 'text' — How a multiple select shows its selection.
maxVisibleChipsnumber — Default visible selected chips before select renders a collapsed +N chip.
chevronIconKuiIconGlyph — Icon of the options toggle. Takes precedence over defaults.icons.pickerChevron. See Structural Icons.
clearIconKuiIconGlyph — Icon of the clear button. Takes precedence over defaults.icons.clear. See Structural Icons.

Set any of these on the component or an ancestor to restyle one part. Each token is optional: when it is not set, the part uses the role or scale token in the default column.

NameTypeDefaultDescription
--kui-listbox-option-colorCSS custom property--kui-color-textStbox option color
--kui-listbox-option-focus-ring-colorCSS custom property--kui-color-focusStbox option focus ring color
--kui-listbox-option-bg-selectedCSS custom property--kui-color-primary-soft-bgStbox option background, selected
--kui-listbox-option-color-selectedCSS custom property--kui-color-primary-soft-textStbox option color, selected
--kui-listbox-option-bg-selected-hoverCSS custom property--kui-color-primary-soft-bg-hoverStbox option background, selected hover
--kui-listbox-group-label-colorCSS custom property--kui-color-text-secondaryStbox group label color
--kui-listbox-separator-bgCSS custom property--kui-color-borderStbox separator background
--kui-listbox-empty-colorCSS custom property--kui-color-text-secondaryStbox empty color
--kui-select-chevron-color-expandedCSS custom property--kui-color-primary-textLect chevron color, expanded
NameTypeDefaultDescription
--kui-listbox-option-gapCSS custom property--kui-space-2Option gap
--kui-listbox-option-padding-blockCSS custom property--kui-space-2Option padding, block
--kui-listbox-option-padding-inlineCSS custom property--kui-space-3Option padding, inline
--kui-listbox-option-radiusCSS custom property--kui-radius-smOption corner radius
--kui-listbox-option-font-sizeCSS custom property--kui-text-sm-sizeOption font size
--kui-listbox-group-label-font-sizeCSS custom property--kui-text-xs-sizeGroup label font size
--kui-listbox-group-label-padding-block-startCSS custom property--kui-space-2Group label padding, block start
--kui-listbox-group-label-padding-inlineCSS custom property--kui-space-3Group label padding, inline
--kui-listbox-group-label-padding-block-endCSS custom property--kui-space-1Group label padding, block end
--kui-listbox-empty-padding-blockCSS custom property--kui-space-4Empty padding, block
--kui-listbox-empty-padding-inlineCSS custom property--kui-space-3Empty padding, inline
--kui-listbox-empty-font-sizeCSS custom property--kui-text-sm-sizeEmpty font size
--kui-select-padding-inline-endCSS custom property34pxInput end padding that clears the chevron
--kui-select-padding-inline-end-clearableCSS custom property56pxInput end padding that clears the clear button and the chevron
--kui-field-clear-icon-sizeCSS custom property12pxClear button icon size (Select, Combobox, Date Picker)

Every text the component owns (accessible names, visible words, announcements) is a typed message with an English default. Override it for the application with provideKikitaUi({ messages }), or for a subtree with provideKuiMessages.

NameTypeDefaultDescription
openOptionsstring — Name of the open button. Default Open options.
closeOptionsstring — Name of the close button. Default Close options.
removeItemKuiMessageFn<{ label: string; }> — Name of the remove button of one chip. Default Remove {label}.

Inputs and outputs verified against @kikita-labs/ui v2.0.0 public typings.

NameTypeDefaultDescription
valueT | readonly T[] | null — Selected value. In multiple mode this is an array.
disabledboolean — Disables the native input and prevents opening the dropdown.
readonlyboolean — Prevents opening the dropdown while keeping the field visually enabled.
invalidboolean — Validation state set by Signal Forms or direct input binding.
errorsValidationError[] — Validation errors consumed by kui-field for automatic error text.
touchedboolean — Touched state set by Signal Forms.
idstring — Explicit id override. Inside kui-field, the field id is used when omitted.
multipleboolean — Enables array values and keeps the dropdown open on option selection.
maxVisibleChipsnumber | undefined — Maximum selected chips shown before collapsed +N overflow. Falls back to defaults.select.maxVisibleChips, then 3.
multipleDisplay'chips' | 'text' — Renders multiple selections as field chips or plain joined text.
multipleTextFn(items: readonly T[]) => string — Formats native input text when multipleDisplay is text.
kuiLabelFn(item: T) => string — Maps selected object values to display text.
placeholderstring — Placeholder on the readonly input.
clearableboolean | undefined — Shows a clear button when a value is selected. Resolved as local input, defaults.select.clearable, defaults.field.clearable, then false.
touchoutput — Emitted after an opened dropdown closes for Signal Forms support.
ng-template[kuiSelectValue]context: { $implicit: T; label: string; remove: () => void }-Replaces the default chip for each visible selected item in multiple mode. Call remove from a native button to make the item removable.
KuiSelectOptionsinterface-Shape of defaults.select: clearable, multipleDisplay, maxVisibleChips, chevronIcon and clearIcon.

Select keeps field wiring on kui-field and listbox semantics on dropdown options.

  • The trigger input uses combobox semantics and reflects dropdown expanded state.
  • Dropdown panel uses listbox semantics; each kuiOption is an option.
  • Use kui-field for label, hint, error, and described-by wiring.
  • Each kuiOption exposes aria-selected and aria-disabled.
  • The clear affordance is a native button named Clear, and the options toggle is named by the kuiSelect.openOptions and kuiSelect.closeOptions messages.
  • Enter or Space opens the dropdown and then selects the focused option; ArrowDown and ArrowUp open it and focus the first or last option; Escape closes it; Tab closes it through the focused option flow.
  • Multiple selected values render removable chip buttons named by the kuiSelect.removeItem message. maxVisibleChips is count-based and does not measure the field width.
  • touch is emitted after an opened dropdown closes, which marks the control touched for Signal Forms.

Consumer-visible changes of @kikita-labs/ui 2.0 for Select.

  • The classes are KuiSelect, KuiSelectValue, KuiOption and KuiDropdown; the Directive and Component suffixes are gone.
  • kuiProvideSelectOptions and KUI_SELECT_OPTIONS are replaced by provideKuiDefaults({ select: { ... } }); clearable resolves as local input, then defaults.select, then defaults.field, then false.
  • The legacy tokens --kui-select-bg, --kui-select-border, --kui-select-border-hover, --kui-select-border-focus, --kui-select-border-error and --kui-select-radius were removed; use the shared --kui-input-* tokens.
  • chevronIcon and clearIcon defaults set the glyphs of the options toggle and the clear button.
  • The open, close and chip remove button names come from the kuiSelect messages.