Third attempt, done properly this time - first two were reverted (one stopped cleanly on real conflicts, one botched sequencing and deleted the old focus-trap before finishing the swap). DialogComponent gains closeOnEscape/closeOnBackdropClick (default true, backward-compatible with its 13 other call sites) and ariaLabel (for dialogs with no visible title header). FOCUSABLE_SELECTOR now includes iframe for the bank-payment panel's focus trap. Cart wires closeOnBackdropClick=false on both dialogs (in-flight payment shouldn't cancel on a stray click) and closeOnEscape tied to the bank popup's open state, so Escape closes the nested bank iframe first and falls back to the QR view - matches the original priority exactly. Original geometry (500px QR modal/40px padding, 960x760 bank modal/ 56-16-16 padding, both mobile breakpoints) preserved via :host ::ng-deep overrides scoped per dialog instance - same pattern already used by product-carousel-widget.component.ts. cart.component.ts loses ~90 lines of hand-rolled ViewChild/HostListener/ focus-trap code - app-dialog owns all of it now. Verified live in browser: dialog sizing/padding/aria-label correct at mobile+desktop, backdrop-click confirmed inert, Escape-priority confirmed (bank closes first, then QR), initial focus lands on close button. 83/83 tests pass, tsc/build clean. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
4.4 KiB
Future Features
Nice-to-have, non-blocking work — no client decision needed, just not worth doing now. Verified against current repo state 2026-07-26.
Cart payment modal → app-dialog migration
Done, 2026-08-06. .payment-modal/.bank-payment-modal on the cart page now render through the shared app-dialog primitive instead of hand-rolled overlays. Two earlier same-session attempts were reverted before landing (one stopped cleanly after finding real conflicts, one botched the sequencing — deleted the old focus-trap before finishing the swap); this pass fixed the actual API gaps first, then migrated, then verified live in a browser before shipping:
DialogComponentgainedcloseOnEscape/closeOnBackdropClickinputs (defaulttrue, backward-compatible with its other 13 call sites) and anariaLabelinput (for dialogs with no visible title header — cart's modals render their own close button in content instead).FOCUSABLE_SELECTORnow includesiframe(needed for the bank-payment panel's focus trap).- Cart wires
[closeOnBackdropClick]="false"on both dialogs (in-flight payment shouldn't cancel on a stray click) and[closeOnEscape]="!showBankPaymentPopup()"on the QR/status dialog (so Escape closes the bank iframe first, falls back to the QR view, matches the original nested-modal priority). - Exact original geometry (500px QR modal, 40px padding; 960×760 bank iframe modal, 56/16/16 padding, both mobile breakpoints) preserved via
:host ::ng-deepoverrides on.app-dialog-panel/.app-dialog-panel__body/.app-dialog-backdrop, scoped per-instance via.payment-dialog/.bank-payment-dialoghost classes — same::ng-deeppattern already used byproduct-carousel-widget.component.ts. cart.component.tslost its hand-rolled@ViewChild/@HostListener/focus-trap methods (~90 lines) —app-dialogowns all of that now.- Verified live: both dialogs render at correct size/padding/aria-label at mobile and desktop breakpoints, backdrop-click confirmed inert, Escape-priority confirmed (closes bank first, then QR), initial focus confirmed landing on the close button. 83/83 tests pass, tsc/build clean.
Angular 22 upgrade
Researched, not executed. Estimated ~2–3.5 days, needs the barry-cache dependency fix and a Node version bump first. Explicitly out of scope for the Backend Finalization Sprint. Plan: docs/ANGULAR22_PLAN.md.
Bundle splitting
Initial (eagerly-loaded) bundle carries an ~11 MB chunk that is the entire @lucide/angular icon set, confirmed 2026-08-05 by inspecting build output — app-icon/IconComponent only ever needs the ~85 icons named in icon-registry.ts, but esbuild is not eliminating the other ~1500+ unused icon classes from @lucide/angular's single-file fesm2022/lucide-angular.mjs bundle, despite the package declaring sideEffects: false and every usage in this codebase being clean named imports (no wildcard imports found). Root cause not fully diagnosed — likely each icon's Angular component metadata assignment isn't PURE-annotated in that build, so esbuild can't drop unreferenced classes within the single shared module even though it can drop unreferenced exports. The package ships no per-icon deep-import path as a workaround (single fesm file only). Real fix options, neither attempted here (touches a dependency, needs sign-off): (a) check for a newer @lucide/angular release with better tree-shaking, (b) drop the dependency and hand-roll inline SVG path data for just the ~85 used icons (removes a dependency, matches this repo's minimal-deps convention, but is real work — extracting/verifying 85 icon paths). This alone is roughly 6x the size of the two lazy chunks below combined and, unlike them, ships to every visitor on first load.
Two lazy chunks are also large: project-editor (~1.0 MB), catalog-container (~330–375 kB, varies by build). No mechanical split found yet for either — needs a dedicated profiling task, ideally under real backend latency per docs/NEXT_PHASE.md Phase 3.
Homepage hero-to-categories spacing investigation
A dead-space gap between the hero and categories section on the storefront home page traces to bootstrap mock config (widget/section padding values in the dev fixture), not a confirmed code defect. Needs reproduction with real tenant data before it's worth investigating further — not a bug until it's confirmed to happen outside the mock fixture.