fix(notification-center): errors following a full review of the component - #1943
Conversation
|
Visit the preview URL for this PR (updated for commit 30156db): https://koobiq-next--prs-1943-yn91re71.web.app (expires Thu, 10 Sep 2026 11:28:04 GMT) 🔥 via Firebase Hosting GitHub Action 🌎 Sign: c9e37e518febda70d0317d07e8ceb35ac43c534c |
9e25e84 to
e706cf5
Compare
🚨 E2E tests failedReview the report for details. 💡 Comment |
🚨 E2E tests failedReview the report for details. 💡 Comment |
🚨 E2E tests failedReview the report for details. 💡 Comment |
18b5a53 to
b6192fb
Compare
🚨 E2E tests failedReview the report for details. 💡 Comment |
🚨 E2E tests failedReview the report for details. 💡 Comment |
5168dff to
86bf066
Compare
🚨 E2E tests failedReview the report for details. 💡 Comment |
86bf066 to
92d4c53
Compare
🚨 E2E tests failedReview the report for details. 💡 Comment |
92d4c53 to
62938a8
Compare
🚨 E2E tests failedReview the report for details. 💡 Comment |
🚨 E2E tests failedReview the report for details. 💡 Comment |
e71aed0 to
4c4e385
Compare
🚨 E2E tests failedReview the report for details. 💡 Comment |
|
/approve-snapshots |
|
🔄 Updating snapshots. |
|
✅ Snapshots updated! |
… the migration guide Two schematics shipped without a section in the upgrade guide, and the change that hurts most has no schematic to report it at all: the service stopped being provided by the module, so its date adapter now has to reach the root injector or the first injection throws NG0201.
KbqLuxonDateModule imports KbqLocaleServiceModule, so providing it app-wide bound KBQ_LOCALE_SERVICE for every fixture, not just this one. KbqDataSizePipe injects that token optionally and falls back to its built-in units without it, so file-upload started rendering "4 Б" against a baseline holding "4 B". LuxonDateModule provides the DateAdapter the notification-center service needs and nothing else.
The tooltip and popover reviews landed on main while this branch was open, and both narrowed `KbqPopUpTrigger.placementChange` from `EventEmitter<string>` to `EventEmitter<KbqPopUpPlacementValues>`. This branch had typed its own override as `string` — correct against the old base, and no longer assignable to the new one, which broke the whole component: `KbqNotificationCenterTrigger` stopped satisfying `KbqPopUpTrigger`, so `KbqNotificationCenterComponent.trigger` failed too. main's own version declares a bare `new EventEmitter()`, which type-checks only because it infers `any`. The union is what the base emits, so that is what the override says now.
…p root `KbqNotificationCenterService` left `KbqNotificationCenterModule.providers` in this review, so the `providedIn: 'root'` singleton is now the only instance and it resolves `DateAdapter` and `DateFormatter` from the root injector. Neither has a root provider — `DateAdapter` is an abstract class and `DateFormatter` carries no `providedIn` — and the dev-ssr root supplied neither, so the first notification-center example rendered in a prerender worker threw NG0201 and took the worker down with it, failing every route batched into that worker: 197 of ~530, spread across every component, from two dead workers. Same fix the e2e app already got, and the same reasoning for the module choice: `KbqLuxonDateModule` would also import `KbqLocaleServiceModule`, which this config already binds a line above. Measured: `ssr:build` fails with 197 unrendered routes before, 0 after, matching main.
3459808 to
117e5be
Compare
There was a problem hiding this comment.
🟡 Changes recommended
The new migrations should be adjusted to avoid rewriting/scanning .d.ts and .ngtypecheck.ts files and to correctly scope local receiver renames to block-level to prevent false-positive edits.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR hardens and modernizes notification-center by preventing invalid-date crashes, improving keyboard/focus accessibility in the overlay panel, and introducing two ng update migrations to help consumers adapt to the API surface changes.
Changes:
- Prevent panel-breaking errors from unparsable notification dates (service-side parsing/cache + UI-side guarding).
- Fix keyboard/focus behavior in the overlay (focus trap installation, focus restoration after deletes, keyboard-reachable delete controls, added ARIA labeling/live-region text).
- Add
ng updatemigrations to (a) renameKbqReadStateDirectivedwell handlers and (b) report non-mechanical notification-center breaking changes.
File summaries
| File | Description |
|---|---|
| tools/public_api_guard/components/notification-center.api.md | Updates public API snapshot for notification-center surface changes. |
| tools/public_api_guard/components/core.api.md | Updates core public API snapshot (locale + read-state directive signature changes). |
| tools/check-public-api-any/baseline.json | Updates any/unknown baseline counts for notification-center. |
| packages/schematics/src/migrations/read-state-dwell-handlers/schema.ts | Adds migration options typing. |
| packages/schematics/src/migrations/read-state-dwell-handlers/schema.json | Defines migration schema for CLI usage. |
| packages/schematics/src/migrations/read-state-dwell-handlers/README.md | Documents the dwell-handler rename migration and manual follow-ups. |
| packages/schematics/src/migrations/read-state-dwell-handlers/index.ts | Implements the dwell-handler rename + warnings migration. |
| packages/schematics/src/migrations/read-state-dwell-handlers/index.spec.ts | Adds schematic test coverage for renames and reporting behavior. |
| packages/schematics/src/migrations/read-state-dwell-handlers/data.ts | Centralizes patterns/messages for the dwell-handler migration. |
| packages/schematics/src/migrations/notification-center-signals/schema.ts | Adds migration options typing. |
| packages/schematics/src/migrations/notification-center-signals/schema.json | Defines migration schema for CLI usage. |
| packages/schematics/src/migrations/notification-center-signals/README.md | Documents notification-center breaking changes that require manual decisions. |
| packages/schematics/src/migrations/notification-center-signals/index.ts | Implements report-only migration for notification-center API changes. |
| packages/schematics/src/migrations/notification-center-signals/index.spec.ts | Adds schematic test coverage for report behavior. |
| packages/schematics/src/migrations/notification-center-signals/data.ts | Centralizes patterns/messages for notification-center report migration. |
| packages/schematics/src/migrations.json | Registers both new migrations for ng update. |
| packages/schematics/src/collection.json | Registers both schematics in the schematics collection. |
| packages/e2e/routes.ts | Adds new notification-center e2e routes/fixtures. |
| packages/e2e/main.ts | Ensures DateAdapter/formatters are provided at root for e2e app bootstrapping. |
| packages/components/notification-center/public-api.ts | Adjusts exports (adds tokens export, removes animations export). |
| packages/components/notification-center/notification-item.ts | Guards date formatting, switches to panel token contract, adds focus-safe delete behavior. |
| packages/components/notification-center/notification-item.scss | Makes delete button keyboard-reachable and updates sizing tokens. |
| packages/components/notification-center/notification-item.html | Fixes template context exposure, adds unread SR text, wires focus-safe removal. |
| packages/components/notification-center/notification-center.ts | Focus trap + focus restoration + scroll handling fixes; introduces panel token/provider. |
| packages/components/notification-center/notification-center.tokens.ts | Introduces tokens + locale provider utilities + narrow panel contract. |
| packages/components/notification-center/notification-center.service.ts | Adds parsed-date caching/guarding, Subjects instead of EventEmitters, unread counter sharing. |
| packages/components/notification-center/notification-center.scss | Adds tokens, trap wrapper styling, keyboard-reveal affordances, and z-index fixes. |
| packages/components/notification-center/notification-center-tokens.scss | Defines component CSS tokens for sizing/theme. |
| packages/components/notification-center/notification-center.ru.md | Documents new requirements/behavior (root date adapter, unparsable dates, deletion semantics). |
| packages/components/notification-center/notification-center.en.md | Same documentation updates in English. |
| packages/components/notification-center/notification-center.module.ts | Makes NgModule a compatibility wrapper (drops redundant providers). |
| packages/components/notification-center/notification-center.html | Installs focus trap wrapper + live region, improves tracking keys and delete wiring. |
| packages/components/notification-center/notification-center-animations.ts | Removes unused animations file/export. |
| packages/components/notification-center/e2e.ts | Adds richer notification-center e2e fixtures including overlay-triggered scenario. |
| packages/components/notification-center/e2e.playwright-spec.ts | Adds Playwright assertions for new states + keyboard/focus behaviors. |
| packages/components/notification-center/_notification-center-theme.scss | Switches theme styling to tokenized variables. |
| packages/components/core/locales/types.ts | Adds unread string to notification-center locale configuration type. |
| packages/components/core/locales/en-US.ts | Adds unread locale string. |
| packages/components/core/locales/es-LA.ts | Adds unread locale string. |
| packages/components/core/locales/pt-BR.ts | Adds unread locale string. |
| packages/components/core/locales/ru-RU.ts | Adds unread locale string. |
| packages/components/core/locales/tk-TM.ts | Adds unread locale string. |
| packages/components/core/common-behaviors/read-state.ts | Extends dwell tracking to keyboard focus and refactors handlers/timestamp semantics. |
| packages/components/core/common-behaviors/read-state.spec.ts | Adds unit tests for new dwell behavior across pointer and focus. |
| packages/components-dev/ssr/config.ts | Ensures root-provided DateAdapter/formatters for SSR prerender stability. |
| docs/guides/migration.ru.md | Documents notification-center + read-state migration implications. |
| docs/guides/migration.en.md | Same documentation updates in English. |
Review details
- Files reviewed: 48/50 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.
…ted TypeScript
`read-state-dwell-handlers` collected a `let`/`const` receiver and gave it the whole enclosing
function as its scope, so a sibling block declaring the same name was rewritten too. Reproduced
through the schematic's own runner: an `if` branch holding a real `KbqReadStateDirective` and an
`else` branch holding `{ mouseenterHandler() {} }` both came back as `startDwell()`, silently
breaking the second. A local is visible in its block, so that is what it is scoped to now —
including case and default clauses and module blocks, which are bindings' scopes too but are not
`Block` nodes.
Both migrations also visited every `.ts`, `.d.ts` and `.ngtypecheck.ts` included. A declaration
file has no call sites for the rewriting one to touch and only restates the API the reporting one
warns about, so the first can gain nothing there and the second can only produce noise about the
consumer's own typings. `deprecated-icons` and `new-icons-pack` already skip both.
Raised by Copilot on #1943; the scoping half is its find, verified before acting on it.
…v app roots Reported on the deploy preview: the notification-center overview page throws NG0201 on load. Same defect this branch already fixed for the e2e and dev-ssr apps, in the two roots it missed. `KbqNotificationCenterService` is `providedIn: 'root'` and injects `DateAdapter` and `DateFormatter` without `optional`. Neither has a root provider — `DateAdapter` is an abstract class and `DateFormatter` carries no `providedIn` — and importing the modules into a component, which is what both the docs example and the dev app did, serves that component's own injections and never the root singleton's. Reproduced in the dev app, where the message is not minified: "No provider found for `DateAdapter`". With the providers at the root the panel renders its 30 notifications with formatted headings and times. The docs app already binds the locale service, so it takes the bare `LuxonDateModule`; the dev app has none, so it keeps `KbqLuxonDateModule` and drops the now-redundant component imports.
Summary
The review found one crash-class defect and two release-blocking keyboard failures. A notification
whose
datethe configuredDateAdaptercould not parse madeformat(null)throw inside thegroupedItemsmap, erroring the observable and permanently blanking the panel — reopeningresubscribed to the same dead pipe. Separately, the per-item delete buttons were
display: noneuntil:hover, while being the only focusable element in their container, so a keyboard user could notdelete anything.
Two
ng updatemigrations ship with this branch.List of notable changes:
compareByDateDescalready guarded exactly this casecomputing but never installing — Tab escaped the overlay and host-scoped Escape then went dead
closingActions()subscription throwinga
TypeErroron every subsequent scroll anywhere in the appCdkScrollableinstanceswithout resetting them and silently broke
closeOnScrollfor other overlays app-widenotification-center-signalsandread-state-dwell-handlers—for the renamed surface and the removed
mouseenterHandler/mouseleaveHandlerkeyboard focus ring, because the call hardcoded
'keyboard'. It now uses the real input modalityvia
InputModalityDetector, the same rule asKbqBasePipe.currentFocusOrigin— not FocusMonitor'slast origin, which reports
programfor a click landing outside its detection windowWhat should reviewers focus on?
packages/schematics/src/migrations/and their registration incollection.json/migrations.json.packages/components/core/common-behaviors/read-state.tsis shared with toast — that consumer suiteruns green here, but the toast branch touches the same file.
KBQ_NOTIFICATION_CENTER_DEFAULT_CONFIGURATION,KBQ_NOTIFICATION_CENTER_SCROLL_STRATEGY,mouseenterHandler,mouseleaveHandler,timestamp./approve-snapshotshere.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).