Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions app/app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,17 @@ onNuxtReady(() => loadSearchSections())

const nuxtApp = useNuxtApp()
const navTree = computed<NavigationItem[]>(() => prefixNavigation(navigation.value ?? [], content.value.base))
const navigationLayout = ref(findNavigationLayout(navTree.value, route.path))
const resolveNavigationLayout = () => {
if (route.meta.layout === false) return undefined
if (route.meta.layout === 'docs' || route.meta.layout === 'page') return route.meta.layout
const layout = findNavigationLayout(navTree.value, route.path)
if (!layout && route.matched?.[0]?.name === 'slug') return 'docs'
return layout
}
const navigationLayout = ref(resolveNavigationLayout())
onNuxtReady(() => {
nuxtApp.hook('page:finish', () => {
navigationLayout.value = findNavigationLayout(navTree.value, route.path)
navigationLayout.value = resolveNavigationLayout()
})
})
const searchFiles = computed<SearchSection[]>(() =>
Expand Down Expand Up @@ -99,9 +106,7 @@ defineShortcuts({
<LayoutsDocs v-else-if="navigationLayout === 'docs'">
<NuxtPage />
</LayoutsDocs>
<UContainer v-else>
<NuxtPage />
</UContainer>
<NuxtPage v-else />
</Suspense>
</UMain>

Expand Down
8 changes: 8 additions & 0 deletions app/types/navigation-layout.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
declare module 'nuxt/app' {
interface NuxtLayouts {
docs: Record<string, never>
page: Record<string, never>
}
}

export {}
4 changes: 2 additions & 2 deletions app/utils/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export function findNavigationLayout(
navigation: NavigationItem[] | undefined | null,
path: string | undefined
): NavigationLayout | undefined {
if (!navigation?.length || !path || path === '/') return undefined
if (!navigation?.length || !path) return undefined

let layout: NavigationLayout | undefined
const visit = (items: NavigationItem[]) => {
Expand All @@ -56,7 +56,7 @@ export function findNavigationLayout(
}

visit(navigation)
return layout || 'docs'
return layout
}

/** Trail of navigation items leading to `path`, including the page itself. */
Expand Down
10 changes: 9 additions & 1 deletion eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,15 @@ export default createConfigForNuxt({
// `index.vue`, `docs.vue`, `[...slug].vue` are the framework's naming, not ours.
// `Browser.vue` is exempt for a different reason: it's addressed from markdown
// (`::browser`), so its name is part of the content API.
files: ['app/pages/**/*.vue', 'app/layouts/**/*.vue', 'app/error.vue', 'app/components/Browser.vue'],
files: [
'app/pages/**/*.vue',
'playground/app/pages/**/*.vue',
'app/layouts/**/*.vue',
'playground/app/layouts/**/*.vue',
'app/error.vue',
'playground/app/error.vue',
'app/components/Browser.vue',
],
rules: {
'vue/multi-word-component-names': 'off',
},
Expand Down
3 changes: 3 additions & 0 deletions playground/app/pages/full.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<template>
<div>This page is a custom vue page and should not have any layout</div>
</template>
8 changes: 4 additions & 4 deletions test/navigation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ describe('findNavigationLayout', () => {
})

it('does not inherit a layout from a partial path segment match', () => {
expect(findNavigationLayout(navigation, '/examples-extended/page')).toBe('docs')
expect(findNavigationLayout(navigation, '/examples-extended/page')).toBeUndefined()
})

it('supports navigation paths prefixed for version previews', () => {
Expand All @@ -122,12 +122,12 @@ describe('findNavigationLayout', () => {
expect(findNavigationLayout(previewNavigation, '/tree/feature/examples/overview')).toBe('page')
})

it('falls back to docs without a matching supported layout', () => {
expect(findNavigationLayout(navigation, '/unknown')).toBe('docs')
it('returns undefined without a matching supported layout', () => {
expect(findNavigationLayout(navigation, '/unknown')).toBeUndefined()
expect(findNavigationLayout(
[{ title: 'Custom', path: '/custom', layout: 'custom' }] as unknown as NavigationItem[],
'/custom'
)).toBe('docs')
)).toBeUndefined()
})

it('returns undefined for the landing page or without enough navigation context', () => {
Expand Down
Loading