feat(gui-v2): port SidebarNav to TypeScript
Ports crewli-starter's sidebar nav into the SPA as production TS: V2NavGroup/V2NavItem types, a pure toV2NavGroups adapter wrapped by useV2Nav(items) (composables zone can't import @/navigation, so the v1 nav array is passed in — the layout supplies orgNavItems in Task 7), a pure isNavItemActive helper, and SidebarNav.vue (props-only, router-driven nav, route-based active state, collapsed mode, main.css translated to Tailwind inline). 16 unit tests. Icon import is allowed via the components-foundation bridge (no eslint-disable). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
37
apps/app/src/components-v2/layout/sidebarNavActive.ts
Normal file
37
apps/app/src/components-v2/layout/sidebarNavActive.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import type { V2NavItem } from '@/types/v2/nav'
|
||||
|
||||
/**
|
||||
* Pure helper — determines whether a V2NavItem is "active" given the current
|
||||
* route name.
|
||||
*
|
||||
* Active rules (simplest correct definition):
|
||||
* 1. Exact match: currentRouteName === item.to.name
|
||||
* 2. Prefix match for nested routes: currentRouteName starts with
|
||||
* item.to.name + '-' (e.g. item "organisation" is active on
|
||||
* "organisation-settings"). The dash boundary prevents "org" from
|
||||
* spuriously matching "organisation-settings".
|
||||
*
|
||||
* Only `to` values that are a plain object with a string `name` property are
|
||||
* compared — string/array `to` values always return false (router-push
|
||||
* style not used in v1 nav).
|
||||
*/
|
||||
export function isNavItemActive(
|
||||
item: V2NavItem,
|
||||
currentRouteName: string | symbol | null | undefined,
|
||||
): boolean {
|
||||
if (typeof currentRouteName !== 'string')
|
||||
return false
|
||||
|
||||
const to = item.to
|
||||
|
||||
if (typeof to !== 'object' || to === null || Array.isArray(to))
|
||||
return false
|
||||
|
||||
const itemName = (to as { name?: unknown }).name
|
||||
|
||||
if (typeof itemName !== 'string')
|
||||
return false
|
||||
|
||||
return currentRouteName === itemName
|
||||
|| currentRouteName.startsWith(`${itemName}-`)
|
||||
}
|
||||
Reference in New Issue
Block a user