useNavigation
The useNavigation composable provides utilities for handling navigation menu items, breadcrumbs, active states, and permission-based filtering. It automatically generates and syncs breadcrumb trails from the navigation structure.
TIP
This composable integrates with the breadcrumbs store and automatically syncs breadcrumb data on route changes.
Features
- Role and permission-based filtering for navigation items
- Active state detection for menu highlighting
- Automatic breadcrumb generation from navigation structure
- Auto-sync with breadcrumbs store on route changes
- Hierarchical navigation support with parent/grandparent tracking
- Localization support via i18n
- Partial path matching for detail pages
Usage
Basic Usage
ts
const { navigationItems, isItemActive, breadcrumbTrail, currentPageTitle } =
useNavigation();Navigation Menu
vue
<script setup lang="ts">
const { navigationItems, isItemActive, isItemOpen } = useNavigation();
</script>
<template>
<nav>
<ul>
<li
v-for="item in navigationItems"
:key="item.href"
:class="{ active: isItemActive(item), open: isItemOpen(item) }"
>
<NuxtLink :to="item.href">
{{ item.label }}
</NuxtLink>
</li>
</ul>
</nav>
</template>Breadcrumb Display
vue
<script setup lang="ts">
const { breadcrumbTrail, currentPageTitle } = useNavigation();
</script>
<template>
<nav aria-label="Breadcrumb">
<ol>
<li v-for="(item, index) in breadcrumbTrail" :key="item.href">
<NuxtLink v-if="index < breadcrumbTrail.length - 1" :to="item.href">
{{ item.label }}
</NuxtLink>
<span v-else>{{ item.label }}</span>
</li>
</ol>
</nav>
</template>Parent/Grandparent Navigation
vue
<script setup lang="ts">
const { currentParent, currentGrandparent } = useNavigation();
</script>
<template>
<div v-if="currentParent">
<NuxtLink :to="currentParent.link">
← Back to {{ currentParent.title }}
</NuxtLink>
</div>
<div v-if="currentGrandparent">
<NuxtLink :to="currentGrandparent.link">
{{ currentGrandparent.title }}
</NuxtLink>
</div>
</template>API
Return Type
ts
interface UseNavigationReturnType {
navigationItems: ComputedRef<NavigationItem[]>;
isItemActive: (item: NavigationItem) => boolean;
isItemOpen: (item: NavigationItem) => boolean;
breadcrumbTrail: ComputedRef<NavigationItem[]>;
currentPageTitle: ComputedRef<string>;
currentParent: ComputedRef<{ title: string; link: string } | null>;
currentGrandparent: ComputedRef<{ title: string; link: string } | null>;
}Properties
navigationItems
- Type:
ComputedRef<NavigationItem[]> - Description: Filtered navigation items based on user roles and permissions
- Details: Items without roles/permissions are visible to all users. Recursively filters children and removes parent items with no visible children.
isItemActive
- Type:
(item: NavigationItem) => boolean - Description: Checks if a navigation item is currently active
- Logic: An item is active if:
- The current route matches its
href - Any of its children match the current route
- The current route matches its
isItemOpen
- Type:
(item: NavigationItem) => boolean - Description: Checks if a navigation item should be open (has active children)
breadcrumbTrail
- Type:
ComputedRef<NavigationItem[]> - Description: Breadcrumb trail for current route, auto-derived from navigation structure
- Details: Returns array of NavigationItems from root to current page. Supports partial path matching for detail pages (e.g.,
/customers/company/123matches/customers/company/list)
currentPageTitle
- Type:
ComputedRef<string> - Description: Current page title from navigation structure
- Details: Returns the label of the last item in the breadcrumb trail
currentParent
- Type:
ComputedRef<{ title: string; link: string } | null> - Description: Parent navigation item
- Details: Returns the second-to-last item in the breadcrumb trail. Returns
nullif trail has fewer than 2 items.
currentGrandparent
- Type:
ComputedRef<{ title: string; link: string } | null> - Description: Grandparent navigation item
- Details: Returns the third-to-last item in the breadcrumb trail. Returns
nullif trail has fewer than 3 items.
Navigation Structure
The navigation structure is defined in app/lib/navigation.ts and includes:
ts
interface NavigationItem {
label: string; // Display text (localized)
href: string; // Route path
icon?: Component; // Optional icon component
roles?: string[]; // Required user roles
permissions?: string[]; // Required permissions
children?: NavigationItem[]; // Nested items
}Example Navigation Config
ts
export const getNavigation = (
t: (key: string, count?: number) => string,
): NavigationItem[] => [
{
label: t('home'),
href: '/',
icon: HomeIcon,
},
{
label: t('customer', 2),
href: '/customers',
icon: UsersIcon,
children: [
{
label: t('company', 2),
href: '/customers/company/list',
},
],
},
];Automatic Breadcrumb Sync
The composable automatically syncs breadcrumbs to the breadcrumbs store on route changes:
ts
watch(
breadcrumbTrail,
(newTrail) => {
breadcrumbsStore.setNavigationBreadcrumbs(newTrail);
},
{ immediate: true },
);The store can override individual breadcrumbs if needed for custom page titles or dynamic content.
Path Matching Algorithm
The breadcrumb trail finder uses intelligent path matching:
- Exact match priority: Exact path matches are preferred
- Depth-first search: Children are checked before siblings (prefers deeper exact matches)
- Partial matching: For detail pages, removes
/listsuffix and checks if target path starts with the base - Longest match wins: When multiple partial matches exist, the longest one is selected
Example:
- Route:
/customers/company/123 - Matches:
/customers/company/list(base:/customers/company) - Trail:
Home > Customers > Companies
Integration with Breadcrumbs Store
The composable works seamlessly with useBreadcrumbsStore:
ts
const breadcrumbsStore = useBreadcrumbsStore();
// Set navigation config (done automatically)
breadcrumbsStore.setNavigationConfig(navigationConfig);
// Auto-sync breadcrumbs (done automatically)
breadcrumbsStore.setNavigationBreadcrumbs(breadcrumbTrail.value);
// Override breadcrumbs manually if needed
breadcrumbsStore.setBreadcrumbs([{ label: 'Custom', href: '/custom' }]);Best Practices
- Define navigation once: Use
app/lib/navigation.tsas single source of truth - Use localization keys: Always use
t()function for labels - Consistent paths: Ensure navigation
hrefvalues match route paths - Permission filtering: Add
rolesandpermissionsarrays to restrict access - List suffix convention: Use
/listsuffix for list views to enable partial matching
Related
- Breadcrumbs Store
- User Store (for role/permission checks)