Feature Description
Public API to set the active (highlighted) option on ngListbox
Package: @angular/aria (listbox)
Versions: @angular/aria@22.0.2, @angular/core@22.0.4
Summary
ngListbox exposes a first-class way to read the active option (Listbox.activeDescendant, Option.active) but no public way to programmatically move it to an arbitrary option. The only public "setters" are Listbox.gotoFirst() and Listbox.scrollActiveItemIntoView(). This makes it impossible to build a pointer-driven highlight.
Current behavior (public API)
class Listbox<V> {
readonly activeDescendant: Signal<string | undefined>; // read only
gotoFirst(): void; // only "first"
scrollActiveItemIntoView(options?: ScrollIntoViewOptions): void;
}
class Option<V> {
readonly active: Signal<boolean>; // read only
}
There is no public equivalent of "make this option active".
Desired behavior
A public, supported way to set the active option to any option — ideally one that works in focusMode="activedescendant" without moving DOM focus off the trigger (i.e. update aria-activedescendant only).
Alternatives considered
- CSS
:hover only — produces two simultaneous highlights and lets Enter/click act on a different option than the hovered one. Not acceptable.
- Reaching into internals — the capability exists today only via non-public members:
listbox._pattern.listBehavior.goto(option._pattern, { focusElement: false });
Depending on _pattern / listBehavior / goto / Option._pattern is not viable for us: they're underscore-prefixed internals.
@angular/cdk/listbox — CdkOption.focus() (public) sets the active option in roving-tabindex mode, so this behavior is achievable there. It would be great for @angular/aria to offer a first-class equivalent that also works in activedescendant mode (no DOM focus move).
Additional context
gotoFirst() and scrollActiveItemIntoView() are already public, so the active-position concept is partly exposed — this request is to round it out with an "activate arbitrary option" entry point that composes cleanly with focusMode="activedescendant".
Use Case
I'm building a custom select/combobox on top of ngListbox with focusMode="activedescendant" (focus stays on the trigger; the listbox is portaled in a popup). I want the standard desktop behavior where hovering an option makes it the active option, so that:
- there is a single visual highlight (the keyboard-active item and the pointer are always the same item), and
- pressing
Enter / clicking commits the pointed option — not a stale keyboard-active one somewhere else.
Today, because I can only read the active option, hover and keyboard-active diverge: I get two highlighted items at once (a CSS :hover highlight on one, a CSS data-active on another with keyboard navigation), and the committed option can differ from the visually hovered one.
Feature Description
Public API to set the active (highlighted) option on
ngListboxPackage:
@angular/aria(listbox)Versions:
@angular/aria@22.0.2,@angular/core@22.0.4Summary
ngListboxexposes a first-class way to read the active option (Listbox.activeDescendant,Option.active) but no public way to programmatically move it to an arbitrary option. The only public "setters" areListbox.gotoFirst()andListbox.scrollActiveItemIntoView(). This makes it impossible to build a pointer-driven highlight.Current behavior (public API)
There is no public equivalent of "make this option active".
Desired behavior
A public, supported way to set the active option to any option — ideally one that works in
focusMode="activedescendant"without moving DOM focus off the trigger (i.e. updatearia-activedescendantonly).Alternatives considered
:hoveronly — produces two simultaneous highlights and letsEnter/click act on a different option than the hovered one. Not acceptable._pattern/listBehavior/goto/Option._patternis not viable for us: they're underscore-prefixed internals.@angular/cdk/listbox—CdkOption.focus()(public) sets the active option in roving-tabindex mode, so this behavior is achievable there. It would be great for@angular/ariato offer a first-class equivalent that also works inactivedescendantmode (no DOM focus move).Additional context
gotoFirst()andscrollActiveItemIntoView()are already public, so the active-position concept is partly exposed — this request is to round it out with an "activate arbitrary option" entry point that composes cleanly withfocusMode="activedescendant".Use Case
I'm building a custom select/combobox on top of
ngListboxwithfocusMode="activedescendant"(focus stays on the trigger; the listbox is portaled in a popup). I want the standard desktop behavior where hovering an option makes it the active option, so that:Enter/ clicking commits the pointed option — not a stale keyboard-active one somewhere else.Today, because I can only read the active option, hover and keyboard-active diverge: I get two highlighted items at once (a CSS
:hoverhighlight on one, a CSSdata-activeon another with keyboard navigation), and the committed option can differ from the visually hovered one.