feat(portal-shell): app-shell layout with collapsable sidebar #83
Reference in New Issue
Block a user
Delete Branch "feat/portal-shell/app-shell-layout"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
localStorage.@themetokens (primary teal#12546c, accent orange#f7a919) so every utility (bg-brand-primary-500,text-brand-accent-400,ring-brand-primary-200, …) is available from now on.<app-icon>façade backed bylucide-angularfor v1. Logical kebab-case names already match the icomoon-sprite convention, so the future migration is a single-file change inicon.tsand consumers stay untouched.Decisions worth flagging
#placeholders in v1, except Dashboard which isrouterLink="/"so the active-state styling is visible on the home page. TheMenuItemshape already carries an optionalrequiredPermissions: string[]so the permission-aware filter (PR 2, alongside ADR-0009 auth) plugs in without restructuring.<app-icon>over direct lucide imports. Consumers write<app-icon name="bell">rather than importing the lucide pascal-case symbol. When the icomoon sprite lands, only the registry inicon.tschanges — templates do not.localStorage, not backend. Zero round-trip, survives reloads, falls back gracefully when storage is blocked (private mode). Eventually mirrored server-side if the user-preferences feature lands.Accessibility (ADR-0016)
<nav aria-label="Sections">,<nav aria-label="Accessibility">) and the collapse button usesaria-expanded+ a descriptivearia-label.ariaCurrentWhenActive="page".prefers-reduced-motion: reduce.aria-hidden(decorative); accessible names live on the parent control.Perf (ADR-0017)
What this PR explicitly does NOT do
<app-icon>).Test plan
pnpm exec nx run-many -t lint test build --projects=portal-shell— green (19 / 19 specs)./, confirm Dashboard appears active in the sidebar, collapse → reload → still collapsed, focus the address bar then Tab → skip-link visible, keyboard-traverse the sidebar.prefers-reduced-motion: reduce→ no width animation when toggling.md:breakpoint).