@mozaic-ds/vue 2.13.0 → 2.14.0

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.
Files changed (90) hide show
  1. package/dist/mozaic-vue.css +1 -1
  2. package/dist/mozaic-vue.d.ts +1088 -378
  3. package/dist/mozaic-vue.js +2662 -1854
  4. package/dist/mozaic-vue.js.map +1 -1
  5. package/dist/mozaic-vue.umd.cjs +5 -5
  6. package/dist/mozaic-vue.umd.cjs.map +1 -1
  7. package/package.json +4 -4
  8. package/src/components/actionlistbox/MActionListbox.spec.ts +53 -59
  9. package/src/components/actionlistbox/MActionListbox.stories.ts +22 -1
  10. package/src/components/actionlistbox/MActionListbox.vue +91 -28
  11. package/src/components/actionlistbox/README.md +15 -0
  12. package/src/components/breadcrumb/MBreadcrumb.vue +5 -0
  13. package/src/components/button/README.md +4 -0
  14. package/src/components/checkbox/README.md +2 -0
  15. package/src/components/divider/README.md +4 -0
  16. package/src/components/iconbutton/MIconButton.stories.ts +12 -0
  17. package/src/components/iconbutton/MIconButton.vue +13 -1
  18. package/src/components/iconbutton/README.md +27 -0
  19. package/src/components/loader/README.md +2 -0
  20. package/src/components/navigationindicator/MNavigationIndicator.spec.ts +152 -0
  21. package/src/components/navigationindicator/MNavigationIndicator.stories.ts +41 -0
  22. package/src/components/navigationindicator/MNavigationIndicator.vue +132 -0
  23. package/src/components/navigationindicator/README.md +37 -0
  24. package/src/components/pageheader/MPageHeader.spec.ts +142 -0
  25. package/src/components/pageheader/MPageHeader.stories.ts +125 -0
  26. package/src/components/pageheader/MPageHeader.vue +133 -0
  27. package/src/components/pageheader/README.md +46 -0
  28. package/src/components/popover/MPopover.spec.ts +106 -0
  29. package/src/components/popover/MPopover.stories.ts +126 -0
  30. package/src/components/popover/MPopover.vue +131 -0
  31. package/src/components/popover/README.md +42 -0
  32. package/src/components/radio/README.md +2 -0
  33. package/src/components/select/MSelect.spec.ts +2 -1
  34. package/src/components/select/MSelect.vue +30 -25
  35. package/src/components/sidebar/MSidebar.const.ts +6 -0
  36. package/src/components/sidebar/MSidebar.spec.ts +110 -0
  37. package/src/components/sidebar/MSidebar.stories.ts +108 -0
  38. package/src/components/sidebar/MSidebar.vue +124 -0
  39. package/src/components/sidebar/README.md +59 -0
  40. package/src/components/sidebar/stories/DefaultCase.stories.vue +120 -0
  41. package/src/components/sidebar/stories/README.md +27 -0
  42. package/src/components/sidebar/stories/WithExpandOnly.stories.vue +112 -0
  43. package/src/components/sidebar/stories/WithProfileInfoOnly.stories.vue +119 -0
  44. package/src/components/sidebar/stories/WithSingleLevel.stories.vue +98 -0
  45. package/src/components/sidebar/use-floating-item.composable.ts +135 -0
  46. package/src/components/sidebar/use-floating-item.spec.ts +251 -0
  47. package/src/components/sidebarexpandableitem/MSidebarExpandableItem.spec.ts +151 -0
  48. package/src/components/sidebarexpandableitem/MSidebarExpandableItem.vue +113 -0
  49. package/src/components/sidebarexpandableitem/README.md +36 -0
  50. package/src/components/sidebarfooter/MSidebarFooter.spec.ts +276 -0
  51. package/src/components/sidebarfooter/MSidebarFooter.vue +201 -0
  52. package/src/components/sidebarfooter/README.md +52 -0
  53. package/src/components/sidebarfooter/_MSidebarFooterMenu.vue +64 -0
  54. package/src/components/sidebarheader/MSidebarHeader.vue +36 -0
  55. package/src/components/sidebarheader/README.md +31 -0
  56. package/src/components/sidebarnavitem/MSidebarNavItem.spec.ts +127 -0
  57. package/src/components/sidebarnavitem/MSidebarNavItem.vue +113 -0
  58. package/src/components/sidebarnavitem/README.md +56 -0
  59. package/src/components/sidebarshortcutitem/MSidebarShortcutItem.spec.ts +59 -0
  60. package/src/components/sidebarshortcutitem/MSidebarShortcutItem.vue +52 -0
  61. package/src/components/sidebarshortcutitem/README.md +32 -0
  62. package/src/components/sidebarshortcuts/MSidebarShortcuts.spec.ts +87 -0
  63. package/src/components/sidebarshortcuts/MSidebarShortcuts.vue +101 -0
  64. package/src/components/sidebarshortcuts/README.md +36 -0
  65. package/src/components/statusbadge/README.md +12 -0
  66. package/src/components/textinput/MTextInput.stories.ts +13 -1
  67. package/src/components/textinput/MTextInput.vue +12 -0
  68. package/src/components/textinput/README.md +3 -1
  69. package/src/components/tile/MTile.spec.ts +61 -0
  70. package/src/components/tile/MTile.stories.ts +102 -0
  71. package/src/components/tile/MTile.vue +68 -0
  72. package/src/components/tile/README.md +19 -0
  73. package/src/components/tileclickable/MTileClickable.spec.ts +130 -0
  74. package/src/components/tileclickable/MTileClickable.stories.ts +60 -0
  75. package/src/components/tileclickable/MTileClickable.vue +106 -0
  76. package/src/components/tileclickable/README.md +30 -0
  77. package/src/components/tileexpandable/MTileExpandable.spec.ts +121 -0
  78. package/src/components/tileexpandable/MTileExpandable.stories.ts +50 -0
  79. package/src/components/tileexpandable/MTileExpandable.vue +131 -0
  80. package/src/components/tileexpandable/README.md +36 -0
  81. package/src/components/tileselectable/MTileSelectable.spec.ts +177 -0
  82. package/src/components/tileselectable/MTileSelectable.stories.ts +55 -0
  83. package/src/components/tileselectable/MTileSelectable.vue +142 -0
  84. package/src/components/tileselectable/README.md +44 -0
  85. package/src/components/toaster/README.md +1 -1
  86. package/src/components/tooltip/MTooltip.vue +5 -0
  87. package/src/components/tooltip/README.md +16 -1
  88. package/src/main.ts +12 -2
  89. package/src/utils/use-is-mobile.composable.ts +20 -0
  90. package/src/utils/use-is-mobile.spec.ts +70 -0
@@ -0,0 +1,110 @@
1
+ import { defineComponent, inject, ref } from 'vue';
2
+ import { mount } from '@vue/test-utils';
3
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
4
+ import MSidebar from './MSidebar.vue';
5
+ import { EXPANDED_SIDEBAR_KEY, TOGGLE_SIDEBAR_KEY } from './MSidebar.const';
6
+
7
+ const isMobile = ref(false);
8
+
9
+ vi.mock('../../utils/use-is-mobile.composable.ts', () => {
10
+ return {
11
+ useIsMobile: () => {
12
+ return {
13
+ isMobile: isMobile.value,
14
+ };
15
+ },
16
+ };
17
+ });
18
+
19
+ const MockedFooter = defineComponent({
20
+ name: 'MockedFooter',
21
+ setup() {
22
+ const expanded = inject(EXPANDED_SIDEBAR_KEY);
23
+ const toggle = inject(TOGGLE_SIDEBAR_KEY);
24
+ return { expanded, toggle };
25
+ },
26
+ template: `
27
+ <div>
28
+ <button data-test="toggle" @click="toggle">Toggle</button>
29
+ </div>
30
+ `,
31
+ });
32
+
33
+ describe('MSidebar', () => {
34
+ it('toggles expanded state and emits event when consumer calls toggle', async () => {
35
+ const wrapper = mount(MSidebar, {
36
+ global: { components: { MockedFooter } },
37
+ props: {
38
+ modelValue: true,
39
+ },
40
+ slots: {
41
+ header: '',
42
+ shortcuts: '',
43
+ nav: '',
44
+ footer: '<MockedFooter />',
45
+ },
46
+ });
47
+
48
+ const toggleBtn = wrapper.find('[data-test="toggle"]');
49
+ await toggleBtn.trigger('click');
50
+
51
+ const emitted = wrapper.emitted('update:modelValue') || [];
52
+ expect(emitted.length).toBe(1);
53
+ expect(emitted[0]).toEqual([false]);
54
+
55
+ await wrapper.setProps({ modelValue: emitted[0][0] as boolean });
56
+
57
+ const aside = wrapper.find('aside');
58
+ expect(aside.classes()).toContain('mc-sidebar--collapsed');
59
+ });
60
+
61
+ it('emits "close" when the close button is clicked', async () => {
62
+ const wrapper = mount(MSidebar, {
63
+ props: { modelValue: true },
64
+ global: {
65
+ stubs: ['MIconButton', 'Cross24'],
66
+ },
67
+ });
68
+
69
+ const btn = wrapper.find('.mc-sidebar__close-button');
70
+ await btn.trigger('click');
71
+
72
+ expect(wrapper.emitted()).toHaveProperty('close');
73
+ expect(wrapper.emitted('close')?.length).toBe(1);
74
+ });
75
+
76
+ describe('Resize handling', () => {
77
+ let addSpy: ReturnType<typeof vi.spyOn>;
78
+ let removeSpy: ReturnType<typeof vi.spyOn>;
79
+
80
+ beforeEach(() => {
81
+ vi.resetModules();
82
+ addSpy = vi.spyOn(window, 'addEventListener');
83
+ removeSpy = vi.spyOn(window, 'removeEventListener');
84
+ });
85
+
86
+ afterEach(() => {
87
+ addSpy.mockRestore();
88
+ removeSpy.mockRestore();
89
+ vi.clearAllMocks();
90
+ });
91
+
92
+ it('registers/unregisters resize listener and does not emit when isMobile is false', async () => {
93
+ isMobile.value = false;
94
+
95
+ const wrapper = mount(MSidebar, {
96
+ props: { modelValue: false },
97
+ });
98
+
99
+ expect(addSpy).toHaveBeenCalledWith('resize', expect.any(Function));
100
+
101
+ window.dispatchEvent(new Event('resize'));
102
+
103
+ const emitted = wrapper.emitted('update:modelValue');
104
+ expect(emitted).toBeUndefined();
105
+
106
+ wrapper.unmount();
107
+ expect(removeSpy).toHaveBeenCalledWith('resize', expect.any(Function));
108
+ });
109
+ });
110
+ });
@@ -0,0 +1,108 @@
1
+ import type { Meta, StoryObj } from '@storybook/vue3-vite';
2
+
3
+ import DefaultStory from './stories/DefaultCase.stories.vue';
4
+ import WithExpandOnlyStory from './stories/WithExpandOnly.stories.vue';
5
+ import WithProfileInfoOnlyStory from './stories/WithProfileInfoOnly.stories.vue';
6
+ import WithSingleLevelStory from './stories/WithSingleLevel.stories.vue';
7
+ import SourceCode from './stories/DefaultCase.stories.vue?raw';
8
+ import MSidebar from './MSidebar.vue';
9
+ import MSidebarHeader from '../sidebarheader/MSidebarHeader.vue';
10
+ import MSidebarFooter from '../sidebarfooter/MSidebarFooter.vue';
11
+ import MSidebarNavItem from '../sidebarnavitem/MSidebarNavItem.vue';
12
+ import MSidebarShortcutItem from '../sidebarshortcutitem/MSidebarShortcutItem.vue';
13
+ import MSidebarShortcuts from '../sidebarshortcuts/MSidebarShortcuts.vue';
14
+ import MSidebarExpandableItem from '../sidebarexpandableitem/MSidebarExpandableItem.vue';
15
+ import { action } from 'storybook/actions';
16
+
17
+ const meta: Meta<typeof MSidebar> = {
18
+ title: 'Structure/Sidebar',
19
+ component: MSidebar,
20
+ subcomponents: {
21
+ MSidebarExpandableItem,
22
+ MSidebarHeader,
23
+ MSidebarFooter,
24
+ MSidebarNavItem,
25
+ MSidebarShortcuts,
26
+ MSidebarShortcutItem,
27
+ },
28
+ tags: ['v2'],
29
+ parameters: {
30
+ layout: 'fullscreen',
31
+ docs: {
32
+ source: {
33
+ code: SourceCode,
34
+ },
35
+ description: {
36
+ component:
37
+ 'A sidebar is a vertical navigation component that provides quick access to key sections and functionalities within an application or website. It contains expandable menus, and shortcuts, allowing users to navigate efficiently while keeping the main content area uncluttered. Sidebars can be collapsible or persistent, adapting to different screen sizes and user preferences. They are commonly used in dashboards, content management systems, and productivity tools.',
38
+ },
39
+ },
40
+ },
41
+ globals: {
42
+ backgrounds: { value: 'secondary' },
43
+ },
44
+ render: () => ({
45
+ setup() {
46
+ const handleClose = action('close');
47
+ const handleUpdateModelValue = action('update:modelValue');
48
+ const handleLogOut = action('log-out');
49
+
50
+ return {
51
+ handleClose,
52
+ handleUpdateModelValue,
53
+ handleLogOut,
54
+ };
55
+ },
56
+ components: { DefaultStory },
57
+ template: `
58
+ <DefaultStory
59
+ @close="handleClose"
60
+ @update:model-value="handleUpdateModelValue"
61
+ @log-out="handleLogOut"
62
+ />
63
+ `,
64
+ }),
65
+ };
66
+ export default meta;
67
+ type Story = StoryObj<typeof MSidebar>;
68
+
69
+ export const Default: Story = {};
70
+
71
+ export const ExpandOnly: Story = {
72
+ render: () => ({
73
+ components: { WithExpandOnlyStory },
74
+ template: `
75
+ <WithExpandOnlyStory
76
+ @close="handleClose"
77
+ @update:model-value="handleUpdateModelValue"
78
+ @log-out="handleLogOut"
79
+ />
80
+ `,
81
+ }),
82
+ };
83
+
84
+ export const ProfileInfoOnly: Story = {
85
+ render: () => ({
86
+ components: { WithProfileInfoOnlyStory },
87
+ template: `
88
+ <WithProfileInfoOnlyStory
89
+ @close="handleClose"
90
+ @update:model-value="handleUpdateModelValue"
91
+ @log-out="handleLogOut"
92
+ />
93
+ `,
94
+ }),
95
+ };
96
+
97
+ export const SingleLevel: Story = {
98
+ render: () => ({
99
+ components: { WithSingleLevelStory },
100
+ template: `
101
+ <WithSingleLevelStory
102
+ @close="handleClose"
103
+ @update:model-value="handleUpdateModelValue"
104
+ @log-out="handleLogOut"
105
+ />
106
+ `,
107
+ }),
108
+ };
@@ -0,0 +1,124 @@
1
+ <template>
2
+ <aside
3
+ :class="[
4
+ 'mc-sidebar',
5
+ `mc-sidebar--${expanded ? 'expanded' : 'collapsed'}`,
6
+ ]"
7
+ >
8
+ <div class="mc-sidebar__wrapper">
9
+ <slot name="header" />
10
+
11
+ <slot name="shortcuts" />
12
+
13
+ <section class="mc-sidebar__container">
14
+ <nav
15
+ class="mc-sidebar__menu"
16
+ role="navigation"
17
+ aria-label="navigation items"
18
+ >
19
+ <ul class="mc-sidebar__list">
20
+ <slot name="nav" />
21
+ </ul>
22
+ </nav>
23
+ </section>
24
+
25
+ <slot name="footer" />
26
+ </div>
27
+
28
+ <MIconButton
29
+ class="mc-sidebar__close-button"
30
+ ghost
31
+ aria-label="Sidebar close button"
32
+ @click="emit('close')"
33
+ >
34
+ <template #icon>
35
+ <Cross24 />
36
+ </template>
37
+ </MIconButton>
38
+ </aside>
39
+ </template>
40
+
41
+ <script setup lang="ts">
42
+ import { computed, onMounted, onUnmounted, provide, type VNode } from 'vue';
43
+ import { EXPANDED_SIDEBAR_KEY, TOGGLE_SIDEBAR_KEY } from './MSidebar.const';
44
+ import MIconButton from '../iconbutton/MIconButton.vue';
45
+ import { Cross24 } from '@mozaic-ds/icons-vue';
46
+ import { useIsMobile } from '@/utils/use-is-mobile.composable';
47
+
48
+ /**
49
+ * A sidebar is a vertical navigation component that provides quick access to key sections and functionalities within an application or website. It contains expandable menus, and shortcuts, allowing users to navigate efficiently while keeping the main content area uncluttered. Sidebars can be collapsible or persistent, adapting to different screen sizes and user preferences. They are commonly used in dashboards, content management systems, and productivity tools.
50
+ */
51
+
52
+ const props = defineProps<{
53
+ /**
54
+ * the state of the expanded sidebar, bound via v-model.
55
+ */
56
+ modelValue: boolean;
57
+ }>();
58
+
59
+ const emit = defineEmits<{
60
+ /**
61
+ * Emits when the sidebar state changes.
62
+ */
63
+ (on: 'update:modelValue', value: boolean): void; /**
64
+ * Emits when the sidebar close button is clicked (mobile only).
65
+ */
66
+ (on: 'close'): void;
67
+ }>();
68
+
69
+ defineSlots<{
70
+ /**
71
+ * Slot for the sidebar header. Should contain an `MSidebarHeader` component.
72
+ */
73
+ header: VNode[];
74
+ /**
75
+ * Slot for sidebar shortcuts. Should contain an `MSidebarShortcuts` component
76
+ * with one or more `MSidebarShortcutItem` components inside.
77
+ */
78
+ shortcuts: VNode[];
79
+ /**
80
+ * Slot for the main navigation items. Should contain one or more `MSidebarNavItem` components.
81
+ */
82
+ nav: VNode[];
83
+ /**
84
+ * Slot for the sidebar footer. Should contain an `MSidebarFooter` component.
85
+ */
86
+ footer: VNode[];
87
+ }>();
88
+
89
+ const expanded = computed({
90
+ get() {
91
+ return props.modelValue;
92
+ },
93
+ set(value) {
94
+ emit('update:modelValue', value);
95
+ },
96
+ });
97
+
98
+ function toggleSidebar() {
99
+ expanded.value = !expanded.value;
100
+ }
101
+
102
+ provide(EXPANDED_SIDEBAR_KEY, expanded);
103
+ provide(TOGGLE_SIDEBAR_KEY, toggleSidebar);
104
+
105
+ const { isMobile } = useIsMobile();
106
+
107
+ function handleResize() {
108
+ if (isMobile.value) {
109
+ expanded.value = true;
110
+ }
111
+ }
112
+
113
+ onMounted(() => {
114
+ window.addEventListener('resize', handleResize);
115
+ });
116
+
117
+ onUnmounted(() => {
118
+ window.removeEventListener('resize', handleResize);
119
+ });
120
+ </script>
121
+
122
+ <style lang="scss" scoped>
123
+ @use '@mozaic-ds/styles/components/sidebar';
124
+ </style>
@@ -0,0 +1,59 @@
1
+ # MSidebar
2
+
3
+ A sidebar is a vertical navigation component that provides quick access to key sections and functionalities within an application or website. It contains expandable menus, and shortcuts, allowing users to navigate efficiently while keeping the main content area uncluttered. Sidebars can be collapsible or persistent, adapting to different screen sizes and user preferences. They are commonly used in dashboards, content management systems, and productivity tools.
4
+
5
+
6
+ ## Props
7
+
8
+ | Name | Description | Type | Default |
9
+ | --- | --- | --- | --- |
10
+ | `modelValue*` | the state of the expanded sidebar, bound via v-model. | `boolean` | - |
11
+
12
+ ## Slots
13
+
14
+ | Name | Description |
15
+ | --- | --- |
16
+ | `header` | Slot for the sidebar header. Should contain an `MSidebarHeader` component. |
17
+ | `shortcuts` | Slot for sidebar shortcuts. Should contain an `MSidebarShortcuts` component
18
+ with one or more `MSidebarShortcutItem` components inside. |
19
+ | `nav` | Slot for the main navigation items. Should contain one or more `MSidebarNavItem` components. |
20
+ | `footer` | Slot for the sidebar footer. Should contain an `MSidebarFooter` component. |
21
+
22
+ ## Events
23
+
24
+ | Name | Description | Type |
25
+ | --- | --- | --- |
26
+ | `update:modelValue` | Emits when the sidebar state changes. | [value: boolean] |
27
+ | `close` | Emits when the sidebar close button is clicked (mobile only). | [] |
28
+
29
+ ## Dependencies
30
+
31
+ ### Depends on
32
+
33
+ - [MIconButton](../iconbutton)
34
+
35
+ ### Graph
36
+
37
+ ```mermaid
38
+ graph TD;
39
+ MSidebar --> MIconButton
40
+ style MSidebar fill:#008240,stroke:#333,stroke-width:4px
41
+ ```
42
+
43
+ ### Used By
44
+
45
+ - [DefaultCase.stories](stories)
46
+ - [WithExpandOnly.stories](stories)
47
+ - [WithProfileInfoOnly.stories](stories)
48
+ - [WithSingleLevel.stories](stories)
49
+
50
+ ### Graph
51
+
52
+ ```mermaid
53
+ graph TD;
54
+ DefaultCase.stories --> MSidebar
55
+ WithExpandOnly.stories --> MSidebar
56
+ WithProfileInfoOnly.stories --> MSidebar
57
+ WithSingleLevel.stories --> MSidebar
58
+ style MSidebar fill:#008240,stroke:#333,stroke-width:4px
59
+ ```
@@ -0,0 +1,120 @@
1
+ <template>
2
+ <MSidebar
3
+ v-model="expanded"
4
+ @update:model-value="emit('update:modelValue')"
5
+ @close="emit('close')"
6
+ >
7
+ <template #header>
8
+ <MSidebarHeader title="Adeo Design System" logo="/logo.svg" />
9
+ </template>
10
+
11
+ <template #shortcuts>
12
+ <MSidebarShortcuts stacked>
13
+ <MSidebarShortcutItem
14
+ v-for="(item, index) in shortcutItems"
15
+ :key="index"
16
+ v-bind="item"
17
+ />
18
+ </MSidebarShortcuts>
19
+ </template>
20
+
21
+ <template #nav>
22
+ <template v-for="(item, index) in navigationItems" :key="index">
23
+ <MSidebarExpandableItem
24
+ v-if="item.items"
25
+ menu-label="Sublist menu label"
26
+ :label="item.label"
27
+ :icon="item.icon"
28
+ >
29
+ <MSidebarNavItem
30
+ v-for="(subItem, subIndex) in item.items"
31
+ :key="subIndex"
32
+ v-bind="subItem"
33
+ :active="active === `subNav-${subIndex}`"
34
+ @click="active = `subNav-${subIndex}`"
35
+ />
36
+ </MSidebarExpandableItem>
37
+
38
+ <MSidebarNavItem
39
+ v-else
40
+ v-bind="item"
41
+ :active="active === `nav-${index}`"
42
+ @click="active = `nav-${index}`"
43
+ />
44
+ </template>
45
+ </template>
46
+
47
+ <template #footer>
48
+ <MSidebarFooter
49
+ title="Dieter Rams"
50
+ subtitle="Industrial designer"
51
+ href="#"
52
+ avatar="/images/Avatar.png"
53
+ @log-out="emit('log-out')"
54
+ >
55
+ <MSidebarNavItem
56
+ v-for="(item, index) in footerMenuItems"
57
+ :key="index"
58
+ v-bind="item"
59
+ :active="active === `footer-${index}`"
60
+ @click="active = `footer-${index}`"
61
+ />
62
+ </MSidebarFooter>
63
+ </template>
64
+ </MSidebar>
65
+ </template>
66
+
67
+ <script setup lang="ts">
68
+ import { ref } from 'vue';
69
+ import {
70
+ Coffee24,
71
+ Course24,
72
+ Sample24,
73
+ Release24,
74
+ Palette24,
75
+ Pantone24,
76
+ Admin24,
77
+ } from '@mozaic-ds/icons-vue';
78
+
79
+ import MSidebar from '../MSidebar.vue';
80
+ import MSidebarExpandableItem from '../../sidebarexpandableitem/MSidebarExpandableItem.vue';
81
+ import MSidebarFooter from '../../sidebarfooter/MSidebarFooter.vue';
82
+ import MSidebarHeader from '../../sidebarheader/MSidebarHeader.vue';
83
+ import MSidebarNavItem from '../../sidebarnavitem/MSidebarNavItem.vue';
84
+ import MSidebarShortcutItem from '../../sidebarshortcutitem/MSidebarShortcutItem.vue';
85
+ import MSidebarShortcuts from '../../sidebarshortcuts/MSidebarShortcuts.vue';
86
+
87
+ const emit = defineEmits(['close', 'update:modelValue', 'log-out']);
88
+
89
+ const expanded = ref(true);
90
+
91
+ const active = ref('');
92
+
93
+ const shortcutItems = [
94
+ { label: 'Shortcut 01', icon: Coffee24, href: '#' },
95
+ { label: 'Shortcut 02', icon: Course24, href: '#' },
96
+ ];
97
+
98
+ const navigationItems = [
99
+ { label: 'Get Started', href: '#', icon: Release24 },
100
+ {
101
+ label: 'Design Tokens',
102
+ icon: Sample24,
103
+ items: [
104
+ { label: 'Subsection menu label 1', href: '#', locked: true },
105
+ { label: 'Subsection menu label 2', href: '#', external: true },
106
+ { label: 'Subsection menu label 2', href: '#' },
107
+ { label: 'Subsection menu label 2', href: '#' },
108
+ ],
109
+ },
110
+ { label: 'Styles', href: '#', icon: Palette24 },
111
+ { label: 'Components', href: '#', icon: Pantone24 },
112
+ ];
113
+
114
+ const footerMenuItems = [
115
+ { label: 'Action 01', icon: Admin24, href: '#' },
116
+ { label: 'Action 02', icon: Admin24, href: '#' },
117
+ { label: 'Action 03', icon: Admin24, href: '#' },
118
+ { label: 'Action 04', icon: Admin24, href: '#' },
119
+ ];
120
+ </script>
@@ -0,0 +1,27 @@
1
+ # WithSingleLevel.stories
2
+
3
+
4
+
5
+ ## Dependencies
6
+
7
+ ### Depends on
8
+
9
+ - [MSidebar](..)
10
+ - [MSidebarFooter](../../sidebarfooter)
11
+ - [MSidebarHeader](../../sidebarheader)
12
+ - [MSidebarNavItem](../../sidebarnavitem)
13
+ - [MSidebarShortcutItem](../../sidebarshortcutitem)
14
+ - [MSidebarShortcuts](../../sidebarshortcuts)
15
+
16
+ ### Graph
17
+
18
+ ```mermaid
19
+ graph TD;
20
+ WithSingleLevel.stories --> MSidebar
21
+ WithSingleLevel.stories --> MSidebarFooter
22
+ WithSingleLevel.stories --> MSidebarHeader
23
+ WithSingleLevel.stories --> MSidebarNavItem
24
+ WithSingleLevel.stories --> MSidebarShortcutItem
25
+ WithSingleLevel.stories --> MSidebarShortcuts
26
+ style WithSingleLevel.stories fill:#008240,stroke:#333,stroke-width:4px
27
+ ```
@@ -0,0 +1,112 @@
1
+ <template>
2
+ <MSidebar
3
+ v-model="expanded"
4
+ @update:model-value="emit('update:modelValue')"
5
+ @close="emit('close')"
6
+ >
7
+ <template #header>
8
+ <MSidebarHeader title="Adeo Design System" logo="/logo.svg" />
9
+ </template>
10
+
11
+ <template #shortcuts>
12
+ <MSidebarShortcuts>
13
+ <MSidebarShortcutItem
14
+ v-for="(item, index) in shortcutItems"
15
+ :key="index"
16
+ v-bind="item"
17
+ />
18
+ </MSidebarShortcuts>
19
+ </template>
20
+
21
+ <template #nav>
22
+ <template v-for="(item, index) in navigationItems" :key="index">
23
+ <MSidebarExpandableItem
24
+ v-if="item.items"
25
+ menu-label="Sublist menu label"
26
+ :label="item.label"
27
+ :icon="item.icon"
28
+ >
29
+ <MSidebarNavItem
30
+ v-for="(subItem, subIndex) in item.items"
31
+ :key="subIndex"
32
+ v-bind="subItem"
33
+ :active="active === `subNav-${subIndex}`"
34
+ @click="active = `subNav-${subIndex}`"
35
+ />
36
+ </MSidebarExpandableItem>
37
+
38
+ <MSidebarNavItem
39
+ v-else
40
+ v-bind="item"
41
+ :active="active === `nav-${index}`"
42
+ @click="active = `nav-${index}`"
43
+ />
44
+ </template>
45
+ </template>
46
+
47
+ <template #footer>
48
+ <MSidebarFooter @log-out="emit('log-out')">
49
+ <MSidebarNavItem
50
+ v-for="(item, index) in footerMenuItems"
51
+ :key="index"
52
+ v-bind="item"
53
+ :active="active === `footer-${index}`"
54
+ @click="active = `footer-${index}`"
55
+ />
56
+ </MSidebarFooter>
57
+ </template>
58
+ </MSidebar>
59
+ </template>
60
+
61
+ <script setup lang="ts">
62
+ import { ref } from 'vue';
63
+ import {
64
+ Coffee24,
65
+ Course24,
66
+ Sample24,
67
+ Release24,
68
+ Palette24,
69
+ Pantone24,
70
+ Admin24,
71
+ } from '@mozaic-ds/icons-vue';
72
+
73
+ import MSidebar from '../MSidebar.vue';
74
+ import MSidebarExpandableItem from '../../sidebarexpandableitem/MSidebarExpandableItem.vue';
75
+ import MSidebarFooter from '../../sidebarfooter/MSidebarFooter.vue';
76
+ import MSidebarHeader from '../../sidebarheader/MSidebarHeader.vue';
77
+ import MSidebarNavItem from '../../sidebarnavitem/MSidebarNavItem.vue';
78
+ import MSidebarShortcutItem from '../../sidebarshortcutitem/MSidebarShortcutItem.vue';
79
+ import MSidebarShortcuts from '../../sidebarshortcuts/MSidebarShortcuts.vue';
80
+
81
+ const emit = defineEmits(['close', 'update:modelValue', 'log-out']);
82
+
83
+ const expanded = ref(true);
84
+
85
+ const active = ref('');
86
+
87
+ const shortcutItems = [
88
+ { label: 'Shortcut 01', icon: Coffee24, href: '#' },
89
+ { label: 'Shortcut 02', icon: Course24, href: '#' },
90
+ ];
91
+
92
+ const navigationItems = [
93
+ { label: 'Get Started', href: '#', icon: Release24 },
94
+ {
95
+ label: 'Design Tokens',
96
+ icon: Sample24,
97
+ items: [
98
+ { label: 'Subsection menu label 1', href: '#', locked: true },
99
+ { label: 'Subsection menu label 2', href: '#', external: true },
100
+ ],
101
+ },
102
+ { label: 'Styles', href: '#', icon: Palette24 },
103
+ { label: 'Components', href: '#', icon: Pantone24 },
104
+ ];
105
+
106
+ const footerMenuItems = [
107
+ { label: 'Action 01', icon: Admin24, href: '#' },
108
+ { label: 'Action 02', icon: Admin24, href: '#' },
109
+ { label: 'Action 03', icon: Admin24, href: '#' },
110
+ { label: 'Action 04', icon: Admin24, href: '#' },
111
+ ];
112
+ </script>