feat(portal-shell): app-shell layout with collapsable sidebar
CI / commits (pull_request) Successful in 1m39s
CI / scan (pull_request) Successful in 1m51s
CI / check (pull_request) Successful in 2m10s
CI / a11y (pull_request) Successful in 1m9s
CI / perf (pull_request) Successful in 2m7s

Switch the SPA from header+main+footer to a fixed header above a
sidebar/main split. The sidebar carries grouped navigation, can be
collapsed to an icon-only rail (state persisted in localStorage), and
hosts the accessibility-statement links the footer used to own. Adds
brand palette tokens (primary teal #12546c, accent orange #f7a919) as
Tailwind v4 @theme entries, an <app-icon> façade over lucide-angular
so the future icomoon sprite migration is a single-file change, and
the APF logo asset under public/logos/.

Menu data is static for v1 — items point to '#' placeholders, with the
Dashboard entry routerLink-bound so the active-state styling is
visible on the home page. The MenuItem shape already carries an
optional requiredPermissions field so the permission-aware filter (to
land alongside the auth flow per ADR-0009) plugs in without
restructuring. WCAG-relevant choices preserved: skip-link, role/aria
landmarks, aria-current="page" on active links, aria-expanded on the
toggle, prefers-reduced-motion respected on width transitions, and a
44px minimum hit-target on every interactive element (ADR-0016).

Footer component removed — its links migrated to the sidebar bottom.
This commit is contained in:
Julien Gautier
2026-05-11 00:17:15 +02:00
parent a463199728
commit c144cdcbd5
21 changed files with 683 additions and 105 deletions
+15
View File
@@ -107,6 +107,9 @@ importers:
class-validator:
specifier: ^0.15.1
version: 0.15.1
lucide-angular:
specifier: ^1.0.0
version: 1.0.0(@angular/common@21.2.12(@angular/core@21.2.12(@angular/compiler@21.2.12)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.12(@angular/compiler@21.2.12)(rxjs@7.8.2)(zone.js@0.16.2))
nestjs-cls:
specifier: ^6.2.0
version: 6.2.0(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(reflect-metadata@0.2.2)(rxjs@7.8.2)
@@ -7360,6 +7363,12 @@ packages:
resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==}
engines: {node: '>=12'}
lucide-angular@1.0.0:
resolution: {integrity: sha512-YxCNEXHUz2IzAZIlxU4CkD55ljMjOlm3/am4eqadX/qkFszyGDzZwtbWOP1wj6vlbn/BNL4RhJeXbusLz96ajg==}
peerDependencies:
'@angular/common': 13.x - 21.x
'@angular/core': 13.x - 21.x
luxon@3.7.2:
resolution: {integrity: sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==}
engines: {node: '>=12'}
@@ -18408,6 +18417,12 @@ snapshots:
lru-cache@7.18.3: {}
lucide-angular@1.0.0(@angular/common@21.2.12(@angular/core@21.2.12(@angular/compiler@21.2.12)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.12(@angular/compiler@21.2.12)(rxjs@7.8.2)(zone.js@0.16.2)):
dependencies:
'@angular/common': 21.2.12(@angular/core@21.2.12(@angular/compiler@21.2.12)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2)
'@angular/core': 21.2.12(@angular/compiler@21.2.12)(rxjs@7.8.2)(zone.js@0.16.2)
tslib: 2.8.1
luxon@3.7.2: {}
magic-string@0.25.7: