@sit-onyx/nuxt-docs 0.1.0 → 0.2.0-dev-20251229091238
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,41 +1,59 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
import type {
|
|
2
|
+
import type { SidebarNavigationItem } from "../composables/useSidebarNavigation.js";
|
|
3
3
|
|
|
4
4
|
const props = defineProps<{
|
|
5
|
-
item:
|
|
5
|
+
item: SidebarNavigationItem;
|
|
6
6
|
}>();
|
|
7
7
|
|
|
8
|
-
const
|
|
8
|
+
const route = useRoute();
|
|
9
9
|
|
|
10
10
|
const isAccordionOpen = ref(true);
|
|
11
|
+
watch(
|
|
12
|
+
() => props.item.sidebar?.collapsed,
|
|
13
|
+
(collapsed) => {
|
|
14
|
+
isAccordionOpen.value = !collapsed;
|
|
15
|
+
},
|
|
16
|
+
{ immediate: true },
|
|
17
|
+
);
|
|
11
18
|
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
19
|
+
const isChildActive = computed(() => {
|
|
20
|
+
const isActive = (item: SidebarNavigationItem): boolean => {
|
|
21
|
+
if (item.path === route.path) return true;
|
|
22
|
+
return item.children?.some(isActive) ?? false;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// ensure accordion is open if any child route is currently active
|
|
26
|
+
return props.item.children?.some(isActive) ?? false;
|
|
15
27
|
});
|
|
28
|
+
|
|
29
|
+
watch(
|
|
30
|
+
isChildActive,
|
|
31
|
+
(isActive) => {
|
|
32
|
+
// ensure accordion is open if any child route is currently active
|
|
33
|
+
// e.g. when reloading the page or navigating via global search
|
|
34
|
+
if (isActive) isAccordionOpen.value = true;
|
|
35
|
+
},
|
|
36
|
+
{ immediate: true },
|
|
37
|
+
);
|
|
16
38
|
</script>
|
|
17
39
|
|
|
18
40
|
<template>
|
|
19
|
-
<OnyxSidebarItem v-if="!children" class="sidebar-item" :link="
|
|
41
|
+
<OnyxSidebarItem v-if="!props.item.children?.length" class="sidebar-item" :link="props.item.path">
|
|
20
42
|
{{ props.item.title }}
|
|
21
43
|
</OnyxSidebarItem>
|
|
22
44
|
|
|
23
45
|
<OnyxAccordion
|
|
24
46
|
v-else
|
|
25
|
-
:model-value="isAccordionOpen ? [
|
|
47
|
+
:model-value="isAccordionOpen ? [props.item.path] : undefined"
|
|
26
48
|
class="sidebar-accordion"
|
|
27
49
|
type="nested-large"
|
|
28
50
|
@update:model-value="isAccordionOpen = !isAccordionOpen"
|
|
29
51
|
>
|
|
30
|
-
<OnyxAccordionItem :value="
|
|
52
|
+
<OnyxAccordionItem :value="props.item.path">
|
|
31
53
|
<template #header>{{ props.item.title }}</template>
|
|
32
54
|
|
|
33
55
|
<div class="sidebar-item__children">
|
|
34
|
-
<OnyxSidebarItem
|
|
35
|
-
v-for="child in children"
|
|
36
|
-
:key="localePath(child.path)"
|
|
37
|
-
:link="localePath(child.path)"
|
|
38
|
-
>
|
|
56
|
+
<OnyxSidebarItem v-for="child in props.item.children" :key="child.path" :link="child.path">
|
|
39
57
|
{{ child.title }}
|
|
40
58
|
</OnyxSidebarItem>
|
|
41
59
|
</div>
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { Collections, ContentNavigationItem } from "@nuxt/content";
|
|
2
|
+
|
|
3
|
+
export type SidebarNavigationItem = {
|
|
4
|
+
title: string;
|
|
5
|
+
/**
|
|
6
|
+
* Item path. Already localized for i18n with `useLocalePath`.
|
|
7
|
+
*/
|
|
8
|
+
path: string;
|
|
9
|
+
children?: SidebarNavigationItem[];
|
|
10
|
+
sidebar?: SidebarNavigationOptions;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Custom navigation options. Can be set via the `.navigation.yml` file inside of a content folder.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```yaml
|
|
18
|
+
* # .navigation.yml
|
|
19
|
+
* sidebar:
|
|
20
|
+
* root: true
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export type SidebarNavigationOptions = {
|
|
24
|
+
/**
|
|
25
|
+
* Whether this item is considered the root of the sidebar.
|
|
26
|
+
* If true, items above this one will be filtered out.
|
|
27
|
+
*/
|
|
28
|
+
root?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Whether children should be initially collapsed.
|
|
31
|
+
*/
|
|
32
|
+
collapsed?: boolean;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const useSidebarNavigation = async () => {
|
|
36
|
+
const { locale } = useI18n();
|
|
37
|
+
const localePath = useLocalePath();
|
|
38
|
+
const route = useRoute();
|
|
39
|
+
|
|
40
|
+
const { data } = await useAsyncData(
|
|
41
|
+
() => `navigation-${locale.value}`,
|
|
42
|
+
() => {
|
|
43
|
+
const collection = `content_${locale.value}` as const;
|
|
44
|
+
return queryCollectionNavigation(collection as keyof Collections);
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
default: () => [],
|
|
48
|
+
},
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
const navigation = computed(() => {
|
|
52
|
+
// map the items from "@nuxt/content" to our custom data scheme for better type support
|
|
53
|
+
const mapItem = (item: ContentNavigationItem): SidebarNavigationItem => {
|
|
54
|
+
return {
|
|
55
|
+
title: item.title,
|
|
56
|
+
path: localePath(item.path),
|
|
57
|
+
children: item.children?.map(mapItem),
|
|
58
|
+
sidebar: item.sidebar && typeof item.sidebar === "object" ? item.sidebar : undefined,
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const items = data.value.map(mapItem);
|
|
63
|
+
|
|
64
|
+
// support multiple sidebars / roots so different pages can have their own sub-sidebar
|
|
65
|
+
const root = findDeepestRoot(items, route.path);
|
|
66
|
+
if (!root) return items;
|
|
67
|
+
return root.children ?? [root];
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const findDeepestRoot = (
|
|
71
|
+
items: SidebarNavigationItem[],
|
|
72
|
+
activePath: string,
|
|
73
|
+
): SidebarNavigationItem | undefined => {
|
|
74
|
+
/** Helper function to check if a path exists anywhere in a node's subtree */
|
|
75
|
+
const containsPath = (node: SidebarNavigationItem, path: string): boolean => {
|
|
76
|
+
if (node.path === path) return true;
|
|
77
|
+
return node.children?.some((child) => containsPath(child, path)) ?? false;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
for (const item of items) {
|
|
81
|
+
// 1. Check children first (to find something deeper)
|
|
82
|
+
if (item.children) {
|
|
83
|
+
const deeperResult = findDeepestRoot(item.children, activePath);
|
|
84
|
+
if (deeperResult) return deeperResult;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// 2. If no deeper root was found, check if this current node is a match
|
|
88
|
+
if (item.sidebar?.root && containsPath(item, activePath)) {
|
|
89
|
+
return item;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
return { navigation };
|
|
95
|
+
};
|
package/app/layouts/sidebar.vue
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
import type {
|
|
3
|
-
import
|
|
2
|
+
import type { OnyxPageLayoutProps, OnyxSidebarProps } from "sit-onyx";
|
|
3
|
+
import type { SidebarNavigationItem } from "../composables/useSidebarNavigation.js";
|
|
4
4
|
|
|
5
5
|
const props = defineProps<
|
|
6
6
|
OnyxPageLayoutProps & {
|
|
@@ -24,7 +24,7 @@ const slots = defineSlots<{
|
|
|
24
24
|
/**
|
|
25
25
|
* Optionally override the main sidebar body content.
|
|
26
26
|
*/
|
|
27
|
-
sidebarBody?(props: { items:
|
|
27
|
+
sidebarBody?(props: { items: SidebarNavigationItem[] }): unknown;
|
|
28
28
|
/**
|
|
29
29
|
* Optionally override the sidebar header content.
|
|
30
30
|
*/
|
|
@@ -35,18 +35,7 @@ const slots = defineSlots<{
|
|
|
35
35
|
sidebarFooter?(): unknown;
|
|
36
36
|
}>();
|
|
37
37
|
|
|
38
|
-
const {
|
|
39
|
-
const localePath = useLocalePath();
|
|
40
|
-
|
|
41
|
-
const navigation = await useAsyncData(
|
|
42
|
-
() => `navigation-${locale.value}`,
|
|
43
|
-
() => {
|
|
44
|
-
const collection = `content_${locale.value}` as const;
|
|
45
|
-
return queryCollectionNavigation(collection);
|
|
46
|
-
},
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
const sidebarItems = computed(() => navigation.data.value ?? []);
|
|
38
|
+
const { navigation } = await useSidebarNavigation();
|
|
50
39
|
</script>
|
|
51
40
|
|
|
52
41
|
<template>
|
|
@@ -61,10 +50,10 @@ const sidebarItems = computed(() => navigation.data.value ?? []);
|
|
|
61
50
|
<slot name="sidebarHeader"> </slot>
|
|
62
51
|
</template>
|
|
63
52
|
|
|
64
|
-
<slot name="sidebarBody" :items="
|
|
65
|
-
<SidebarItem v-for="item in
|
|
53
|
+
<slot name="sidebarBody" :items="navigation">
|
|
54
|
+
<SidebarItem v-for="item in navigation" :key="item.path" :item="item" />
|
|
66
55
|
|
|
67
|
-
<OnyxEmpty v-if="!
|
|
56
|
+
<OnyxEmpty v-if="!navigation.length" class="sidebar__empty">
|
|
68
57
|
{{ $t("onyx.select.empty") }}
|
|
69
58
|
</OnyxEmpty>
|
|
70
59
|
</slot>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sit-onyx/nuxt-docs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0-dev-20251229091238",
|
|
4
4
|
"description": "Nuxt layer/template for creating documentations with the onyx design system",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Schwarz IT KG",
|
|
@@ -30,27 +30,27 @@
|
|
|
30
30
|
"@nuxtjs/color-mode": ">= 4",
|
|
31
31
|
"@nuxtjs/i18n": ">= 10",
|
|
32
32
|
"sass-embedded": ">= 1",
|
|
33
|
-
"@sit-onyx/icons": "^1.
|
|
33
|
+
"@sit-onyx/icons": "^1.3.0",
|
|
34
34
|
"@sit-onyx/nuxt": "^1.0.1",
|
|
35
|
-
"sit-onyx": "^1.
|
|
35
|
+
"sit-onyx": "^1.6.0-dev-20251229091238"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@fontsource-variable/source-code-pro": ">= 5",
|
|
39
39
|
"@fontsource-variable/source-sans-3": ">= 5",
|
|
40
40
|
"@nuxt/content": ">= 3",
|
|
41
41
|
"@nuxt/image": ">= 1",
|
|
42
|
-
"@nuxt/test-utils": "^3.
|
|
42
|
+
"@nuxt/test-utils": "^3.21.0",
|
|
43
43
|
"@nuxtjs/color-mode": ">= 4",
|
|
44
|
-
"@playwright/experimental-ct-vue": "1.
|
|
45
|
-
"@playwright/test": "1.
|
|
46
|
-
"nuxt": "4.2.
|
|
47
|
-
"sass-embedded": "1.
|
|
44
|
+
"@playwright/experimental-ct-vue": "1.57.0",
|
|
45
|
+
"@playwright/test": "1.57.0",
|
|
46
|
+
"nuxt": "4.2.2",
|
|
47
|
+
"sass-embedded": "1.97.1",
|
|
48
48
|
"typescript": "5.9.3",
|
|
49
|
-
"vue": "3.5.
|
|
49
|
+
"vue": "3.5.26",
|
|
50
|
+
"@sit-onyx/icons": "^1.3.0",
|
|
50
51
|
"@sit-onyx/nuxt": "^1.0.1",
|
|
51
|
-
"@sit-onyx/icons": "^1.2.0",
|
|
52
52
|
"@sit-onyx/shared": "^0.1.0",
|
|
53
|
-
"sit-onyx": "^1.
|
|
53
|
+
"sit-onyx": "^1.6.0-dev-20251229091238"
|
|
54
54
|
},
|
|
55
55
|
"scripts": {
|
|
56
56
|
"dev": "pnpm dev:prepare && nuxi dev playground",
|