From 1619d6a277190d5c12790aa5da0c2aba5ad7b27e Mon Sep 17 00:00:00 2001 From: "bert.hausmans" Date: Wed, 3 Jun 2026 14:10:57 +0200 Subject: [PATCH 1/2] fix(storybook): register v2-dashboard route so AppSidebar stories render The story router only knew the pre-v2 route names, so SidebarNav's RouterLink to the v2-prefixed 'v2-dashboard' threw 'No match for' and the Storybook error boundary replaced every AppSidebar story. Add 'v2-dashboard' to the story router's known names. Co-Authored-By: Claude Opus 4.8 --- apps/app/.storybook/preview.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/app/.storybook/preview.ts b/apps/app/.storybook/preview.ts index a263f5cd..7c7cff19 100644 --- a/apps/app/.storybook/preview.ts +++ b/apps/app/.storybook/preview.ts @@ -15,6 +15,9 @@ const routeNames = [ 'organisation-companies', 'organisation-form-failures', 'organisation-settings', 'platform', 'platform-organisations', 'platform-users', 'platform-form-failures', 'platform-activity-log', + // v2 shell nav targets (APP_NAVIGATION uses v2-prefixed route names) — + // without these, AppSidebar/SidebarNav RouterLinks throw "No match for". + 'v2-dashboard', ] export const storyRouter = createRouter({ -- 2.39.5 From 4fa53a18610836b45204fed8ebf1162c5ba77a43 Mon Sep 17 00:00:00 2001 From: "bert.hausmans" Date: Wed, 3 Jun 2026 14:10:58 +0200 Subject: [PATCH 2/2] fix: group mobile drawer sections, drop the bottom-pinned void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the mobile drawer the nav's flex-1 filled the full-height panel, pushing the WorkspaceSwitcher to the very bottom and leaving a large empty void between the menu and the switcher. Add a 'grow' prop to SidebarNav (default true = desktop bottom-anchor) and pass grow=false in the mobile drawer so the nav takes only its natural height — logo, menu and switcher group together at the top. Desktop sidebar unchanged. +2 Vitest assertions for the contract. Co-Authored-By: Claude Opus 4.8 --- .../src/components-v2/layout/AppSidebar.vue | 5 ++- .../src/components-v2/layout/SidebarNav.vue | 21 ++++++++++-- .../layout/__tests__/AppSidebar.spec.ts | 33 +++++++++++++++++-- 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/apps/app/src/components-v2/layout/AppSidebar.vue b/apps/app/src/components-v2/layout/AppSidebar.vue index 36cdddcc..b31288c7 100644 --- a/apps/app/src/components-v2/layout/AppSidebar.vue +++ b/apps/app/src/components-v2/layout/AppSidebar.vue @@ -165,7 +165,10 @@ const mobileVisible = computed({ }" > - + diff --git a/apps/app/src/components-v2/layout/SidebarNav.vue b/apps/app/src/components-v2/layout/SidebarNav.vue index 8fb82563..05639afd 100644 --- a/apps/app/src/components-v2/layout/SidebarNav.vue +++ b/apps/app/src/components-v2/layout/SidebarNav.vue @@ -22,9 +22,21 @@ import type { RouteLocationRaw } from 'unplugin-vue-router' import Icon from '@/components/Icon.vue' import { APP_NAVIGATION, type NavItem } from '@/config/navigation' -defineProps<{ +withDefaults(defineProps<{ collapsed: boolean -}>() + /** + * When true (default), the nav fills available vertical space (`flex-1`) + * so a bottom-anchored sibling (WorkspaceSwitcher) pins to the bottom — the + * desktop sidebar behaviour. Set false in the mobile drawer (`flex-initial`) + * so the nav takes its natural height — logo + menu + switcher group together + * at the top instead of leaving a void above a bottom-pinned switcher + * (MOBILE-SHELL-PARITY follow-up). `flex-initial` (not `flex-none`) keeps + * `flex-shrink: 1`, so if the menu ever grows past the panel height the nav + * shrinks and scrolls internally (`min-h-0 overflow-y-auto`) rather than + * pushing the switcher out of the `overflow-hidden` drawer content. + */ + grow?: boolean +}>(), { grow: true }) const route = useRoute() @@ -52,7 +64,10 @@ function itemTo(item: NavItem): RouteLocationRaw {