fix: Fix focus on ng-select sorting element - #21509
Conversation
🚨 PR Title Validation Failed 🚨Your pull request title does not follow the required format. Please update it to match the expected pattern: Expected format: Allowed Types
Example of a valid PR title✅ ❌ Merge is blocked until the PR title is corrected. |
7ef25ee to
251693a
Compare
c71bb6c to
50b36c8
Compare
50b36c8 to
be6eb8f
Compare
Zeyber
left a comment
There was a problem hiding this comment.
It works. But there seems to be a lot of unrelated changes. Could you please explain why we have modified different focus directives? Are we using all of them?
There also seems to be case-specific code (ie. reference to ng-select and combobox). These directives should stay generic. We can modify sorting component itself or look into the cxNgSelectA11y directive for this specific component. I would say these places would be more appropriate for these targetted changes.
@Zeyber
The API itself stays generic — it accepts any CSS selector and a boolean. The JSDoc mentions only as an example of a wrapper-with-inner-interactive-element pattern. VisibleFocusDirective — agreed, the role="combobox" check did not belong in a generic directive. I've reverted that change and moved the logic to NgSelectA11yDirective, which now listens to keydown on its host and clears the mouse-focus class from the closest ancestor that has it (deferred via microtask so it runs after VisibleFocusDirective's bubbled handler). This keeps the case-specific knowledge ("ng-select keystrokes are dropdown navigation, not form filling") in the case-specific directive. Tests added to ng-select-a11y.directive.spec.ts; the combobox-specific tests in visible-focus.directive.spec.ts were removed. The a11yConsentManagementFocusPreservation (checkbox/radio) tests stay — they cover pre-existing logic in the directive. Let me know if you'd like the PersistFocusDirective API renamed or rescoped further. |
spartacus
|
||||||||||||||||||||||||||||
| Project |
spartacus
|
| Branch Review |
bugfix/CXSPA-12686-keep-sorting-focused-after-sort
|
| Run status |
|
| Run duration | 04m 47s |
| Commit |
|
| Committer | sebastianpaduch |
| View all properties for this run ↗︎ | |
| Test results | |
|---|---|
|
|
0
|
|
|
3
|
|
|
0
|
|
|
0
|
|
|
101
|
| View all changes introduced in this branch ↗︎ | |
560d935 to
b24b2f0
Compare
Zeyber
left a comment
There was a problem hiding this comment.
I think this fix is much too complicated. I've created an example PR to show all I found needed to resolve the problem using ViewChild and requestAnimationFrame. Note that using requestAnimationFrame is favourable over setTimeout as requesting the frame itself is more verbose.
#21566
b24b2f0 to
ff1a9b4
Compare
Zeyber
left a comment
There was a problem hiding this comment.
Can we clean up any unnecessary artifacts in this PR? Lots of redundant code.
|
I see the issue persists in Coupons page with the example I shared due to rerendering happening on that page. I only tested PLP before so lets disregard my last review comment for now while I look into it. |
Zeyber
left a comment
There was a problem hiding this comment.
Tested on MyCoupons page and now understand the reason for these changes much better. focusTargetSelector is very useful to have and the solution is working well! Feature flags also handled well. Remaining comments are minor.
|
I needed to revert the ngFocus logic because of a specific corner case. Currently, when there is only one coupon on the page and you change the sorting via Tab + Enter, the focus is lost after the second attempt. To fix this, I changed the focusing approach: instead of invoking focus() from NgSelectComponent, I apply native focus directly to the specific DOM element. |
5dc1ba2 to
0756a10
Compare
Merge Checks Failed |
Zeyber
left a comment
There was a problem hiding this comment.
It seems like there are a lot of mechanics built into the ng-select component which makes it more difficult to manage as this library is 3rd-party and we need to work around a lot of this behaviour. We also have a legacy of our on focus management tools on tops of this which adds to the complexity.
Great job on resolving the issues around this component and showing me some very unexpected edge cases!
E2E Tests Failed ❌Commit: 6c4fbfb |
Merge Checks Failed |
- PersistFocusDirective: add `focusTargetSelector` (delegate restore to a descendant) and `clearOnRestore` (prevent key leaking across routes). - VisibleFocusDirective: keep focus outline on `role="combobox"` keys and on Space/Enter for checkbox/radio (behind feature flag). - SortingComponent: opt into the new flags and redirect focus to inner combobox after sort for the not-remounted case (PLP). - Tests for both directives.
…yDirective Address review: keep VisibleFocusDirective generic. The case-specific "ng-select keystrokes are dropdown navigation" handling now lives in NgSelectA11yDirective, where the ng-select context belongs. - VisibleFocusDirective: revert the role="combobox" check; the directive no longer references ng-select-specific concepts. - NgSelectA11yDirective: add `onKeyDown` host listener that clears the `mouse-focus` class from the closest ancestor (microtask-deferred so it runs after VisibleFocusDirective's bubbled handler). - Tests moved accordingly.
62320e9 to
af1e990
Compare
E2E Tests Failed ❌Commit: 5335d3a |
Merge Checks Failed |
Ticket: https://jira.tools.sap/browse/CXSPA-12686
Ticket: https://jira.tools.sap/browse/CXSPA-12776
Global fix for focusing sorting component.