Getting StartedInstall and bootstrap headless foundations 4
LayoutHeadless structural primitives for expandable and container patterns 6
OverlayHeadless modal and floating layer behavior 3
FeedbackHeadless notification and status communication patterns 5
FormHeadless input and selection contracts 17
UtilityReusable action, identity, and clipboard behavior 6
NavigationHeadless trails, trees, menus, and command surfaces 7

API reference

Attach tngListbox to the owned list container and tngOption to each option host. The directives handle selection state, roving focus, and typeahead without imposing a wrapper DOM.

Focus stays on the tngListbox host. Individual tngOption items are exposed to assistive technology and active-descendant tracking, but they are not part of the normal Tab sequence.

tngListbox

Primitive attachment

html
<div
  tngListbox
  tabindex="0"
  [multiple]="true"
  [value]="selectedChannels()"
  (valueChange)="onSelectedChannelsChange($event)"
>
  @for (channel of channels; track channel.id) {
    <div
      tngOption
      [tngValue]="channel.id"
      [disabled]="channel.disabled === true"
    >
      {{ channel.label }}
    </div>
  }
</div>
Input / outputTypeNotes
multiplebooleanEnables multi-selection. Default is single selection.
orientation'vertical' | 'horizontal'Controls the arrow-key axis for active-item roving.
direction'ltr' | 'rtl'Used when orientation="horizontal".
disabledbooleanDisables the entire listbox interaction model.
loopbooleanWraps roving focus from last to first option and vice versa.
typeaheadbooleanPrintable keys jump to matching option text. Enabled by default.
value / valueChangeT | readonly T[] | nullSelection model for single or multiple mode.

tngOption

InputTypeNotes
tngValueTValue committed into the listbox selection model.
disabledbooleanPrevents pointer and keyboard selection for that option.

Reflected attributes

The directives expose state through ARIA and presence-based data attributes so you can style without relying on implementation-private classes.

Reflected attributes

html
<div
  role="listbox"
  aria-activedescendant="tng-option-..."
  aria-multiselectable="true"
>
  <div
    role="option"
    tabindex="-1"
    aria-selected="true"
    data-active
    data-selected
  >
    Docs
  </div>
</div>
DirectiveAttributesPurpose
tngListboxrole, aria-multiselectable, aria-disabled, aria-activedescendantListbox semantics and active-descendant wiring.
tngOptionrole, tabindex="-1", aria-selected, aria-disabledOption semantics for screen readers while the listbox host owns Tab focus.
tngOptiondata-active, data-selected, data-disabledPublic styling hooks for stateful option rendering.

Change handling

In multiple mode, normalize the emitted value into an array so summaries and downstream filters stay stable.

Selection normalizer

ts
type ListboxValue = string | readonly string[] | null;

readonly selectedChannels = signal<readonly string[]>(['docs']);

onSelectedChannelsChange(value: ListboxValue): void {
  if (value === null) {
    this.selectedChannels.set([]);
    return;
  }

  this.selectedChannels.set(typeof value === 'string' ? [value] : value);
}