@mozaic-ds/vue 2.13.1 → 2.15.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 (104) hide show
  1. package/dist/mozaic-vue.css +1 -1
  2. package/dist/mozaic-vue.d.ts +1482 -369
  3. package/dist/mozaic-vue.js +3639 -2308
  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/DarkMode.mdx +115 -0
  9. package/src/components/actionlistbox/MActionListbox.spec.ts +49 -59
  10. package/src/components/actionlistbox/MActionListbox.stories.ts +22 -1
  11. package/src/components/actionlistbox/MActionListbox.vue +82 -28
  12. package/src/components/actionlistbox/README.md +15 -0
  13. package/src/components/avatar/MAvatar.stories.ts +1 -1
  14. package/src/components/breadcrumb/MBreadcrumb.vue +5 -0
  15. package/src/components/button/README.md +4 -0
  16. package/src/components/checkbox/README.md +2 -0
  17. package/src/components/divider/README.md +4 -0
  18. package/src/components/iconbutton/MIconButton.stories.ts +12 -0
  19. package/src/components/iconbutton/MIconButton.vue +13 -1
  20. package/src/components/iconbutton/README.md +27 -0
  21. package/src/components/loader/README.md +2 -0
  22. package/src/components/navigationindicator/MNavigationIndicator.spec.ts +152 -0
  23. package/src/components/navigationindicator/MNavigationIndicator.stories.ts +41 -0
  24. package/src/components/navigationindicator/MNavigationIndicator.vue +132 -0
  25. package/src/components/navigationindicator/README.md +37 -0
  26. package/src/components/pageheader/MPageHeader.spec.ts +142 -0
  27. package/src/components/pageheader/MPageHeader.stories.ts +133 -0
  28. package/src/components/pageheader/MPageHeader.vue +130 -0
  29. package/src/components/pageheader/README.md +46 -0
  30. package/src/components/popover/MPopover.spec.ts +106 -0
  31. package/src/components/popover/MPopover.stories.ts +126 -0
  32. package/src/components/popover/MPopover.vue +131 -0
  33. package/src/components/popover/README.md +42 -0
  34. package/src/components/radio/README.md +2 -0
  35. package/src/components/segmentedcontrol/MSegmentedControl.spec.ts +57 -25
  36. package/src/components/segmentedcontrol/MSegmentedControl.stories.ts +6 -19
  37. package/src/components/segmentedcontrol/MSegmentedControl.vue +27 -13
  38. package/src/components/segmentedcontrol/README.md +6 -3
  39. package/src/components/select/MSelect.spec.ts +2 -1
  40. package/src/components/select/MSelect.vue +31 -25
  41. package/src/components/sidebar/MSidebar.const.ts +6 -0
  42. package/src/components/sidebar/MSidebar.spec.ts +110 -0
  43. package/src/components/sidebar/MSidebar.stories.ts +108 -0
  44. package/src/components/sidebar/MSidebar.vue +124 -0
  45. package/src/components/sidebar/README.md +59 -0
  46. package/src/components/sidebar/stories/DefaultCase.stories.vue +120 -0
  47. package/src/components/sidebar/stories/README.md +35 -0
  48. package/src/components/sidebar/stories/WithExpandOnly.stories.vue +112 -0
  49. package/src/components/sidebar/stories/WithProfileInfoOnly.stories.vue +119 -0
  50. package/src/components/sidebar/stories/WithSingleLevel.stories.vue +98 -0
  51. package/src/components/sidebar/use-floating-item.composable.ts +135 -0
  52. package/src/components/sidebar/use-floating-item.spec.ts +251 -0
  53. package/src/components/sidebarexpandableitem/MSidebarExpandableItem.spec.ts +151 -0
  54. package/src/components/sidebarexpandableitem/MSidebarExpandableItem.vue +113 -0
  55. package/src/components/sidebarexpandableitem/README.md +36 -0
  56. package/src/components/sidebarfooter/MSidebarFooter.spec.ts +276 -0
  57. package/src/components/sidebarfooter/MSidebarFooter.vue +201 -0
  58. package/src/components/sidebarfooter/README.md +52 -0
  59. package/src/components/sidebarfooter/_MSidebarFooterMenu.vue +64 -0
  60. package/src/components/sidebarheader/MSidebarHeader.vue +36 -0
  61. package/src/components/sidebarheader/README.md +31 -0
  62. package/src/components/sidebarnavitem/MSidebarNavItem.spec.ts +127 -0
  63. package/src/components/sidebarnavitem/MSidebarNavItem.vue +113 -0
  64. package/src/components/sidebarnavitem/README.md +56 -0
  65. package/src/components/sidebarshortcutitem/MSidebarShortcutItem.spec.ts +59 -0
  66. package/src/components/sidebarshortcutitem/MSidebarShortcutItem.vue +52 -0
  67. package/src/components/sidebarshortcutitem/README.md +32 -0
  68. package/src/components/sidebarshortcuts/MSidebarShortcuts.spec.ts +87 -0
  69. package/src/components/sidebarshortcuts/MSidebarShortcuts.vue +101 -0
  70. package/src/components/sidebarshortcuts/README.md +36 -0
  71. package/src/components/statusbadge/README.md +12 -0
  72. package/src/components/stepperinline/MStepperInline.spec.ts +63 -28
  73. package/src/components/stepperinline/MStepperInline.stories.ts +18 -10
  74. package/src/components/stepperinline/MStepperInline.vue +24 -10
  75. package/src/components/stepperinline/README.md +6 -2
  76. package/src/components/tabs/MTabs.stories.ts +18 -0
  77. package/src/components/tabs/MTabs.vue +30 -14
  78. package/src/components/tabs/Mtabs.spec.ts +56 -10
  79. package/src/components/tabs/README.md +6 -3
  80. package/src/components/textinput/MTextInput.stories.ts +13 -1
  81. package/src/components/textinput/MTextInput.vue +12 -0
  82. package/src/components/textinput/README.md +3 -1
  83. package/src/components/tile/MTile.spec.ts +61 -0
  84. package/src/components/tile/MTile.stories.ts +102 -0
  85. package/src/components/tile/MTile.vue +68 -0
  86. package/src/components/tile/README.md +19 -0
  87. package/src/components/tileclickable/MTileClickable.spec.ts +130 -0
  88. package/src/components/tileclickable/MTileClickable.stories.ts +60 -0
  89. package/src/components/tileclickable/MTileClickable.vue +106 -0
  90. package/src/components/tileclickable/README.md +30 -0
  91. package/src/components/tileexpandable/MTileExpandable.spec.ts +121 -0
  92. package/src/components/tileexpandable/MTileExpandable.stories.ts +50 -0
  93. package/src/components/tileexpandable/MTileExpandable.vue +131 -0
  94. package/src/components/tileexpandable/README.md +36 -0
  95. package/src/components/tileselectable/MTileSelectable.spec.ts +177 -0
  96. package/src/components/tileselectable/MTileSelectable.stories.ts +55 -0
  97. package/src/components/tileselectable/MTileSelectable.vue +142 -0
  98. package/src/components/tileselectable/README.md +44 -0
  99. package/src/components/toaster/README.md +1 -1
  100. package/src/components/tooltip/MTooltip.vue +5 -0
  101. package/src/components/tooltip/README.md +16 -1
  102. package/src/main.ts +15 -0
  103. package/src/utils/use-is-mobile.composable.ts +20 -0
  104. package/src/utils/use-is-mobile.spec.ts +70 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mozaic-ds/vue",
3
- "version": "2.13.1",
3
+ "version": "2.15.0",
4
4
  "type": "module",
5
5
  "description": "Mozaic-Vue is the Vue.js implementation of ADEO Design system",
6
6
  "author": "ADEO - ADEO Design system",
@@ -41,7 +41,7 @@
41
41
  "*.d.ts"
42
42
  ],
43
43
  "dependencies": {
44
- "@mozaic-ds/styles": "^2.7.0",
44
+ "@mozaic-ds/styles": "^2.11.0",
45
45
  "@mozaic-ds/web-fonts": "^1.65.0",
46
46
  "postcss-scss": "^4.0.9",
47
47
  "vue": "^3.5.13"
@@ -50,25 +50,26 @@
50
50
  "@commitlint/cli": "^20.1.0",
51
51
  "@commitlint/config-conventional": "^20.0.0",
52
52
  "@mozaic-ds/css-dev-tools": "1.75.0",
53
- "@mozaic-ds/icons-vue": "^2.2.0",
53
+ "@mozaic-ds/icons-vue": "^2.5.0",
54
54
  "@release-it/conventional-changelog": "^10.0.1",
55
55
  "@storybook/addon-a11y": "^10.0.4",
56
56
  "@storybook/addon-docs": "^10.0.4",
57
57
  "@storybook/addon-themes": "^10.0.4",
58
58
  "@storybook/vue3-vite": "^10.0.4",
59
- "@types/jsdom": "^27.0.0",
59
+ "@types/jsdom": "^28.0.0",
60
60
  "@vitejs/plugin-vue": "^6.0.1",
61
61
  "@vitest/coverage-v8": "^4.0.7",
62
62
  "@vitest/eslint-plugin": "^1.1.38",
63
63
  "@vue/eslint-config-prettier": "^10.2.0",
64
64
  "@vue/eslint-config-typescript": "^14.5.0",
65
65
  "@vue/test-utils": "^2.4.6",
66
- "eslint": "^9.22.0",
66
+ "eslint": "^10.0.2",
67
67
  "eslint-plugin-storybook": "^10.0.5",
68
68
  "eslint-plugin-vue": "^10.0.0",
69
69
  "eslint-plugin-vuejs-accessibility": "^2.4.1",
70
+ "globals": "^17.3.0",
70
71
  "husky": "^9.1.7",
71
- "jsdom": "^27.0.0",
72
+ "jsdom": "^28.0.0",
72
73
  "libphonenumber-js": "^1.12.23",
73
74
  "lint-staged": "^16.1.5",
74
75
  "mdx-mermaid": "^2.0.3",
@@ -0,0 +1,115 @@
1
+ import { Meta, Source } from '@storybook/addon-docs/blocks';
2
+
3
+ <Meta title="Dark Mode" />
4
+
5
+ # Dark Mode
6
+
7
+ A concise guide explaining **how dark mode works** with your CSS variables and **how to use it** in Storybook.
8
+
9
+ ---
10
+
11
+ ## What dark mode is (high‑level)
12
+
13
+ Dark mode is implemented with **two sets of CSS variables** (tokens):
14
+
15
+ - **Light** values live under `:root`.
16
+ - **Dark** values override under `:root[data-theme="dark"]`.
17
+
18
+ Components only reference tokens with `var(--token-name)` — switching theme is just toggling the `data-theme` attribute (no component code changes).
19
+
20
+ ---
21
+
22
+ ## Token structure (SCSS → CSS)
23
+
24
+ Your presets export SCSS like this:
25
+
26
+ <Source
27
+ language="scss"
28
+ dark
29
+ code={`
30
+ $root-selector: ':root' !default;
31
+ $dark-selector: '[data-theme="dark"]' !default;
32
+
33
+ #{$root-selector} {
34
+ /_ Light tokens _/
35
+ --color-background-primary: #ffffff;
36
+ --color-text-primary: #000000;
37
+ /_ … all your light variables … _/
38
+ }
39
+
40
+ #{$root-selector}#{$dark-selector} {
41
+ /_ Dark tokens _/
42
+ --color-background-primary: #191919;
43
+ --color-text-primary: #d9d9d9;
44
+ /_ … all your dark variables … _/
45
+ }
46
+ `}
47
+ />
48
+
49
+ After compilation, this becomes standard CSS:
50
+
51
+ <Source
52
+ language="css"
53
+ dark
54
+ code={`
55
+ :root {
56
+ /* light tokens */
57
+ }
58
+ :root[data-theme='dark'] {
59
+ /* dark tokens */
60
+ }
61
+ `}
62
+ />
63
+
64
+ > If you can’t (or don’t want to) target `:root`, you can pass a different `$root-selector` when building your theme and apply `data-theme="dark"` on that container instead.
65
+
66
+ ---
67
+
68
+ ## Using tokens inside components
69
+
70
+ To enable the dark mode you have to ensure to:
71
+
72
+ - Add the `data-theme` attribute in your root element with the value `dark`,
73
+ - Use variables — never hard‑code colors or sizes
74
+
75
+ ```html
76
+ <div class="root" data-theme="dark">…</div>
77
+ ```
78
+
79
+ <Source
80
+ language="sass"
81
+ dark
82
+ code={`
83
+ @use "@mozaic-ds/tokens" as *;
84
+
85
+ .mc-component: {
86
+ background-color: $--color-background-primary;
87
+ }
88
+
89
+ `}
90
+ />
91
+
92
+ When the theme changes, these values update automatically via CSS.
93
+
94
+ ---
95
+
96
+ ## Accessibility & good practices
97
+
98
+ - Aim for **WCAG AA** contrast at minimum; verify text vs. background pairs.
99
+ - Prefer **semantic tokens** (`--button-color-…`, `--color-text-…`) over raw color hexes.
100
+ - Keep all component styles expressed in tokens so the **theme switch has zero component logic**.
101
+
102
+ ---
103
+
104
+ ## Troubleshooting
105
+
106
+ - **Dark toggle does nothing** → Ensure the tokens were imported **before** component styles and that `data-theme="dark"` is set on the same selector the tokens target (usually `:root`).
107
+ - **Weird colors** → Search for hard‑coded values and replace them with tokens.
108
+ - **Variables undefined** → Check your build order and that the SCSS was compiled to CSS and loaded by Storybook.
109
+
110
+ ---
111
+
112
+ ## Summary
113
+
114
+ - Light tokens on `:root`, dark overrides on `:root[data-theme="dark"]`.
115
+ - Components read tokens with `var(--$token-name)` — no runtime branching required.
@@ -40,12 +40,9 @@ const items = [
40
40
  ];
41
41
 
42
42
  describe('MActionListbox', () => {
43
- it('renders the title if provided', () => {
44
- const wrapper = mount(MActionListbox, {
45
- props: {
46
- title: 'Action List',
47
- items,
48
- },
43
+ function mountComponent(props = {}, options = {}) {
44
+ return mount(MActionListbox, {
45
+ props: { items, ...props },
49
46
  global: {
50
47
  components: {
51
48
  MDivider,
@@ -53,82 +50,75 @@ describe('MActionListbox', () => {
53
50
  Cross24,
54
51
  },
55
52
  },
53
+ ...options,
56
54
  });
55
+ }
57
56
 
57
+ it('renders the title if provided', () => {
58
+ const wrapper = mountComponent({ title: 'Action List' });
58
59
  expect(wrapper.find('.mc-listbox__title').text()).toBe('Action List');
59
60
  });
60
61
 
61
62
  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
-
63
+ const wrapper = mountComponent();
75
64
  items.forEach((item) => {
76
65
  expect(wrapper.text()).toContain(item.label);
77
66
  });
78
67
  });
79
68
 
80
69
  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
-
70
+ const wrapper = mountComponent();
94
71
  const icons = wrapper.findAll('[data-testid="icon"]');
95
72
  expect(icons.length).toBe(items.length);
96
73
  });
97
74
 
98
75
  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
-
76
+ const wrapper = mountComponent();
112
77
  const dangerousItem = wrapper.findAll('.mc-action-list__element--danger');
78
+
113
79
  expect(dangerousItem.length).toBe(1);
114
80
  expect(dangerousItem[0].text()).toContain('Delete');
115
81
  });
116
82
 
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
-
83
+ it('renders MDivider when divider is true', () => {
84
+ const wrapper = mountComponent();
131
85
  const dividers = wrapper.findAll('.mc-action-list__divider');
132
86
  expect(dividers.length).toBe(1);
133
87
  });
88
+
89
+ it('applies disabled class when item.disabled is true', () => {
90
+ const disabledItems = [...items, { label: 'Disabled', disabled: true }];
91
+
92
+ const wrapper = mountComponent({ items: disabledItems });
93
+
94
+ const disabled = wrapper.findAll('.mc-action-list__element--disabled');
95
+ expect(disabled.length).toBe(1);
96
+ expect(disabled[0].text()).toContain('Disabled');
97
+ });
98
+
99
+ it('applies mc-listbox--bottom by default', () => {
100
+ const wrapper = mountComponent();
101
+ expect(wrapper.find('.mc-listbox').classes()).toContain(
102
+ 'mc-listbox--bottom',
103
+ );
104
+ });
105
+
106
+ it('applies mc-listbox--top when position is "top"', () => {
107
+ const wrapper = mountComponent({ position: 'top' });
108
+ expect(wrapper.find('.mc-listbox').classes()).toContain('mc-listbox--top');
109
+ });
110
+
111
+ it('applies mc-listbox--left when position is "left"', () => {
112
+ const wrapper = mountComponent({ position: 'left' });
113
+ expect(wrapper.find('.mc-listbox').classes()).toContain('mc-listbox--left');
114
+ });
115
+
116
+ it('emits "close" when close button is clicked', async () => {
117
+ const wrapper = mountComponent({ title: 'Action List' });
118
+
119
+ await wrapper.find('.mc-listbox__close').trigger('click');
120
+
121
+ expect(wrapper.emitted('close')).toBeTruthy();
122
+ expect(wrapper.emitted('close')?.length).toBe(1);
123
+ });
134
124
  });
@@ -1,6 +1,7 @@
1
1
  import type { Meta, StoryObj } from '@storybook/vue3-vite';
2
2
 
3
3
  import MActionListbox from './MActionListbox.vue';
4
+ import MButton from '../button/MButton.vue';
4
5
  import {
5
6
  Copy20,
6
7
  ArrowTopRight20,
@@ -12,7 +13,9 @@ const meta: Meta<typeof MActionListbox> = {
12
13
  title: 'Overlay/Action Listbox',
13
14
  component: MActionListbox,
14
15
  parameters: {
16
+ layout: 'centered',
15
17
  docs: {
18
+ story: { height: '700px' },
16
19
  description: {
17
20
  component:
18
21
  '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.',
@@ -64,7 +67,7 @@ const meta: Meta<typeof MActionListbox> = {
64
67
  return { args };
65
68
  },
66
69
  template: `
67
- <MActionListbox v-bind="args"></MActionListbox>
70
+ <MActionListbox v-bind="args" />
68
71
  `,
69
72
  }),
70
73
  };
@@ -72,3 +75,21 @@ export default meta;
72
75
  type Story = StoryObj<typeof MActionListbox>;
73
76
 
74
77
  export const Default: Story = {};
78
+
79
+ export const Activator: Story = {
80
+ render: (args) => ({
81
+ components: { MActionListbox, MButton },
82
+ setup() {
83
+ return { args };
84
+ },
85
+ template: `
86
+ <div>
87
+ <MActionListbox v-bind="args">
88
+ <template #activator="{id}">
89
+ <MButton :popovertarget="id">Activator</MButton>
90
+ </template>
91
+ </MActionListbox>
92
+ </div>
93
+ `,
94
+ }),
95
+ };
@@ -1,9 +1,23 @@
1
1
  <template>
2
- <div class="mc-listbox">
3
- <div class="mc-listbox__content">
2
+ <div
3
+ :class="{
4
+ 'mc-listbox': true,
5
+ [`mc-listbox--${props.position}`]: true,
6
+ }"
7
+ >
8
+ <div
9
+ ref="popover"
10
+ class="mc-listbox__content"
11
+ v-bind="$slots.activator ? { id, popover: '' } : {}"
12
+ >
4
13
  <div class="mc-listbox__header">
5
14
  <h3 v-if="title" class="mc-listbox__title">{{ title }}</h3>
6
- <MIconButton class="mc-listbox__close" ghost aria-label="Close">
15
+ <MIconButton
16
+ class="mc-listbox__close"
17
+ ghost
18
+ aria-label="Close"
19
+ @click="close"
20
+ >
7
21
  <template #icon>
8
22
  <Cross24 aria-hidden="true" />
9
23
  </template>
@@ -42,45 +56,85 @@
42
56
  </div>
43
57
  </div>
44
58
  </div>
59
+
60
+ <slot name="activator" v-bind="{ id }" />
45
61
  </template>
46
62
 
47
63
  <script setup lang="ts">
48
- import type { Component } from 'vue';
64
+ import { useId, useTemplateRef, type Component, type VNode } from 'vue';
65
+ import MIconButton from '../iconbutton/MIconButton.vue';
49
66
  import MDivider from '../divider/MDivider.vue';
67
+ import { Cross24 } from '@mozaic-ds/icons-vue';
68
+
50
69
  /**
51
70
  * 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
71
  */
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<{
72
+ const props = withDefaults(
73
+ defineProps<{
62
74
  /**
63
- * The icon displayed for the item from Mozaic-icon-vue.
75
+ * title displayed in mobile version.
64
76
  */
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;
77
+
78
+ title?: string;
74
79
  /**
75
- * Allows to define the item appearance.
80
+ * Defines the position of the listbox relative to its trigger or container.
76
81
  */
77
- appearance?: 'standard' | 'danger';
82
+ position?: 'top' | 'bottom' | 'left' | 'right';
78
83
  /**
79
- * Add a divider on top of the item.
84
+ * An array of objects that allows you to provide all the data needed to generate the content for each item.
80
85
  */
81
- divider?: boolean;
82
- }>;
86
+
87
+ items: Array<{
88
+ /**
89
+ * The icon displayed for the item from Mozaic-icon-vue.
90
+ */
91
+ icon?: Component;
92
+ /**
93
+ * The label displayed for the item.
94
+ */
95
+ label: string;
96
+ /**
97
+ * If `true`, the item will be disabled.
98
+ */
99
+ disabled?: boolean;
100
+ /**
101
+ * Allows to define the item appearance.
102
+ */
103
+ appearance?: 'standard' | 'danger';
104
+ /**
105
+ * Add a divider on top of the item.
106
+ */
107
+ divider?: boolean;
108
+ }>;
109
+ }>(),
110
+ { position: 'bottom' },
111
+ );
112
+
113
+ const emit = defineEmits<{
114
+ /**
115
+ * Emits when the close button is clicked.
116
+ */
117
+ (on: 'close'): void;
83
118
  }>();
119
+
120
+ const slots = defineSlots<{
121
+ /**
122
+ * Activator element that triggers the listbox.
123
+ */
124
+ activator?: VNode[];
125
+ }>();
126
+
127
+ const id = useId();
128
+
129
+ const popover = useTemplateRef('popover');
130
+
131
+ function close() {
132
+ emit('close');
133
+
134
+ if (slots.activator) {
135
+ popover.value?.hidePopover();
136
+ }
137
+ }
84
138
  </script>
85
139
 
86
140
  <style lang="scss" scoped>
@@ -8,18 +8,33 @@ An action list is a contextual menu that presents a list of available actions re
8
8
  | Name | Description | Type | Default |
9
9
  | --- | --- | --- | --- |
10
10
  | `title` | title displayed in mobile version. | `string` | - |
11
+ | `position` | Defines the position of the listbox relative to its trigger or container. | `"bottom"` `"top"` `"left"` `"right"` | `"bottom"` |
11
12
  | `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
 
14
+ ## Slots
15
+
16
+ | Name | Description |
17
+ | --- | --- |
18
+ | `activator` | Activator element that triggers the listbox. |
19
+
20
+ ## Events
21
+
22
+ | Name | Description | Type |
23
+ | --- | --- | --- |
24
+ | `close` | Emits when the close button is clicked. | [] |
25
+
13
26
  ## Dependencies
14
27
 
15
28
  ### Depends on
16
29
 
17
30
  - [MDivider](../divider)
31
+ - [MIconButton](../iconbutton)
18
32
 
19
33
  ### Graph
20
34
 
21
35
  ```mermaid
22
36
  graph TD;
37
+ MActionListbox --> MIconButton
23
38
  MActionListbox --> MDivider
24
39
  style MActionListbox fill:#008240,stroke:#333,stroke-width:4px
25
40
  ```
@@ -17,7 +17,7 @@ const meta: Meta<typeof MAvatar> = {
17
17
  },
18
18
  args: {
19
19
  default: `
20
- <img src="/images/Avatar.png" alt="Dieter Rams" loading="lazy"/>
20
+ <img src="/mozaic-vue/images/Avatar.png" alt="Dieter Rams" loading="lazy"/>
21
21
  `,
22
22
  },
23
23
  render: (args) => ({
@@ -14,9 +14,13 @@
14
14
  :class="{
15
15
  'mc-breadcrumb__current': isLastLink(index),
16
16
  }"
17
+ iconPosition="right"
17
18
  :aria-current="isLastLink(index) ? 'page' : undefined"
18
19
  >
19
20
  {{ link.label }}
21
+ <template v-if="index !== links.length - 1" #icon>
22
+ <ChevronRight20 />
23
+ </template>
20
24
  </MLink>
21
25
  </li>
22
26
  </ul>
@@ -26,6 +30,7 @@
26
30
  <script setup lang="ts">
27
31
  import { computed } from 'vue';
28
32
  import MLink from '../link/MLink.vue';
33
+ import { ChevronRight20 } from '@mozaic-ds/icons-vue';
29
34
  /**
30
35
  * A breadcrumb is a navigation help that displays the hierarchical path of the current page within a website or application. It helps users understand their location and allows them to navigate back to previous levels easily. Breadcrumbs improve usability and accessibility, especially in multi-level websites, dashboards, and e-commerce platforms.
31
36
  */
@@ -40,17 +40,21 @@ style MButton fill:#008240,stroke:#333,stroke-width:4px
40
40
  ### Used By
41
41
 
42
42
  - [MFileUploaderItem](../fileuploaderitem)
43
+ - [MNavigationIndicator](../navigationindicator)
43
44
  - [MPagination](../pagination)
44
45
  - [MPasswordInput](../passwordinput)
45
46
  - [MStepperBottomBar](../stepperbottombar)
47
+ - [MTileExpandable](../tileexpandable)
46
48
 
47
49
  ### Graph
48
50
 
49
51
  ```mermaid
50
52
  graph TD;
51
53
  MFileUploaderItem --> MButton
54
+ MNavigationIndicator --> MButton
52
55
  MPagination --> MButton
53
56
  MPasswordInput --> MButton
54
57
  MStepperBottomBar --> MButton
58
+ MTileExpandable --> MButton
55
59
  style MButton fill:#008240,stroke:#333,stroke-width:4px
56
60
  ```
@@ -27,11 +27,13 @@ A checkbox is an interactive component used to select or deselect an option, typ
27
27
  ### Used By
28
28
 
29
29
  - [MCheckboxGroup](../checkboxgroup)
30
+ - [MTileSelectable](../tileselectable)
30
31
 
31
32
  ### Graph
32
33
 
33
34
  ```mermaid
34
35
  graph TD;
35
36
  MCheckboxGroup --> MCheckbox
37
+ MTileSelectable --> MCheckbox
36
38
  style MCheckbox fill:#008240,stroke:#333,stroke-width:4px
37
39
  ```
@@ -24,6 +24,8 @@ A divider is a visual element used to separate content or sections within an int
24
24
  - [MActionBottomBar](../actionbottombar)
25
25
  - [MActionListbox](../actionlistbox)
26
26
  - [MFileUploaderItem](../fileuploaderitem)
27
+ - [MSidebarFooter](../sidebarfooter)
28
+ - [_MSidebarFooterMenu](../sidebarfooter)
27
29
  - [MStepperBottomBar](../stepperbottombar)
28
30
  - [MTabs](../tabs)
29
31
 
@@ -34,6 +36,8 @@ graph TD;
34
36
  MActionBottomBar --> MDivider
35
37
  MActionListbox --> MDivider
36
38
  MFileUploaderItem --> MDivider
39
+ MSidebarFooter --> MDivider
40
+ _MSidebarFooterMenu --> MDivider
37
41
  MStepperBottomBar --> MDivider
38
42
  MTabs --> MDivider
39
43
  style MDivider fill:#008240,stroke:#333,stroke-width:4px
@@ -87,6 +87,18 @@ export const Ghost: Story = {
87
87
  },
88
88
  };
89
89
 
90
+ export const Loading: Story = {
91
+ args: { isLoading: true },
92
+ parameters: {
93
+ docs: {
94
+ description: {
95
+ story:
96
+ 'A loader replaces the icon to indicate that an action is in progress. Mouse events are prohibited.',
97
+ },
98
+ },
99
+ },
100
+ };
101
+
90
102
  export const Standard: Story = {
91
103
  args: { appearance: 'standard' },
92
104
  parameters: {
@@ -5,7 +5,14 @@
5
5
  :disabled="disabled"
6
6
  :type="type"
7
7
  >
8
- <span class="mc-button__icon">
8
+ <span
9
+ v-if="isLoading"
10
+ class="mc-button__icon"
11
+ :style="{ position: 'absolute' }"
12
+ >
13
+ <MLoader :style="{ color: 'currentColor' }" size="s" />
14
+ </span>
15
+ <span v-else class="mc-button__icon">
9
16
  <slot name="icon" />
10
17
  </span>
11
18
  </button>
@@ -13,6 +20,7 @@
13
20
 
14
21
  <script setup lang="ts">
15
22
  import { computed, type VNode } from 'vue';
23
+ import MLoader from '../loader/MLoader.vue';
16
24
  /**
17
25
  * Buttons are key interactive elements used to perform actions and can be used as standalone element, or as part of another component. Their appearance depends on the type of action required from the user and the context in which they are used.
18
26
  */
@@ -42,6 +50,10 @@ const props = withDefaults(
42
50
  * Specifies the button's HTML `type` attribute.
43
51
  */
44
52
  type?: 'button' | 'reset' | 'submit';
53
+ /**
54
+ * If `true`, a loading state is displayed.
55
+ */
56
+ isLoading?: boolean;
45
57
  }>(),
46
58
  {
47
59
  appearance: 'standard',