Section headings ("Beheer" / organisation name, "Platform") were
already uppercase + muted but read as bold paragraph dividers more
than as quiet group markers. Tighten letter-spacing, drop weight
from semibold to medium, lighten the color one step (surface-500 →
surface-400), and shrink text to 11px so the headings recede and
let the nav items themselves carry the visual weight.
Spacing nudged from mt-4/mb-2/px-2 → mt-6/mb-1/px-3: more breathing
room above each group, less below (the items already have py-2 on
top), and the heading left-edge now lines up with the icons of the
nav items beneath it (both at px-3).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Introduces SidebarHeader.vue — a PrimeVue-only org-switcher that
replaces the centered Crewli wordmark at the top of the sidebar. The
component mirrors the legacy Vuetify OrganisationSwitcher (avatar with
org initials, organisation name, plan-tier placeholder, dropdown
chevron, PrimeVue Menu of available orgs) but cannot reuse it
directly per the R-10 layout-shell-isolation invariant.
Plan-tier shows a hardcoded "Pro" placeholder until the backend
Organisation resource exposes a plan field — tracked separately, not
in F3.5 scope. When the user has no active organisation (portal
users, fresh super_admin), the component degrades to the original
title block so PortalLayout continues to read "Crewli Portal".
Desktop sidebar width bumped w-64 → w-72 (256 → 288 px) to give the
org-switcher card breathing room and accommodate the user-info card
arriving in B3. Mobile Drawer width bumped 16rem → 18rem to match.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Layout-shell rewrite per RFC AD-3, B7-option-B. R-10 isolation invariant
honored — this single commit is revertible to roll back the layout
change without losing B1–B6 progress.
New component (PrimeVue-only, no Vuetify imports per F3 hard constraint):
- apps/app/src/layouts/components/AppShell.vue (~210 lines)
- Desktop sidebar (Tailwind grid, lg+ breakpoint) renders nav items
as PrimeVue Buttons + Icons. Mobile (<lg) hides sidebar; PrimeVue
Drawer slides in on hamburger toggle.
- Top bar (Tailwind) has hamburger + title (mobile) and an Avatar +
Menu (PrimeVue) for the user dropdown with "Mijn Profiel" and
"Uitloggen" actions.
- Nav items accept the existing { title, to: { name }, icon: { icon } }
shape from src/navigation/vertical so call-sites stay terse.
Five top-level layouts delegate to AppShell (filename preserved per
AD-3 so vite-plugin-vue-meta-layouts continues to resolve routes
unchanged):
- default.vue — org + (super-admin) platform nav
- OrganizerLayout — same nav as default; matches authenticated org UX
- PortalLayout — portal-specific 2-item nav ("Mijn evenementen",
"Mijn Profiel")
- blank.vue — minimal chrome-less wrapper for login etc.
- PublicLayout — minimal wrapper for public form-fill routes;
uses <main> for semantic structure
F3 functional regressions (intentional — F4 sub-packages reintroduce
each item through PrimeVue):
- NavSearchBar (Vuetify-heavy combobox/overlay) — absent from top bar
- ContextSwitcher (Vuetify VBtn + VMenu) — absent
- NavbarThemeSwitcher (Vuetify IconBtn) — absent; dark mode driven by
PrimeVue's darkModeSelector: '.dark' continues to work via the
existing @core skin classes until F6 cleanup
- NavbarShortcuts (Vuetify-heavy) — absent
- NavBarNotifications (Vuetify-heavy) — absent
- UserProfile from @/layouts/components/ (Vuetify-heavy menu) — replaced
with the minimal Avatar + Menu dropdown described above; rich profile
panel returns in F4
- ImpersonationBanner — absent; super-admin impersonation UX is F4 work
- PortalLayout event-mode vs platform-mode topbar (route.meta.navMode
driven) — absent; F4 reintroduces via AppShell prop or slot
- Suspense + AppLoadingIndicator wrapping pages — dropped; pages handle
their own loading via PrimeVue ProgressSpinner
VApp at App.vue level still wraps everything, so Vuetify components
inside still-Vuetify pages continue to render correctly during the
parallel-mode window.
Test updates (no Vuetify in layout structure to assert against anymore):
- OrganizerLayout.spec.ts — mocks AppShell instead of the deleted
DefaultLayoutWithVerticalNav reference; provides Pinia.
- PortalLayout.spec.ts — same mock pattern; new structural assertions
go through AppShell stub; the new third test verifies
PortalLayout forwards portal nav items + title to AppShell.
- PublicLayout.vue — uses <main> for semantics; PublicLayout.spec.ts
still passes unchanged.
Auto-generated component/auto-import dts files refreshed for the new
AppShell component (committed for stable dev workflow).
Verification:
- pnpm typecheck — clean.
- pnpm test — 402 tests pass (test count unchanged after spec rewrites).
- pnpm build — succeeds in 14.05s; AppShell chunk is ~57 KB raw.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>