@mozaic-ds/vue 2.11.0 → 2.13.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 (125) hide show
  1. package/dist/mozaic-vue.css +1 -1
  2. package/dist/mozaic-vue.d.ts +791 -353
  3. package/dist/mozaic-vue.js +2945 -2404
  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 +7 -6
  8. package/src/components/{usingPresets.mdx → BrandPresets.mdx} +2 -2
  9. package/src/components/Changelog.mdx +19 -0
  10. package/src/components/Color.mdx +226 -0
  11. package/src/components/Contributing.mdx +12 -6
  12. package/src/components/GettingStarted.mdx +1 -1
  13. package/src/components/Icon.stories.ts +134 -0
  14. package/src/components/Welcome.mdx +49 -0
  15. package/src/components/accordionlist/MAccordionList.spec.ts +136 -0
  16. package/src/components/accordionlist/MAccordionList.stories.ts +123 -0
  17. package/src/components/accordionlist/MAccordionList.vue +91 -0
  18. package/src/components/accordionlist/README.md +24 -0
  19. package/src/components/accordionlist/m-accordion-list.const.ts +9 -0
  20. package/src/components/accordionlistitem/MAccordionListItem.spec.ts +123 -0
  21. package/src/components/accordionlistitem/MAccordionListItem.vue +95 -0
  22. package/src/components/accordionlistitem/README.md +23 -0
  23. package/src/components/actionbottombar/MActionBottomBar.spec.ts +52 -0
  24. package/src/components/actionbottombar/MActionBottomBar.stories.ts +162 -0
  25. package/src/components/actionbottombar/MActionBottomBar.vue +45 -0
  26. package/src/components/actionbottombar/README.md +31 -0
  27. package/src/components/actionlistbox/MActionListbox.spec.ts +134 -0
  28. package/src/components/actionlistbox/MActionListbox.stories.ts +74 -0
  29. package/src/components/actionlistbox/MActionListbox.vue +89 -0
  30. package/src/components/actionlistbox/README.md +25 -0
  31. package/src/components/avatar/MAvatar.stories.ts +1 -1
  32. package/src/components/breadcrumb/README.md +14 -0
  33. package/src/components/builtinmenu/MBuiltInMenu.spec.ts +111 -0
  34. package/src/components/builtinmenu/MBuiltInMenu.stories.ts +59 -0
  35. package/src/components/builtinmenu/MBuiltInMenu.vue +110 -0
  36. package/src/components/builtinmenu/README.md +32 -0
  37. package/src/components/button/MButton.spec.ts +1 -1
  38. package/src/components/button/MButton.stories.ts +165 -5
  39. package/src/components/button/README.md +33 -1
  40. package/src/components/callout/MCallout.spec.ts +7 -6
  41. package/src/components/callout/MCallout.stories.ts +1 -2
  42. package/src/components/carousel/MCarousel.spec.ts +1 -2
  43. package/src/components/carousel/MCarousel.stories.ts +2 -1
  44. package/src/components/carousel/MCarousel.vue +1 -2
  45. package/src/components/carousel/README.md +14 -0
  46. package/src/components/checkbox/README.md +14 -0
  47. package/src/components/checkboxgroup/README.md +14 -0
  48. package/src/components/checklistmenu/MCheckListMenu.spec.ts +77 -0
  49. package/src/components/checklistmenu/MCheckListMenu.stories.ts +47 -0
  50. package/src/components/checklistmenu/MCheckListMenu.vue +61 -0
  51. package/src/components/checklistmenu/README.md +32 -0
  52. package/src/components/circularprogressbar/README.md +15 -1
  53. package/src/components/datepicker/MDatepicker.vue +1 -1
  54. package/src/components/divider/README.md +22 -0
  55. package/src/components/drawer/MDrawer.vue +1 -2
  56. package/src/components/drawer/README.md +16 -0
  57. package/src/components/field/README.md +14 -0
  58. package/src/components/fileuploader/MFileUploader.spec.ts +304 -0
  59. package/src/components/fileuploader/MFileUploader.stories.ts +123 -0
  60. package/src/components/fileuploader/MFileUploader.vue +314 -0
  61. package/src/components/fileuploader/README.md +58 -0
  62. package/src/components/fileuploaderitem/MFileUploaderItem.spec.ts +91 -0
  63. package/src/components/fileuploaderitem/MFileUploaderItem.vue +180 -0
  64. package/src/components/fileuploaderitem/README.md +58 -0
  65. package/src/components/flag/README.md +1 -1
  66. package/src/components/iconbutton/MIconButton.spec.ts +1 -1
  67. package/src/components/iconbutton/MIconButton.stories.ts +116 -7
  68. package/src/components/iconbutton/README.md +25 -1
  69. package/src/components/kpiitem/MKpiItem.vue +5 -3
  70. package/src/components/linearprogressbarbuffer/README.md +14 -0
  71. package/src/components/link/MLink.stories.ts +1 -2
  72. package/src/components/link/README.md +14 -0
  73. package/src/components/loader/README.md +20 -0
  74. package/src/components/loadingoverlay/README.md +14 -0
  75. package/src/components/modal/MModal.stories.ts +1 -2
  76. package/src/components/modal/MModal.vue +1 -1
  77. package/src/components/modal/README.md +16 -0
  78. package/src/components/numberbadge/README.md +17 -1
  79. package/src/components/overlay/README.md +16 -0
  80. package/src/components/pagination/MPagination.vue +1 -2
  81. package/src/components/pagination/README.md +18 -0
  82. package/src/components/passwordinput/MPasswordInput.vue +1 -1
  83. package/src/components/passwordinput/README.md +14 -0
  84. package/src/components/phonenumber/MPhoneNumber.spec.ts +7 -6
  85. package/src/components/phonenumber/MPhoneNumber.vue +1 -1
  86. package/src/components/quantityselector/MQuantitySelector.vue +1 -2
  87. package/src/components/radio/README.md +14 -0
  88. package/src/components/radiogroup/README.md +14 -0
  89. package/src/components/select/README.md +14 -0
  90. package/src/components/starrating/MStarRating.spec.ts +1 -2
  91. package/src/components/starrating/MStarRating.vue +1 -3
  92. package/src/components/statusbadge/README.md +14 -0
  93. package/src/components/statusdot/README.md +14 -0
  94. package/src/components/statusmessage/MStatusMessage.spec.ts +6 -4
  95. package/src/components/statusmessage/MStatusMessage.vue +6 -4
  96. package/src/components/statusmessage/README.md +14 -0
  97. package/src/components/statusnotification/MStatusNotification.spec.ts +6 -4
  98. package/src/components/statusnotification/MStatusNotification.stories.ts +1 -1
  99. package/src/components/statusnotification/MStatusNotification.vue +7 -5
  100. package/src/components/statusnotification/README.md +14 -0
  101. package/src/components/stepperbottombar/MStepperBottomBar.spec.ts +134 -0
  102. package/src/components/stepperbottombar/MStepperBottomBar.stories.ts +72 -0
  103. package/src/components/stepperbottombar/MStepperBottomBar.vue +131 -0
  104. package/src/components/stepperbottombar/README.md +40 -0
  105. package/src/components/steppercompact/README.md +14 -0
  106. package/src/components/stepperinline/MStepperInline.spec.ts +78 -0
  107. package/src/components/stepperinline/MStepperInline.stories.ts +49 -0
  108. package/src/components/stepperinline/MStepperInline.vue +93 -0
  109. package/src/components/stepperinline/README.md +11 -0
  110. package/src/components/tabs/MTabs.stories.ts +1 -1
  111. package/src/components/tabs/README.md +16 -0
  112. package/src/components/tag/MTag.vue +1 -1
  113. package/src/components/tag/README.md +14 -0
  114. package/src/components/textinput/MTextInput.spec.ts +1 -1
  115. package/src/components/textinput/MTextInput.stories.ts +1 -1
  116. package/src/components/textinput/MTextInput.vue +1 -1
  117. package/src/components/toaster/MToaster.spec.ts +6 -4
  118. package/src/components/toaster/MToaster.vue +7 -5
  119. package/src/components/toaster/README.md +16 -0
  120. package/src/components/toggle/README.md +14 -0
  121. package/src/components/togglegroup/README.md +14 -0
  122. package/src/main.ts +8 -0
  123. package/src/components/Introduction.mdx +0 -100
  124. package/src/components/Support.mdx +0 -18
  125. package/src/components/usingIcons.mdx +0 -35
@@ -0,0 +1,162 @@
1
+ import type { Meta, StoryObj } from '@storybook/vue3-vite';
2
+
3
+ import MActionBottomBar from './MActionBottomBar.vue';
4
+ import MStatusMessage from '../statusmessage/MStatusMessage.vue';
5
+ import MButton from '../button/MButton.vue';
6
+
7
+ // Icons
8
+ import { Refresh24, Cross24, Check24 } from '@mozaic-ds/icons-vue';
9
+
10
+ const meta: Meta<typeof MActionBottomBar> = {
11
+ title: 'Structure/Action Bottom Bar',
12
+ component: MActionBottomBar,
13
+ tags: ['v2'],
14
+ parameters: {
15
+ layout: 'fullscreen',
16
+ docs: {
17
+ story: { height: '150px' },
18
+ description: {
19
+ component:
20
+ 'An action bottom bar is a fixed element positioned at the bottom of the screen or section, providing persistent access to key actions. It is commonly used for confirmations, validations, warnings, or bulk actions in forms, editing workflows, or data management. This component ensures that primary and secondary actions remain visible and accessible, even when scrolling.',
21
+ },
22
+ },
23
+ },
24
+ args: {
25
+ left: `
26
+ <MStatusMessage status="warning" label="999 unsaved changes"/>
27
+ `,
28
+ right: `
29
+ <MButton size="s" ghost>
30
+ Reset
31
+ </MButton>
32
+ <MButton size="s" outlined appearance="danger">
33
+ Delete
34
+ </MButton>
35
+ <MButton size="s" appearance="accent">
36
+ Save
37
+ </MButton>
38
+ `,
39
+ },
40
+ render: (args) => ({
41
+ components: {
42
+ MActionBottomBar,
43
+ MStatusMessage,
44
+ MButton,
45
+ Refresh24,
46
+ Cross24,
47
+ Check24,
48
+ },
49
+ setup() {
50
+ return { args };
51
+ },
52
+ template: `
53
+ <MActionBottomBar v-bind="args">
54
+ <template v-if="${'left' in args}" v-slot:left>${args.left}</template>
55
+ <template v-if="${'right' in args}" v-slot:right>${args.right}</template>
56
+ </MActionBottomBar>
57
+ `,
58
+ }),
59
+ };
60
+
61
+ export default meta;
62
+
63
+ type Story = StoryObj<typeof MActionBottomBar>;
64
+
65
+ export const Default: Story = {};
66
+
67
+ export const Shadow: Story = {
68
+ args: {
69
+ shadow: true,
70
+ },
71
+ };
72
+
73
+ export const Unsaved: Story = {
74
+ args: {
75
+ right: `
76
+ <MButton size="s" appearance="accent">
77
+ Save
78
+ </MButton>
79
+ `,
80
+ },
81
+ };
82
+
83
+ export const SaveInProgress: Story = {
84
+ args: {
85
+ left: `
86
+ <MStatusMessage status="inprogress" label="Saving changes"/>
87
+ `,
88
+ right: `
89
+ <MButton size="s" appearance="accent">
90
+ Save
91
+ </MButton>
92
+ `,
93
+ },
94
+ };
95
+
96
+ export const Saved: Story = {
97
+ args: {
98
+ left: `
99
+ <MStatusMessage status="success" label="Changes saved"/>
100
+ `,
101
+ right: `
102
+ <MButton size="s" appearance="accent">
103
+ Save
104
+ </MButton>
105
+ `,
106
+ },
107
+ };
108
+
109
+ export const WithoutReset: Story = {
110
+ args: {
111
+ right: `
112
+ <MButton size="s" outlined appearance="danger">
113
+ Delete
114
+ </MButton>
115
+ <MButton size="s" appearance="accent">
116
+ Save
117
+ </MButton>
118
+ `,
119
+ },
120
+ };
121
+
122
+ export const WithoutDelete: Story = {
123
+ args: {
124
+ right: `
125
+ <MButton size="s" appearance="accent">
126
+ Save
127
+ </MButton>
128
+ `,
129
+ },
130
+ };
131
+
132
+ export const Mobile: Story = {
133
+ args: {
134
+ right: `
135
+ <MButton
136
+ ghost
137
+ icon-position="only"
138
+ >
139
+ <template #icon>
140
+ <Refresh24/>
141
+ </template>
142
+ </MButton>
143
+ <MButton
144
+ outlined
145
+ appearance="danger"
146
+ icon-position="only"
147
+ >
148
+ <template #icon>
149
+ <Cross24/>
150
+ </template>
151
+ </MButton>
152
+ <MButton
153
+ appearance="accent"
154
+ icon-position="only"
155
+ >
156
+ <template #icon>
157
+ <Check24/>
158
+ </template>
159
+ </MButton>
160
+ `,
161
+ },
162
+ };
@@ -0,0 +1,45 @@
1
+ <template>
2
+ <div
3
+ class="mc-action-bottom-bar"
4
+ :class="{ 'mc-action-bottom-bar--shadow': shadow }"
5
+ >
6
+ <MDivider class="mc-action-bottom-bar__divider" />
7
+
8
+ <div class="mc-action-bottom-bar__left">
9
+ <slot name="left" />
10
+ </div>
11
+
12
+ <div class="mc-action-bottom-bar__right">
13
+ <slot name="right" />
14
+ </div>
15
+ </div>
16
+ </template>
17
+
18
+ <script setup lang="ts">
19
+ import type { VNode } from 'vue';
20
+ import MDivider from '../divider/MDivider.vue';
21
+ /**
22
+ * An action bottom bar is a fixed element positioned at the bottom of the screen or section, providing persistent access to key actions. It is commonly used for confirmations, validations, warnings, or bulk actions in forms, editing workflows, or data management. This component ensures that primary and secondary actions remain visible and accessible, even when scrolling.
23
+ */
24
+ defineProps<{
25
+ /**
26
+ * If `true`, adds a shadow to the action bottom bar.
27
+ */
28
+ shadow?: boolean;
29
+ }>();
30
+
31
+ defineSlots<{
32
+ /**
33
+ * The content displayed left side of the action bottom bar (e.g. StatusNotification or any element).
34
+ */
35
+ left: VNode[];
36
+ /**
37
+ * Use this slot to insert buttons of the action bottom bar.
38
+ */
39
+ right?: VNode[];
40
+ }>();
41
+ </script>
42
+
43
+ <style lang="scss" scoped>
44
+ @use '@mozaic-ds/styles/components/action-bottom-bar';
45
+ </style>
@@ -0,0 +1,31 @@
1
+ # MActionBottomBar
2
+
3
+ An action bottom bar is a fixed element positioned at the bottom of the screen or section, providing persistent access to key actions. It is commonly used for confirmations, validations, warnings, or bulk actions in forms, editing workflows, or data management. This component ensures that primary and secondary actions remain visible and accessible, even when scrolling.
4
+
5
+
6
+ ## Props
7
+
8
+ | Name | Description | Type | Default |
9
+ | --- | --- | --- | --- |
10
+ | `shadow` | If `true`, adds a shadow to the action bottom bar. | `boolean` | - |
11
+
12
+ ## Slots
13
+
14
+ | Name | Description |
15
+ | --- | --- |
16
+ | `left` | The content displayed left side of the action bottom bar (e.g. StatusNotification or any element). |
17
+ | `right` | Use this slot to insert buttons of the action bottom bar. |
18
+
19
+ ## Dependencies
20
+
21
+ ### Depends on
22
+
23
+ - [MDivider](../divider)
24
+
25
+ ### Graph
26
+
27
+ ```mermaid
28
+ graph TD;
29
+ MActionBottomBar --> MDivider
30
+ style MActionBottomBar fill:#008240,stroke:#333,stroke-width:4px
31
+ ```
@@ -0,0 +1,134 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { mount } from '@vue/test-utils';
3
+ import { defineComponent, h, markRaw } from 'vue';
4
+ import MActionListbox from './MActionListbox.vue';
5
+ import MDivider from '../divider/MDivider.vue';
6
+ import MIconButton from '../iconbutton/MIconButton.vue';
7
+ import { Cross24 } from '@mozaic-ds/icons-vue';
8
+
9
+ // Dummy icon wrapped with markRaw to avoid reactive warnings
10
+ const DummyIcon = markRaw(
11
+ defineComponent({
12
+ name: 'DummyIcon',
13
+ render() {
14
+ return h('svg', { 'data-testid': 'icon' }, [
15
+ h('circle', { cx: 10, cy: 10, r: 10 }),
16
+ ]);
17
+ },
18
+ }),
19
+ );
20
+
21
+ const items = [
22
+ {
23
+ label: 'Duplicate',
24
+ icon: DummyIcon,
25
+ },
26
+ {
27
+ label: 'Move to...',
28
+ icon: DummyIcon,
29
+ },
30
+ {
31
+ label: 'Download',
32
+ icon: DummyIcon,
33
+ },
34
+ {
35
+ label: 'Delete',
36
+ icon: DummyIcon,
37
+ appearance: 'danger' as const,
38
+ divider: true,
39
+ },
40
+ ];
41
+
42
+ describe('MActionListbox', () => {
43
+ it('renders the title if provided', () => {
44
+ const wrapper = mount(MActionListbox, {
45
+ props: {
46
+ title: 'Action List',
47
+ items,
48
+ },
49
+ global: {
50
+ components: {
51
+ MDivider,
52
+ MIconButton,
53
+ Cross24,
54
+ },
55
+ },
56
+ });
57
+
58
+ expect(wrapper.find('.mc-listbox__title').text()).toBe('Action List');
59
+ });
60
+
61
+ it('renders all item labels', () => {
62
+ const wrapper = mount(MActionListbox, {
63
+ props: {
64
+ items,
65
+ },
66
+ global: {
67
+ components: {
68
+ MDivider,
69
+ MIconButton,
70
+ Cross24,
71
+ },
72
+ },
73
+ });
74
+
75
+ items.forEach((item) => {
76
+ expect(wrapper.text()).toContain(item.label);
77
+ });
78
+ });
79
+
80
+ it('renders icons for each item', () => {
81
+ const wrapper = mount(MActionListbox, {
82
+ props: {
83
+ items,
84
+ },
85
+ global: {
86
+ components: {
87
+ MDivider,
88
+ MIconButton,
89
+ Cross24,
90
+ },
91
+ },
92
+ });
93
+
94
+ const icons = wrapper.findAll('[data-testid="icon"]');
95
+ expect(icons.length).toBe(items.length);
96
+ });
97
+
98
+ it('adds danger class to items with appearance set to danger', () => {
99
+ const wrapper = mount(MActionListbox, {
100
+ props: {
101
+ items,
102
+ },
103
+ global: {
104
+ components: {
105
+ MDivider,
106
+ MIconButton,
107
+ Cross24,
108
+ },
109
+ },
110
+ });
111
+
112
+ const dangerousItem = wrapper.findAll('.mc-action-list__element--danger');
113
+ expect(dangerousItem.length).toBe(1);
114
+ expect(dangerousItem[0].text()).toContain('Delete');
115
+ });
116
+
117
+ it('renders MDivider with divider set to true', () => {
118
+ const wrapper = mount(MActionListbox, {
119
+ props: {
120
+ items,
121
+ },
122
+ global: {
123
+ components: {
124
+ MDivider,
125
+ MIconButton,
126
+ Cross24,
127
+ },
128
+ },
129
+ });
130
+
131
+ const dividers = wrapper.findAll('.mc-action-list__divider');
132
+ expect(dividers.length).toBe(1);
133
+ });
134
+ });
@@ -0,0 +1,74 @@
1
+ import type { Meta, StoryObj } from '@storybook/vue3-vite';
2
+
3
+ import MActionListbox from './MActionListbox.vue';
4
+ import {
5
+ Copy20,
6
+ ArrowTopRight20,
7
+ Download20,
8
+ Trash20,
9
+ } from '@mozaic-ds/icons-vue';
10
+
11
+ const meta: Meta<typeof MActionListbox> = {
12
+ title: 'Overlay/Action Listbox',
13
+ component: MActionListbox,
14
+ parameters: {
15
+ docs: {
16
+ description: {
17
+ component:
18
+ 'An action list is a contextual menu that presents a list of available actions related to a specific element or interface area. It allows users to quickly access functions such as editing, sharing, deleting, or navigating to sub-actions. Action Lists are commonly triggered by buttons, icons (e.g., three-dot menus), or right-click interactions, ensuring a clean and efficient UI.',
19
+ },
20
+ source: {
21
+ code: `
22
+ <template>
23
+ <MActionListbox
24
+ :items="[
25
+ { label: 'Duplicate', icon: Copy20, disabled: true },
26
+ { label: 'Move to...', icon: ArrowTopRight20 },
27
+ { label: 'Download', icon: Download20 },
28
+ { label: 'Delete', icon: Trash20, appearance: 'danger', divider: true }
29
+ ]"
30
+ title="Listbox title (optional)"
31
+ />
32
+ </template>
33
+ `,
34
+ },
35
+ },
36
+ },
37
+ args: {
38
+ title: 'Listbox title (optional)',
39
+ items: [
40
+ {
41
+ label: 'Duplicate',
42
+ icon: Copy20,
43
+ disabled: true,
44
+ },
45
+ {
46
+ label: 'Move to...',
47
+ icon: ArrowTopRight20,
48
+ },
49
+ {
50
+ label: 'Download',
51
+ icon: Download20,
52
+ },
53
+ {
54
+ label: 'Delete',
55
+ icon: Trash20,
56
+ appearance: 'danger',
57
+ divider: true,
58
+ },
59
+ ],
60
+ },
61
+ render: (args) => ({
62
+ components: { MActionListbox },
63
+ setup() {
64
+ return { args };
65
+ },
66
+ template: `
67
+ <MActionListbox v-bind="args"></MActionListbox>
68
+ `,
69
+ }),
70
+ };
71
+ export default meta;
72
+ type Story = StoryObj<typeof MActionListbox>;
73
+
74
+ export const Default: Story = {};
@@ -0,0 +1,89 @@
1
+ <template>
2
+ <div class="mc-listbox">
3
+ <div class="mc-listbox__content">
4
+ <div class="mc-listbox__header">
5
+ <h3 v-if="title" class="mc-listbox__title">{{ title }}</h3>
6
+ <MIconButton class="mc-listbox__close" ghost aria-label="Close">
7
+ <template #icon>
8
+ <Cross24 aria-hidden="true" />
9
+ </template>
10
+ </MIconButton>
11
+ </div>
12
+ <div class="mc-listbox__body">
13
+ <ul class="mc-action-list" role="menu">
14
+ <template v-for="(item, index) in items" :key="`item-${index}`">
15
+ <MDivider
16
+ v-if="item.divider"
17
+ class="mc-action-list__divider"
18
+ role="separator"
19
+ ></MDivider>
20
+ <li
21
+ :class="[
22
+ 'mc-action-list__element',
23
+ {
24
+ 'mc-action-list__element--danger':
25
+ item.appearance === 'danger',
26
+ 'mc-action-list__element--disabled': item.disabled,
27
+ },
28
+ ]"
29
+ role="menuitem"
30
+ >
31
+ <button type="button" class="mc-action-list__button">
32
+ <component
33
+ v-if="item.icon"
34
+ class="mc-action-list__icon"
35
+ :is="item.icon"
36
+ />
37
+ <p class="mc-action-list__text">{{ item.label }}</p>
38
+ </button>
39
+ </li>
40
+ </template>
41
+ </ul>
42
+ </div>
43
+ </div>
44
+ </div>
45
+ </template>
46
+
47
+ <script setup lang="ts">
48
+ import type { Component } from 'vue';
49
+ import MDivider from '../divider/MDivider.vue';
50
+ /**
51
+ * An action list is a contextual menu that presents a list of available actions related to a specific element or interface area. It allows users to quickly access functions such as editing, sharing, deleting, or navigating to sub-actions. Action Lists are commonly triggered by buttons, icons (e.g., three-dot menus), or right-click interactions, ensuring a clean and efficient UI.
52
+ */
53
+ defineProps<{
54
+ /**
55
+ * title displayed in mobile version.
56
+ */
57
+ title?: string;
58
+ /**
59
+ * An array of objects that allows you to provide all the data needed to generate the content for each item.
60
+ */
61
+ items: Array<{
62
+ /**
63
+ * The icon displayed for the item from Mozaic-icon-vue.
64
+ */
65
+ icon?: Component;
66
+ /**
67
+ * The label displayed for the item.
68
+ */
69
+ label: string;
70
+ /**
71
+ * If `true`, the item will be disabled.
72
+ */
73
+ disabled?: boolean;
74
+ /**
75
+ * Allows to define the item appearance.
76
+ */
77
+ appearance?: 'standard' | 'danger';
78
+ /**
79
+ * Add a divider on top of the item.
80
+ */
81
+ divider?: boolean;
82
+ }>;
83
+ }>();
84
+ </script>
85
+
86
+ <style lang="scss" scoped>
87
+ @use '@mozaic-ds/styles/components/listbox';
88
+ @use '@mozaic-ds/styles/components/action-list';
89
+ </style>
@@ -0,0 +1,25 @@
1
+ # MActionListbox
2
+
3
+ An action list is a contextual menu that presents a list of available actions related to a specific element or interface area. It allows users to quickly access functions such as editing, sharing, deleting, or navigating to sub-actions. Action Lists are commonly triggered by buttons, icons (e.g., three-dot menus), or right-click interactions, ensuring a clean and efficient UI.
4
+
5
+
6
+ ## Props
7
+
8
+ | Name | Description | Type | Default |
9
+ | --- | --- | --- | --- |
10
+ | `title` | title displayed in mobile version. | `string` | - |
11
+ | `items*` | An array of objects that allows you to provide all the data needed to generate the content for each item. | `{ icon?: Component` `undefined; label: string; disabled?: boolean` `undefined; appearance?: "standard"` `"danger"` `undefined; divider?: boolean` `undefined; }[]` | - |
12
+
13
+ ## Dependencies
14
+
15
+ ### Depends on
16
+
17
+ - [MDivider](../divider)
18
+
19
+ ### Graph
20
+
21
+ ```mermaid
22
+ graph TD;
23
+ MActionListbox --> MDivider
24
+ style MActionListbox fill:#008240,stroke:#333,stroke-width:4px
25
+ ```
@@ -1,7 +1,7 @@
1
1
  import type { Meta, StoryObj } from '@storybook/vue3-vite';
2
2
 
3
3
  import MAvatar from './MAvatar.vue';
4
- import Profile24 from '@mozaic-ds/icons-vue/src/components/Profile24/Profile24.vue';
4
+ import { Profile24 } from '@mozaic-ds/icons-vue';
5
5
 
6
6
  const meta: Meta<typeof MAvatar> = {
7
7
  title: 'Content/Avatar',
@@ -9,3 +9,17 @@ A breadcrumb is a navigation help that displays the hierarchical path of the cur
9
9
  | --- | --- | --- | --- |
10
10
  | `appearance` | Allows to define the breadcrumb appearance. | `"standard"` `"inverse"` | - |
11
11
  | `links*` | Links of the breadcrumb. | `{ label: string; href: string; router?: boolean` `undefined; }[]` | - |
12
+
13
+ ## Dependencies
14
+
15
+ ### Depends on
16
+
17
+ - [MLink](../link)
18
+
19
+ ### Graph
20
+
21
+ ```mermaid
22
+ graph TD;
23
+ MBreadcrumb --> MLink
24
+ style MBreadcrumb fill:#008240,stroke:#333,stroke-width:4px
25
+ ```
@@ -0,0 +1,111 @@
1
+ import { mount } from '@vue/test-utils';
2
+ import { describe, it, expect } from 'vitest';
3
+ import MBuiltInMenu, { type MenuItem } from './MBuiltInMenu.vue';
4
+ import { defineComponent } from 'vue';
5
+
6
+ // Dummy icon component to simulate passed icon
7
+ const DummyIcon = defineComponent({
8
+ name: 'DummyIcon',
9
+ template: '<svg class="dummy-icon" />',
10
+ });
11
+
12
+ const items: MenuItem[] = [
13
+ { label: 'Item 1', icon: DummyIcon },
14
+ { label: 'Item 2', href: '/foo', target: '_blank' },
15
+ { label: 'Item 3' },
16
+ ];
17
+
18
+ describe('MBuiltInMenu', () => {
19
+ it('renders all item labels', () => {
20
+ const wrapper = mount(MBuiltInMenu, {
21
+ props: { items, modelValue: undefined },
22
+ });
23
+ const labels = wrapper.findAll('.mc-built-in-menu__label');
24
+ expect(labels.length).toBe(3);
25
+ expect(labels[0].text()).toBe('Item 1');
26
+ expect(labels[1].text()).toBe('Item 2');
27
+ expect(labels[2].text()).toBe('Item 3');
28
+ });
29
+
30
+ it('uses correct tags for link and buttons', () => {
31
+ const wrapper = mount(MBuiltInMenu, {
32
+ props: { items, modelValue: undefined },
33
+ });
34
+ expect(wrapper.findAll('a').length).toBe(1);
35
+ expect(wrapper.findAll('button').length).toBe(2);
36
+
37
+ const links = wrapper.findAll('.mc-built-in-menu__link');
38
+ const buttons = wrapper.findAll('.mc-built-in-menu__button');
39
+ expect(links.length).toBe(1);
40
+ expect(buttons.length).toBe(2);
41
+ });
42
+
43
+ it('renders an anchor with href and provided target', () => {
44
+ const items: MenuItem[] = [
45
+ { label: 'Anchor', href: '/path', target: '_blank' },
46
+ ];
47
+ const wrapper = mount(MBuiltInMenu, {
48
+ props: { items, modelValue: undefined },
49
+ });
50
+
51
+ const a = wrapper.find('a');
52
+ expect(a).not.toBeNull();
53
+ expect(a?.attributes('href')).toBe('/path');
54
+ expect(a?.attributes('target')).toBe('_blank');
55
+ });
56
+
57
+ it('renders a router-link with to and default target when target omitted', () => {
58
+ const items: MenuItem[] = [{ label: 'Router', to: '/route' }];
59
+ const wrapper = mount(MBuiltInMenu, {
60
+ props: { items, modelValue: undefined },
61
+ });
62
+
63
+ const routerLink = wrapper.find('router-link');
64
+ expect(routerLink).not.toBeNull();
65
+ expect(routerLink?.attributes('to')).toBe('/route');
66
+ expect(routerLink?.attributes('target')).toBe('_self');
67
+ });
68
+
69
+ it('emits update:modelValue when an item is clicked', async () => {
70
+ const wrapper = mount(MBuiltInMenu, {
71
+ props: { items, modelValue: undefined },
72
+ });
73
+ const menuItems = wrapper.findAll(
74
+ '.mc-built-in-menu__button, .mc-built-in-menu__link',
75
+ );
76
+
77
+ await menuItems[1].trigger('click');
78
+ const emitted = wrapper.emitted('update:modelValue');
79
+ expect(emitted).toBeTruthy();
80
+ expect(emitted![0][0]).toBe(1);
81
+ });
82
+
83
+ it('marks the selected item with aria-current and selected class', () => {
84
+ const wrapper = mount(MBuiltInMenu, {
85
+ props: { items, modelValue: 2 },
86
+ });
87
+ const lis = wrapper.findAll('li');
88
+ const selectedItem = lis[2];
89
+ expect(selectedItem.attributes('aria-current')).toBe('true');
90
+ expect(selectedItem.classes()).toContain(
91
+ 'mc-built-in-menu__item--selected',
92
+ );
93
+ });
94
+
95
+ it('renders provided icon component inside the item', () => {
96
+ const wrapper = mount(MBuiltInMenu, {
97
+ props: { items, modelValue: undefined },
98
+ });
99
+ const firstItem = wrapper.findAll('li')[0];
100
+ expect(firstItem.find('.dummy-icon').exists()).toBe(true);
101
+ });
102
+
103
+ it('applies outlined class when outlined prop is true', () => {
104
+ const wrapper = mount(MBuiltInMenu, {
105
+ props: { items, modelValue: undefined, outlined: true },
106
+ });
107
+ expect(wrapper.find('nav').classes()).toContain(
108
+ 'mc-built-in-menu--outlined',
109
+ );
110
+ });
111
+ });