fix(popover): errors following a full review of the component - #1942
Conversation
|
Visit the preview URL for this PR (updated for commit 0e6f08d): https://koobiq-next--prs-1942-3631iuvm.web.app (expires Sat, 05 Sep 2026 14:27:32 GMT) 🔥 via Firebase Hosting GitHub Action 🌎 Sign: c9e37e518febda70d0317d07e8ceb35ac43c534c |
aaae9dd to
8c23016
Compare
The popover-leave-delay schematic shipped without a section in the upgrade guide, and the hover-delay change it reports is the one that has no compile error behind it: a programmatic leaveDelay assignment is now silently overwritten.
8c23016 to
09253ba
Compare
The snapshot came from upstream during the rebase, so it missed the one member the merge changed. Regenerated from a fresh build.
There was a problem hiding this comment.
🟡 Changes recommended
There are a few concrete correctness/documentation issues (including a schematic warning message mismatch and guardrails in popover close paths) that should be addressed before approval.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR addresses multiple correctness, accessibility, and i18n issues in the popover component family, plus adds a warn-only migration schematic to help consumers find impacted call sites.
Changes:
- Fixes popover trigger behavior (scroll subscription teardown, stick-to-window persistence, hover leave-delay defaulting) and improves repositioning stability.
- Improves accessibility (trigger ARIA attributes, close button accessible name, reduced-motion support, focus restoration behavior).
- Adds locale-backed defaults for
KbqPopoverConfirmComponentand wires them into core locale infrastructure and docs/migrations.
File summaries
| File | Description |
|---|---|
| tools/public_api_guard/components/popover.api.md | Public API snapshot updates for popover exports and signature changes. |
| tools/public_api_guard/components/core.api.md | Public API snapshot updates for new locale types/tokens/helpers. |
| tools/cspell-locales/ru.json | Adds a new Russian word form for spellchecking. |
| packages/schematics/src/migrations/popover-leave-delay/schema.ts | Migration schematic options interface. |
| packages/schematics/src/migrations/popover-leave-delay/schema.json | JSON schema for the migration schematic. |
| packages/schematics/src/migrations/popover-leave-delay/README.md | Migration documentation describing behavior changes and manual steps. |
| packages/schematics/src/migrations/popover-leave-delay/index.ts | Warn-only schematic implementation that scans for affected call sites. |
| packages/schematics/src/migrations/popover-leave-delay/index.spec.ts | Unit tests for the migration schematic reporting behavior. |
| packages/schematics/src/migrations/popover-leave-delay/data.ts | Defines detection patterns and user-facing warning messages. |
| packages/schematics/src/migrations.json | Registers the new migration for the target version. |
| packages/schematics/src/collection.json | Adds schematic entry so it can be invoked/generated. |
| packages/docs-examples/components/popover/popover-width/popover-width-example.html | Updates docs examples to new prefixed inputs. |
| packages/docs-examples/components/popover/popover-scroll/popover-scroll-example.ts | Updates docs examples to new prefixed inputs. |
| packages/docs-examples/components/popover/popover-paddings/popover-paddings-example.html | Updates docs examples to new prefixed inputs. |
| packages/docs-examples/components/popover/popover-header/popover-header-example.html | Updates docs examples to new prefixed inputs. |
| packages/docs-examples/components/popover/popover-content/popover-content-example.html | Updates docs examples to new prefixed inputs. |
| packages/docs-examples/components/popover/popover-close/popover-close-example.html | Updates docs examples to new prefixed inputs. |
| packages/docs-examples/components/list/list-intermediate-state/list-intermediate-state-example.html | Updates nested popover example to new prefixed inputs. |
| packages/components/popover/popover.spec.ts | Expands unit tests for hover timing, closing behavior, leaks, a11y, and confirm locale behavior. |
| packages/components/popover/popover.scss | Adjusts layering/z-index and fixes RTL close-button positioning. |
| packages/components/popover/popover.ru.md | Updates RU docs for prefixed inputs, close-on-scroll behavior, confirm variant, a11y, and leave-delay semantics. |
| packages/components/popover/popover.module.ts | Simplifies module wiring now that providers move off the NgModule. |
| packages/components/popover/popover.en.md | Updates EN docs for prefixed inputs, confirm variant, a11y, and leave-delay semantics. |
| packages/components/popover/popover.component.ts | Core behavioral fixes (leaveDelay derivation, scroll teardown, focus restore, aria wiring, reduced-motion). |
| packages/components/popover/popover.component.html | Adds conditional dialog role/naming, scrollable region semantics, and refactors close button markup. |
| packages/components/popover/popover-confirm.component.ts | Adds locale-driven defaults and ensures confirm wiring doesn’t stack on updates. |
| packages/components/popover/popover-confirm.component.html | Aligns confirm template with new panel id/trap focus/arrow behavior and a11y labeling. |
| packages/components/popover/popover-animations.ts | Updates animation curves/durations and documents reduced-motion opt-out. |
| packages/components/popover/e2e.ts | Adjusts e2e setup for trigger querying and panel instantiation. |
| packages/components/popover/e2e.playwright-spec.ts | Updates e2e assertion commentary for the hover gap behavior. |
| packages/components/core/locales/types.ts | Adds KbqPopoverConfirmLocaleConfiguration and wires it into locale string data shape. |
| packages/components/core/locales/tk-TM.ts | Adds popoverConfirm localized strings. |
| packages/components/core/locales/ru-RU.ts | Adds popoverConfirm localized strings. |
| packages/components/core/locales/pt-BR.ts | Adds popoverConfirm localized strings. |
| packages/components/core/locales/es-LA.ts | Adds popoverConfirm localized strings. |
| packages/components/core/locales/en-US.ts | Adds popoverConfirm localized strings. |
| packages/components/core/locales/popover-confirm.ts | Implements token/provider/injector helper for confirm-popover locale section. |
| packages/components/core/locales/popover-confirm.spec.ts | Tests locale fallback, locale switching, overrides, and section completeness per locale. |
| packages/components/core/locales/index.ts | Exports the new popover-confirm locale API. |
| packages/components-dev/popover/template.html | Updates dev-app template to new prefixed inputs. |
| docs/guides/migration.ru.md | Documents popover-related migration notes for v20 update. |
| docs/guides/migration.en.md | Documents popover-related migration notes for v20 update. |
| apps/docs/src/app/components/popover-example/popover-example.component.ts | Updates docs app usage to the new prefixed hide-in-viewport input. |
Review details
Suppressed comments (1)
packages/components/popover/popover.component.ts:221
onClose()callsthis.trigger.close()unconditionally; if the component is used without a trigger, clicking the close button will throw. A safe fallback is to close the panel directly whentriggeris unset.
protected onClose(): void {
this.trigger.close();
}
- Files reviewed: 43/43 changed files
- Comments generated: 3
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
`KbqPopoverComponent` is exported, so a consumer can render the panel on its own, and `ngAfterViewInit` already allowed for a missing trigger — but Escape and the close button reached through it unguarded. They now hide the panel directly when there is no trigger to route through, which is also the only case where there is no `kbqPopoverPreventClose` to honor and nothing to hand focus back to. Two corrections to the review's own text. The size warning read "Will used default size". And the `placementChange` note claimed the output emits `KbqPopUpPlacementValues` and that a `(p: string)` handler stops matching; it emits `string` where it used to emit `any`, so such a handler is unaffected and only a payload assigned to a non-string breaks. Fixed in the schematic message and in both migration guides.
Summary
The popover surface is rich, but the trigger layer leaked and mis-positioned under ordinary
conditions: a global
ScrollDispatchersubscription with no teardown in the default configuration,stickToWindowwiped by every CDK position re-apply, and a hover mode whose effective leave delay was0ms — the panel closed before the pointer could cross the 8px gap to it. The confirm variant also
shipped its default strings hardcoded in Russian.
The second commit fixes the close button's RTL placement.
List of notable changes:
ScrollDispatcher.scrolled()subscription that leaked the trigger'ssubscriber graph for the lifetime of the app and pinned CDK's global scroll listener
stickToWindowbeing undone by the first ancestor scroll, window resize, or input updatewhile the popover is open
this.leaveDelay ?? 500was dead because the base initialises thefield to
0, so hover mode's interactive content was unreachable even for pointer users (WCAG 1.4.13)and the auto-hide watchdog burned CPU as an
interval(0)the whole time the panel was openthe NgModule
aria-expanded/aria-haspopup/aria-controlson the trigger — the default click flow was fully silent for screen-reader usersKbqPopoverConfirmComponent, whose defaults were hardcoded Russianwith no locale-service integration; new
core/locales/popover-confirm.tsplus entries in all fivelocale files
dir="rtl":inset-inline-endmirrors but thephysical
translateX(50%)did not, so the button landed inside the panel on top of the content —the transform is now direction-flipped through the repo's own
rtl()mixinpopover-leave-delaymigration, which reports programmaticleaveDelayassignments(they no longer stick — the delay is re-derived from
triggerunlesskbqLeaveDelaywas bound), thenow-readonly
onConfirm, and the narrowedplacementChangepayloadWhat should reviewers focus on?
packages/components/core/locales/popover-confirm.tsand the five locale files — new translatedstrings that need a native check, particularly
tk-TM.leaveDelayinput is now a write-onlykbqLeaveDelaysetter with a tracked "was it bound"flag, because TypeScript refuses to override the base class's plain field with an accessor (TS2611)
and an explicit
kbqLeaveDelay="0"has to stay distinguishable from an unbound one.One of ten pull requests from a single review pass (
review/*). Every branch carries two commits: thefixes from the component review, and a second pass over the findings an independent verifier could not
confirm outright.
The branches share files, so they have to be merged one at a time with a rebase in between. Overlap:
packages/components/core/locales/*(7 branches),tools/public_api_guard/components/core.api.md(7),tools/cspell-locales/*.json(6),packages/e2e/routes.ts(4) andpackages/schematics/src/{collection,migrations}.json(3).