@sit-onyx/nuxt-docs 0.2.0-dev-20260112121557 → 0.2.0-dev-20260113092604

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.
@@ -29,10 +29,20 @@ const tabs = computed(() => {
29
29
 
30
30
  return tabs.filter((tab) => tab.code);
31
31
  });
32
+
33
+ const getMDCValue = (code: string, language: string) => {
34
+ return `
35
+ \`\`\`${language}
36
+ ${code}
37
+ \`\`\`
38
+ `;
39
+ };
32
40
  </script>
33
41
 
34
42
  <template>
35
43
  <OnyxUnstableCodeTabs v-model="selectedTab">
36
- <OnyxUnstableCodeTab v-for="tab in tabs" v-bind="tab" :key="tab.value" :label="tab.value" />
44
+ <OnyxUnstableCodeTab v-for="tab in tabs" v-bind="tab" :key="tab.value" :label="tab.value">
45
+ <MDC :value="getMDCValue(tab.code, tab.language)" />
46
+ </OnyxUnstableCodeTab>
37
47
  </OnyxUnstableCodeTabs>
38
48
  </template>
@@ -49,7 +49,10 @@ export const useSidebarNavigation = async () => {
49
49
  },
50
50
  );
51
51
 
52
- const navigation = computed(() => {
52
+ /**
53
+ * All navigation items.
54
+ */
55
+ const allItems = computed(() => {
53
56
  // map the items from "@nuxt/content" to our custom data scheme for better type support
54
57
  const mapItem = (item: ContentNavigationItem): SidebarNavigationItem => {
55
58
  return {
@@ -61,18 +64,30 @@ export const useSidebarNavigation = async () => {
61
64
  };
62
65
  };
63
66
 
64
- const items = data.value.map(mapItem);
67
+ return data.value.map(mapItem);
68
+ });
65
69
 
70
+ const navigation = computed(() => {
66
71
  // support multiple sidebars / roots so different pages can have their own sub-sidebar
67
- const root = findDeepestRoot(items, route.path);
68
- if (!root) return items;
72
+ const root = findDeepestRoot(allItems.value, route.path);
73
+ if (!root) return allItems.value;
69
74
  return root.children ?? [root];
70
75
  });
71
76
 
72
- const findDeepestRoot = (
77
+ /**
78
+ * Finds the "previous root" (parent root) for the currently active route within the navigation tree.
79
+ * Useful to e.g. display a back button to traverse up the navigation tree.
80
+ */
81
+ const previousRootItem = computed(() => findPreviousRootItem(allItems.value, route.path));
82
+
83
+ /**
84
+ * Recursively searches for the deepest item marked as a sidebar root
85
+ * that contains the `currentPath` within its subtree.
86
+ */
87
+ function findDeepestRoot(
73
88
  items: SidebarNavigationItem[],
74
- activePath: string,
75
- ): SidebarNavigationItem | undefined => {
89
+ currentPath: string,
90
+ ): SidebarNavigationItem | undefined {
76
91
  /** Helper function to check if a path exists anywhere in a node's subtree */
77
92
  const containsPath = (node: SidebarNavigationItem, path: string): boolean => {
78
93
  if (node.path === path) return true;
@@ -82,16 +97,68 @@ export const useSidebarNavigation = async () => {
82
97
  for (const item of items) {
83
98
  // 1. Check children first (to find something deeper)
84
99
  if (item.children) {
85
- const deeperResult = findDeepestRoot(item.children, activePath);
100
+ const deeperResult = findDeepestRoot(item.children, currentPath);
86
101
  if (deeperResult) return deeperResult;
87
102
  }
88
103
 
89
104
  // 2. If no deeper root was found, check if this current node is a match
90
- if (item.sidebar?.root && containsPath(item, activePath)) {
105
+ if (item.sidebar?.root && containsPath(item, currentPath)) {
91
106
  return item;
92
107
  }
93
108
  }
94
- };
109
+ }
110
+
111
+ /**
112
+ * Finds the "previous root" (parent root) for a given current path within the navigation tree.
113
+ * - If depth >= 2: returns the previous root item
114
+ * - If depth == 1: returns the first item in the navigation (typically a "Home" item)
115
+ * - If depth == 0: returns undefined (no back button needed)
116
+ *
117
+ * @param items - The full navigation array
118
+ * @param currentPath - The path of the currently active page
119
+ * @param rootStack - (Internal) Accumulator for recursion
120
+ */
121
+ function findPreviousRootItem(
122
+ items: SidebarNavigationItem[],
123
+ currentPath: string,
124
+ rootStack: SidebarNavigationItem[] = [],
125
+ ): SidebarNavigationItem | undefined {
126
+ for (const item of items) {
127
+ const isRoot = item.sidebar?.root === true;
128
+
129
+ // 1. update stack: if item is a root, add to ancestry
130
+ const nextRootStack = isRoot ? [...rootStack, item] : rootStack;
131
+
132
+ // 2. check if item is the active item
133
+ if (item.path === currentPath) {
134
+ // case A: deep nesting (e.g. Stack: [Home -> Examples -> Example 1])
135
+ // return the previous root (Examples)
136
+ if (nextRootStack.length >= 2) {
137
+ return nextRootStack[nextRootStack.length - 2];
138
+ }
139
+
140
+ // case B: first level of nesting (e.g. Stack: [Home])
141
+ // return the first item in the navigation (typically a "Home" item)
142
+ if (nextRootStack.length === 1) {
143
+ // if the root is part of the highest navigation level, we want to return undefined
144
+ // (so no back button is shown), otherwise we return the first available item
145
+ const isSameLevel = allItems.value.some((item) => item.path === nextRootStack[0]?.path);
146
+ return isSameLevel ? undefined : allItems.value[0];
147
+ }
148
+
149
+ // case C: no nested roots active
150
+ return undefined;
151
+ }
152
+
153
+ // 3. recursive step for children
154
+ if (item.children) {
155
+ const result = findPreviousRootItem(item.children, currentPath, nextRootStack);
156
+ if (result !== undefined) {
157
+ return result;
158
+ }
159
+ }
160
+ }
161
+ }
95
162
 
96
- return { navigation };
163
+ return { navigation, allItems, previousRootItem };
97
164
  };
@@ -1,4 +1,5 @@
1
1
  <script lang="ts" setup>
2
+ import { iconArrowSmallLeft } from "@sit-onyx/icons";
2
3
  import type { OnyxPageLayoutProps, OnyxSidebarProps } from "sit-onyx";
3
4
  import type { SidebarNavigationItem } from "../composables/useSidebarNavigation.js";
4
5
 
@@ -27,6 +28,7 @@ const slots = defineSlots<{
27
28
  sidebarBody?(props: { items: SidebarNavigationItem[] }): unknown;
28
29
  /**
29
30
  * Optionally override the sidebar header content.
31
+ * By default, a back button will be shown if a nested sidebar root is opened.
30
32
  */
31
33
  sidebarHeader?(): unknown;
32
34
  /**
@@ -35,7 +37,7 @@ const slots = defineSlots<{
35
37
  sidebarFooter?(): unknown;
36
38
  }>();
37
39
 
38
- const { navigation } = await useSidebarNavigation();
40
+ const { navigation, previousRootItem } = await useSidebarNavigation();
39
41
  </script>
40
42
 
41
43
  <template>
@@ -46,8 +48,18 @@ const { navigation } = await useSidebarNavigation();
46
48
  v-bind="props.sidebar"
47
49
  :label="$t('onyx.navigation.navigationHeadline')"
48
50
  >
49
- <template v-if="slots.sidebarHeader" #header>
50
- <slot name="sidebarHeader"> </slot>
51
+ <template v-if="slots.sidebarHeader || previousRootItem" #header>
52
+ <slot name="sidebarHeader">
53
+ <OnyxButton
54
+ v-if="previousRootItem"
55
+ class="sidebar__back"
56
+ :label="$t('onyx.back')"
57
+ color="neutral"
58
+ mode="plain"
59
+ :link="previousRootItem.path"
60
+ :icon="iconArrowSmallLeft"
61
+ />
62
+ </slot>
51
63
  </template>
52
64
 
53
65
  <slot name="sidebarBody" :items="navigation">
@@ -85,5 +97,10 @@ const { navigation } = await useSidebarNavigation();
85
97
  &__empty {
86
98
  max-width: 100%;
87
99
  }
100
+
101
+ &__back {
102
+ width: 100%;
103
+ justify-content: flex-start;
104
+ }
88
105
  }
89
106
  </style>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sit-onyx/nuxt-docs",
3
- "version": "0.2.0-dev-20260112121557",
3
+ "version": "0.2.0-dev-20260113092604",
4
4
  "description": "Nuxt layer/template for creating documentations with the onyx design system",
5
5
  "type": "module",
6
6
  "author": "Schwarz IT KG",
@@ -28,12 +28,12 @@
28
28
  "@nuxt/content": ">= 3",
29
29
  "@nuxt/image": ">= 1",
30
30
  "@nuxtjs/color-mode": ">= 4",
31
- "@nuxtjs/mdc": ">= 0.13.0",
31
+ "@nuxtjs/mdc": ">= 0.17.2",
32
32
  "@nuxtjs/i18n": ">= 10",
33
33
  "sass-embedded": ">= 1",
34
- "@sit-onyx/icons": "^1.4.0-dev-20260112121557",
34
+ "@sit-onyx/icons": "^1.4.0-dev-20260113092604",
35
35
  "@sit-onyx/nuxt": "^1.0.1",
36
- "sit-onyx": "^1.6.0-dev-20260112121557"
36
+ "sit-onyx": "^1.6.0-dev-20260113092604"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@fontsource-variable/source-code-pro": ">= 5",
@@ -42,17 +42,17 @@
42
42
  "@nuxt/image": ">= 1",
43
43
  "@nuxt/test-utils": "^3.23.0",
44
44
  "@nuxtjs/color-mode": ">= 4",
45
- "@nuxtjs/mdc": ">= 0.13.0",
45
+ "@nuxtjs/mdc": ">= 0.17.2",
46
46
  "@playwright/experimental-ct-vue": "1.57.0",
47
47
  "@playwright/test": "1.57.0",
48
48
  "nuxt": "4.2.2",
49
49
  "sass-embedded": "1.97.2",
50
50
  "typescript": "5.9.3",
51
51
  "vue": "3.5.26",
52
- "@sit-onyx/icons": "^1.4.0-dev-20260112121557",
52
+ "@sit-onyx/icons": "^1.4.0-dev-20260113092604",
53
53
  "@sit-onyx/nuxt": "^1.0.1",
54
54
  "@sit-onyx/shared": "^0.1.0",
55
- "sit-onyx": "^1.6.0-dev-20260112121557"
55
+ "sit-onyx": "^1.6.0-dev-20260113092604"
56
56
  },
57
57
  "scripts": {
58
58
  "dev": "pnpm dev:prepare && nuxi dev playground",