@sit-onyx/nuxt-docs 0.2.0-dev-20260112110323 → 0.2.0-dev-20260113075525
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.
- package/app/components/NavBar.vue +0 -1
- package/app/components/NestableSidebarItem.vue +93 -0
- package/app/components/PackageManagerCodeTabs.vue +11 -1
- package/app/components/ResolvableIcon.vue +31 -0
- package/app/components/SidebarItem.vue +5 -69
- package/app/components/content/ProseTable.vue +9 -14
- package/app/composables/useSidebarNavigation.ts +2 -0
- package/app/layouts/sidebar.vue +1 -1
- package/package.json +7 -5
|
@@ -4,7 +4,6 @@ import ColorSchemeSwitch from "./ColorSchemeSwitch.vue";
|
|
|
4
4
|
|
|
5
5
|
const props = withDefaults(defineProps<OnyxNavBarProps>(), {
|
|
6
6
|
appName: "Documentation",
|
|
7
|
-
withBackButton: true,
|
|
8
7
|
// Vue defaults booleans to false so this explicit "undefined" is needed to correctly set the default breakpoint
|
|
9
8
|
mobile: undefined,
|
|
10
9
|
});
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import type { SidebarNavigationItem } from "../composables/useSidebarNavigation.js";
|
|
3
|
+
|
|
4
|
+
const props = defineProps<{
|
|
5
|
+
item: SidebarNavigationItem;
|
|
6
|
+
}>();
|
|
7
|
+
|
|
8
|
+
const route = useRoute();
|
|
9
|
+
|
|
10
|
+
const isAccordionOpen = ref(true);
|
|
11
|
+
watch(
|
|
12
|
+
() => props.item.sidebar?.collapsed,
|
|
13
|
+
(collapsed) => {
|
|
14
|
+
isAccordionOpen.value = !collapsed;
|
|
15
|
+
},
|
|
16
|
+
{ immediate: true },
|
|
17
|
+
);
|
|
18
|
+
|
|
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;
|
|
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
|
+
);
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
<template>
|
|
41
|
+
<SidebarItem v-if="!props.item.children?.length" class="sidebar-item" :item="props.item" />
|
|
42
|
+
|
|
43
|
+
<OnyxAccordion
|
|
44
|
+
v-else
|
|
45
|
+
:model-value="isAccordionOpen ? [props.item.path] : undefined"
|
|
46
|
+
class="sidebar-accordion"
|
|
47
|
+
type="nested-large"
|
|
48
|
+
@update:model-value="isAccordionOpen = !isAccordionOpen"
|
|
49
|
+
>
|
|
50
|
+
<OnyxAccordionItem :value="props.item.path">
|
|
51
|
+
<template #header>
|
|
52
|
+
<div class="sidebar-accordion__header">
|
|
53
|
+
<ResolvableIcon v-if="props.item.icon" :name="props.item.icon" />
|
|
54
|
+
{{ props.item.title }}
|
|
55
|
+
</div>
|
|
56
|
+
</template>
|
|
57
|
+
|
|
58
|
+
<div class="sidebar-item__children">
|
|
59
|
+
<SidebarItem v-for="child in props.item.children" :key="child.path" :item="child" />
|
|
60
|
+
</div>
|
|
61
|
+
</OnyxAccordionItem>
|
|
62
|
+
</OnyxAccordion>
|
|
63
|
+
</template>
|
|
64
|
+
|
|
65
|
+
<style lang="scss" scoped>
|
|
66
|
+
.sidebar-item {
|
|
67
|
+
margin: var(--onyx-density-2xs) var(--onyx-density-xs);
|
|
68
|
+
|
|
69
|
+
&:first-of-type {
|
|
70
|
+
margin-top: var(--onyx-density-xs);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
&__children {
|
|
74
|
+
display: flex;
|
|
75
|
+
flex-direction: column;
|
|
76
|
+
gap: var(--onyx-density-2xs);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.sidebar-accordion {
|
|
81
|
+
> .onyx-accordion-item {
|
|
82
|
+
:deep(> .onyx-accordion-item__panel) {
|
|
83
|
+
padding-top: 0;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
&__header {
|
|
88
|
+
display: flex;
|
|
89
|
+
align-items: center;
|
|
90
|
+
gap: var(--onyx-density-2xs);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
</style>
|
|
@@ -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>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import * as ALL_ICONS from "@sit-onyx/icons";
|
|
3
|
+
import { getIconImportName } from "@sit-onyx/icons/utils";
|
|
4
|
+
|
|
5
|
+
const props = defineProps<{
|
|
6
|
+
/**
|
|
7
|
+
* Icon name that should be resolved.
|
|
8
|
+
*/
|
|
9
|
+
name: string;
|
|
10
|
+
}>();
|
|
11
|
+
|
|
12
|
+
const icon = ref<string>();
|
|
13
|
+
|
|
14
|
+
watch(
|
|
15
|
+
() => props.name,
|
|
16
|
+
(iconName) => {
|
|
17
|
+
icon.value = ALL_ICONS[getIconImportName(iconName) as keyof typeof ALL_ICONS];
|
|
18
|
+
|
|
19
|
+
if (import.meta.dev && !icon.value) {
|
|
20
|
+
// eslint-disable-next-line no-console -- used only during development environment
|
|
21
|
+
console.warn(`Dynamic icon with name "${iconName}" not found.`);
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
{ immediate: true },
|
|
25
|
+
);
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<!-- eslint-disable-next-line vue/no-root-v-if -->
|
|
29
|
+
<template>
|
|
30
|
+
<OnyxIcon v-if="icon" :icon />
|
|
31
|
+
</template>
|
|
@@ -1,86 +1,22 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
+
import { iconArrowSmallRight } from "@sit-onyx/icons";
|
|
2
3
|
import type { SidebarNavigationItem } from "../composables/useSidebarNavigation.js";
|
|
3
4
|
|
|
4
5
|
const props = defineProps<{
|
|
5
|
-
item: SidebarNavigationItem
|
|
6
|
+
item: Omit<SidebarNavigationItem, "children">;
|
|
6
7
|
}>();
|
|
7
|
-
|
|
8
|
-
const route = useRoute();
|
|
9
|
-
|
|
10
|
-
const isAccordionOpen = ref(true);
|
|
11
|
-
watch(
|
|
12
|
-
() => props.item.sidebar?.collapsed,
|
|
13
|
-
(collapsed) => {
|
|
14
|
-
isAccordionOpen.value = !collapsed;
|
|
15
|
-
},
|
|
16
|
-
{ immediate: true },
|
|
17
|
-
);
|
|
18
|
-
|
|
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;
|
|
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
|
-
);
|
|
38
8
|
</script>
|
|
39
9
|
|
|
40
10
|
<template>
|
|
41
|
-
<OnyxSidebarItem
|
|
11
|
+
<OnyxSidebarItem class="sidebar-item" :link="props.item.path">
|
|
12
|
+
<ResolvableIcon v-if="props.item.icon" :name="props.item.icon" />
|
|
42
13
|
{{ props.item.title }}
|
|
14
|
+
<OnyxIcon v-if="props.item.sidebar?.root" :icon="iconArrowSmallRight" />
|
|
43
15
|
</OnyxSidebarItem>
|
|
44
|
-
|
|
45
|
-
<OnyxAccordion
|
|
46
|
-
v-else
|
|
47
|
-
:model-value="isAccordionOpen ? [props.item.path] : undefined"
|
|
48
|
-
class="sidebar-accordion"
|
|
49
|
-
type="nested-large"
|
|
50
|
-
@update:model-value="isAccordionOpen = !isAccordionOpen"
|
|
51
|
-
>
|
|
52
|
-
<OnyxAccordionItem :value="props.item.path">
|
|
53
|
-
<template #header>{{ props.item.title }}</template>
|
|
54
|
-
|
|
55
|
-
<div class="sidebar-item__children">
|
|
56
|
-
<OnyxSidebarItem v-for="child in props.item.children" :key="child.path" :link="child.path">
|
|
57
|
-
{{ child.title }}
|
|
58
|
-
</OnyxSidebarItem>
|
|
59
|
-
</div>
|
|
60
|
-
</OnyxAccordionItem>
|
|
61
|
-
</OnyxAccordion>
|
|
62
16
|
</template>
|
|
63
17
|
|
|
64
18
|
<style lang="scss" scoped>
|
|
65
19
|
.sidebar-item {
|
|
66
20
|
margin: var(--onyx-density-2xs) var(--onyx-density-xs);
|
|
67
|
-
|
|
68
|
-
&:first-of-type {
|
|
69
|
-
margin-top: var(--onyx-density-xs);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
&__children {
|
|
73
|
-
display: flex;
|
|
74
|
-
flex-direction: column;
|
|
75
|
-
gap: var(--onyx-density-2xs);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
.sidebar-accordion {
|
|
80
|
-
> .onyx-accordion-item {
|
|
81
|
-
:deep(> .onyx-accordion-item__panel) {
|
|
82
|
-
padding-top: 0;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
21
|
}
|
|
86
22
|
</style>
|
|
@@ -5,18 +5,6 @@ const slots = defineSlots<{
|
|
|
5
5
|
default(): VNode[];
|
|
6
6
|
}>();
|
|
7
7
|
|
|
8
|
-
/**
|
|
9
|
-
* Extracts the table head and body as vnodes from the slot content.
|
|
10
|
-
*/
|
|
11
|
-
const extractSlotContent = () => {
|
|
12
|
-
const [head, body] = slots.default();
|
|
13
|
-
|
|
14
|
-
return {
|
|
15
|
-
headRows: extractTableRows(head),
|
|
16
|
-
bodyRows: extractTableRows(body),
|
|
17
|
-
};
|
|
18
|
-
};
|
|
19
|
-
|
|
20
8
|
/**
|
|
21
9
|
* Extracts all table rows `<tr>` vnodes from the given vnode (e.g. table head or body).
|
|
22
10
|
*/
|
|
@@ -33,8 +21,15 @@ const extractTableRows = (vnode?: VNode): VNode[] => {
|
|
|
33
21
|
return vnode.children.default();
|
|
34
22
|
};
|
|
35
23
|
|
|
36
|
-
const content =
|
|
37
|
-
|
|
24
|
+
const content = computed(() => {
|
|
25
|
+
const children = slots.default?.() ?? [];
|
|
26
|
+
const [head, body] = children;
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
headRows: extractTableRows(head),
|
|
30
|
+
bodyRows: extractTableRows(body),
|
|
31
|
+
};
|
|
32
|
+
});
|
|
38
33
|
</script>
|
|
39
34
|
|
|
40
35
|
<template>
|
|
@@ -6,6 +6,7 @@ export type SidebarNavigationItem = {
|
|
|
6
6
|
* Item path. Already localized for i18n with `useLocalePath`.
|
|
7
7
|
*/
|
|
8
8
|
path: string;
|
|
9
|
+
icon?: string;
|
|
9
10
|
children?: SidebarNavigationItem[];
|
|
10
11
|
sidebar?: SidebarNavigationOptions;
|
|
11
12
|
};
|
|
@@ -56,6 +57,7 @@ export const useSidebarNavigation = async () => {
|
|
|
56
57
|
path: localePath(item.path),
|
|
57
58
|
children: item.children?.map(mapItem),
|
|
58
59
|
sidebar: item.sidebar && typeof item.sidebar === "object" ? item.sidebar : undefined,
|
|
60
|
+
icon: item.icon && typeof item.icon === "string" ? item.icon : undefined,
|
|
59
61
|
};
|
|
60
62
|
};
|
|
61
63
|
|
package/app/layouts/sidebar.vue
CHANGED
|
@@ -51,7 +51,7 @@ const { navigation } = await useSidebarNavigation();
|
|
|
51
51
|
</template>
|
|
52
52
|
|
|
53
53
|
<slot name="sidebarBody" :items="navigation">
|
|
54
|
-
<
|
|
54
|
+
<NestableSidebarItem v-for="item in navigation" :key="item.path" :item="item" />
|
|
55
55
|
|
|
56
56
|
<OnyxEmpty v-if="!navigation.length" class="sidebar__empty">
|
|
57
57
|
{{ $t("onyx.select.empty") }}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sit-onyx/nuxt-docs",
|
|
3
|
-
"version": "0.2.0-dev-
|
|
3
|
+
"version": "0.2.0-dev-20260113075525",
|
|
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,11 +28,12 @@
|
|
|
28
28
|
"@nuxt/content": ">= 3",
|
|
29
29
|
"@nuxt/image": ">= 1",
|
|
30
30
|
"@nuxtjs/color-mode": ">= 4",
|
|
31
|
+
"@nuxtjs/mdc": ">= 0.17.2",
|
|
31
32
|
"@nuxtjs/i18n": ">= 10",
|
|
32
33
|
"sass-embedded": ">= 1",
|
|
33
|
-
"@sit-onyx/icons": "^1.4.0-dev-
|
|
34
|
+
"@sit-onyx/icons": "^1.4.0-dev-20260113075525",
|
|
34
35
|
"@sit-onyx/nuxt": "^1.0.1",
|
|
35
|
-
"sit-onyx": "^1.6.0-dev-
|
|
36
|
+
"sit-onyx": "^1.6.0-dev-20260113075525"
|
|
36
37
|
},
|
|
37
38
|
"devDependencies": {
|
|
38
39
|
"@fontsource-variable/source-code-pro": ">= 5",
|
|
@@ -41,16 +42,17 @@
|
|
|
41
42
|
"@nuxt/image": ">= 1",
|
|
42
43
|
"@nuxt/test-utils": "^3.23.0",
|
|
43
44
|
"@nuxtjs/color-mode": ">= 4",
|
|
45
|
+
"@nuxtjs/mdc": ">= 0.17.2",
|
|
44
46
|
"@playwright/experimental-ct-vue": "1.57.0",
|
|
45
47
|
"@playwright/test": "1.57.0",
|
|
46
48
|
"nuxt": "4.2.2",
|
|
47
49
|
"sass-embedded": "1.97.2",
|
|
48
50
|
"typescript": "5.9.3",
|
|
49
51
|
"vue": "3.5.26",
|
|
50
|
-
"@sit-onyx/icons": "^1.4.0-dev-
|
|
52
|
+
"@sit-onyx/icons": "^1.4.0-dev-20260113075525",
|
|
51
53
|
"@sit-onyx/nuxt": "^1.0.1",
|
|
52
54
|
"@sit-onyx/shared": "^0.1.0",
|
|
53
|
-
"sit-onyx": "^1.6.0-dev-
|
|
55
|
+
"sit-onyx": "^1.6.0-dev-20260113075525"
|
|
54
56
|
},
|
|
55
57
|
"scripts": {
|
|
56
58
|
"dev": "pnpm dev:prepare && nuxi dev playground",
|