Is this a regression?
The previous version in which this bug was not present was
No response
Description
Combobox + ComboboxWidget + Listbox (the documented Select/Multiselect pattern using usePopover: 'inline' via cdkConnectedOverlay) permanently stops closing on outside click after any option has been selected once.
Root cause: the popup-close decision is only ever evaluated inside ComboboxPattern.onFocusout() (packages/aria/private), which is wired solely to the trigger element's own (focusout). Because usePopover: 'inline' renders the popup in a DOM subtree that is not a descendant of the trigger, and ngOption renders options with tabindex="-1" (which are click-focusable in browsers), clicking an option permanently moves DOM focus off the trigger and into the popup. After that, the trigger element never blurs again, so ComboboxPattern.onFocusout() never re-runs, and the popup can only be closed again by clicking the trigger directly (an unconditional toggle, unrelated to focus).
ComboboxWidget's own (focusout) (packages/aria/combobox) does fire when focus leaves the popup, and correctly updates ComboboxPopupPattern.isFocused, but nothing observes that signal to re-trigger the close check — the close logic needs to react to focus changes from either the trigger or the popup, not just the trigger.
Reproduction
The issue seems to occur on the examples from official documentation as well. So a reproduction can be found there:
- Open https://angular.dev/guide/aria/multiselect#basic-multiselect
- Click the "Select a label" combobox to open it.
- Click any label to select it (popup correctly stays open).
- Click anywhere outside the combobox (e.g. the page heading).
Expected Behavior
The popup closes
Actual Behavior
The popup stays open. Clicking outside again does nothing further. The only way to close it is to click the trigger directly
Environment
Angular CLI : 22.1.3
Angular : 22.1.0
Node.js : 24.19.0
Package Manager : npm 11.17.0
Operating System : linux x64
┌───────────────────────────────────┬───────────────────┬───────────────────┐
│ Package │ Installed Version │ Requested Version │
├───────────────────────────────────┼───────────────────┼───────────────────┤
│ @angular-devkit/architect │ 0.2201.3 │ ^0.2201.3 │
│ @angular-devkit/build-angular │ 22.1.3 │ ^22.1.3 │
│ @angular-devkit/core │ 22.1.3 │ ^22.1.3 │
│ @angular/aria │ 22.1.1 │ ^22.1.1 │
│ @angular/build │ 22.1.3 │ ^22.1.3 │
│ @angular/cdk │ 22.1.1 │ ^22.1.1 │
│ @angular/cli │ 22.1.3 │ ^22.1.3 │
│ @angular/common │ 22.1.0 │ ^22.1.0 │
│ @angular/compiler │ 22.1.0 │ ^22.1.0 │
│ @angular/compiler-cli │ 22.1.0 │ ^22.1.0 │
│ @angular/core │ 22.1.0 │ ^22.1.0 │
│ @angular/forms │ 22.1.0 │ ^22.1.0 │
│ @angular/platform-browser │ 22.1.0 │ ^22.1.0 │
│ @angular/platform-browser-dynamic │ 22.1.0 │ ^22.1.0 │
│ @angular/router │ 22.1.0 │ ^22.1.0 │
│ rxjs │ 7.8.2 │ ~7.8.0 │
│ typescript │ 6.0.3 │ ~6.0.3 │
│ vitest │ 4.1.10 │ ^4.1.10 │
└───────────────────────────────────┴───────────────────┴───────────────────┘
Is this a regression?
The previous version in which this bug was not present was
No response
Description
Combobox + ComboboxWidget + Listbox (the documented Select/Multiselect pattern using usePopover: 'inline' via cdkConnectedOverlay) permanently stops closing on outside click after any option has been selected once.
Root cause: the popup-close decision is only ever evaluated inside ComboboxPattern.onFocusout() (packages/aria/private), which is wired solely to the trigger element's own (focusout). Because usePopover: 'inline' renders the popup in a DOM subtree that is not a descendant of the trigger, and ngOption renders options with tabindex="-1" (which are click-focusable in browsers), clicking an option permanently moves DOM focus off the trigger and into the popup. After that, the trigger element never blurs again, so ComboboxPattern.onFocusout() never re-runs, and the popup can only be closed again by clicking the trigger directly (an unconditional toggle, unrelated to focus).
ComboboxWidget's own (focusout) (packages/aria/combobox) does fire when focus leaves the popup, and correctly updates ComboboxPopupPattern.isFocused, but nothing observes that signal to re-trigger the close check — the close logic needs to react to focus changes from either the trigger or the popup, not just the trigger.
Reproduction
The issue seems to occur on the examples from official documentation as well. So a reproduction can be found there:
Expected Behavior
The popup closes
Actual Behavior
The popup stays open. Clicking outside again does nothing further. The only way to close it is to click the trigger directly
Environment
Angular CLI : 22.1.3
Angular : 22.1.0
Node.js : 24.19.0
Package Manager : npm 11.17.0
Operating System : linux x64
┌───────────────────────────────────┬───────────────────┬───────────────────┐
│ Package │ Installed Version │ Requested Version │
├───────────────────────────────────┼───────────────────┼───────────────────┤
│ @angular-devkit/architect │ 0.2201.3 │ ^0.2201.3 │
│ @angular-devkit/build-angular │ 22.1.3 │ ^22.1.3 │
│ @angular-devkit/core │ 22.1.3 │ ^22.1.3 │
│ @angular/aria │ 22.1.1 │ ^22.1.1 │
│ @angular/build │ 22.1.3 │ ^22.1.3 │
│ @angular/cdk │ 22.1.1 │ ^22.1.1 │
│ @angular/cli │ 22.1.3 │ ^22.1.3 │
│ @angular/common │ 22.1.0 │ ^22.1.0 │
│ @angular/compiler │ 22.1.0 │ ^22.1.0 │
│ @angular/compiler-cli │ 22.1.0 │ ^22.1.0 │
│ @angular/core │ 22.1.0 │ ^22.1.0 │
│ @angular/forms │ 22.1.0 │ ^22.1.0 │
│ @angular/platform-browser │ 22.1.0 │ ^22.1.0 │
│ @angular/platform-browser-dynamic │ 22.1.0 │ ^22.1.0 │
│ @angular/router │ 22.1.0 │ ^22.1.0 │
│ rxjs │ 7.8.2 │ ~7.8.0 │
│ typescript │ 6.0.3 │ ~6.0.3 │
│ vitest │ 4.1.10 │ ^4.1.10 │
└───────────────────────────────────┴───────────────────┴───────────────────┘