@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.
- package/dist/mozaic-vue.css +1 -1
- package/dist/mozaic-vue.d.ts +1482 -369
- package/dist/mozaic-vue.js +3639 -2308
- package/dist/mozaic-vue.js.map +1 -1
- package/dist/mozaic-vue.umd.cjs +5 -5
- package/dist/mozaic-vue.umd.cjs.map +1 -1
- package/package.json +7 -6
- package/src/components/DarkMode.mdx +115 -0
- package/src/components/actionlistbox/MActionListbox.spec.ts +49 -59
- package/src/components/actionlistbox/MActionListbox.stories.ts +22 -1
- package/src/components/actionlistbox/MActionListbox.vue +82 -28
- package/src/components/actionlistbox/README.md +15 -0
- package/src/components/avatar/MAvatar.stories.ts +1 -1
- package/src/components/breadcrumb/MBreadcrumb.vue +5 -0
- package/src/components/button/README.md +4 -0
- package/src/components/checkbox/README.md +2 -0
- package/src/components/divider/README.md +4 -0
- package/src/components/iconbutton/MIconButton.stories.ts +12 -0
- package/src/components/iconbutton/MIconButton.vue +13 -1
- package/src/components/iconbutton/README.md +27 -0
- package/src/components/loader/README.md +2 -0
- package/src/components/navigationindicator/MNavigationIndicator.spec.ts +152 -0
- package/src/components/navigationindicator/MNavigationIndicator.stories.ts +41 -0
- package/src/components/navigationindicator/MNavigationIndicator.vue +132 -0
- package/src/components/navigationindicator/README.md +37 -0
- package/src/components/pageheader/MPageHeader.spec.ts +142 -0
- package/src/components/pageheader/MPageHeader.stories.ts +133 -0
- package/src/components/pageheader/MPageHeader.vue +130 -0
- package/src/components/pageheader/README.md +46 -0
- package/src/components/popover/MPopover.spec.ts +106 -0
- package/src/components/popover/MPopover.stories.ts +126 -0
- package/src/components/popover/MPopover.vue +131 -0
- package/src/components/popover/README.md +42 -0
- package/src/components/radio/README.md +2 -0
- package/src/components/segmentedcontrol/MSegmentedControl.spec.ts +57 -25
- package/src/components/segmentedcontrol/MSegmentedControl.stories.ts +6 -19
- package/src/components/segmentedcontrol/MSegmentedControl.vue +27 -13
- package/src/components/segmentedcontrol/README.md +6 -3
- package/src/components/select/MSelect.spec.ts +2 -1
- package/src/components/select/MSelect.vue +31 -25
- package/src/components/sidebar/MSidebar.const.ts +6 -0
- package/src/components/sidebar/MSidebar.spec.ts +110 -0
- package/src/components/sidebar/MSidebar.stories.ts +108 -0
- package/src/components/sidebar/MSidebar.vue +124 -0
- package/src/components/sidebar/README.md +59 -0
- package/src/components/sidebar/stories/DefaultCase.stories.vue +120 -0
- package/src/components/sidebar/stories/README.md +35 -0
- package/src/components/sidebar/stories/WithExpandOnly.stories.vue +112 -0
- package/src/components/sidebar/stories/WithProfileInfoOnly.stories.vue +119 -0
- package/src/components/sidebar/stories/WithSingleLevel.stories.vue +98 -0
- package/src/components/sidebar/use-floating-item.composable.ts +135 -0
- package/src/components/sidebar/use-floating-item.spec.ts +251 -0
- package/src/components/sidebarexpandableitem/MSidebarExpandableItem.spec.ts +151 -0
- package/src/components/sidebarexpandableitem/MSidebarExpandableItem.vue +113 -0
- package/src/components/sidebarexpandableitem/README.md +36 -0
- package/src/components/sidebarfooter/MSidebarFooter.spec.ts +276 -0
- package/src/components/sidebarfooter/MSidebarFooter.vue +201 -0
- package/src/components/sidebarfooter/README.md +52 -0
- package/src/components/sidebarfooter/_MSidebarFooterMenu.vue +64 -0
- package/src/components/sidebarheader/MSidebarHeader.vue +36 -0
- package/src/components/sidebarheader/README.md +31 -0
- package/src/components/sidebarnavitem/MSidebarNavItem.spec.ts +127 -0
- package/src/components/sidebarnavitem/MSidebarNavItem.vue +113 -0
- package/src/components/sidebarnavitem/README.md +56 -0
- package/src/components/sidebarshortcutitem/MSidebarShortcutItem.spec.ts +59 -0
- package/src/components/sidebarshortcutitem/MSidebarShortcutItem.vue +52 -0
- package/src/components/sidebarshortcutitem/README.md +32 -0
- package/src/components/sidebarshortcuts/MSidebarShortcuts.spec.ts +87 -0
- package/src/components/sidebarshortcuts/MSidebarShortcuts.vue +101 -0
- package/src/components/sidebarshortcuts/README.md +36 -0
- package/src/components/statusbadge/README.md +12 -0
- package/src/components/stepperinline/MStepperInline.spec.ts +63 -28
- package/src/components/stepperinline/MStepperInline.stories.ts +18 -10
- package/src/components/stepperinline/MStepperInline.vue +24 -10
- package/src/components/stepperinline/README.md +6 -2
- package/src/components/tabs/MTabs.stories.ts +18 -0
- package/src/components/tabs/MTabs.vue +30 -14
- package/src/components/tabs/Mtabs.spec.ts +56 -10
- package/src/components/tabs/README.md +6 -3
- package/src/components/textinput/MTextInput.stories.ts +13 -1
- package/src/components/textinput/MTextInput.vue +12 -0
- package/src/components/textinput/README.md +3 -1
- package/src/components/tile/MTile.spec.ts +61 -0
- package/src/components/tile/MTile.stories.ts +102 -0
- package/src/components/tile/MTile.vue +68 -0
- package/src/components/tile/README.md +19 -0
- package/src/components/tileclickable/MTileClickable.spec.ts +130 -0
- package/src/components/tileclickable/MTileClickable.stories.ts +60 -0
- package/src/components/tileclickable/MTileClickable.vue +106 -0
- package/src/components/tileclickable/README.md +30 -0
- package/src/components/tileexpandable/MTileExpandable.spec.ts +121 -0
- package/src/components/tileexpandable/MTileExpandable.stories.ts +50 -0
- package/src/components/tileexpandable/MTileExpandable.vue +131 -0
- package/src/components/tileexpandable/README.md +36 -0
- package/src/components/tileselectable/MTileSelectable.spec.ts +177 -0
- package/src/components/tileselectable/MTileSelectable.stories.ts +55 -0
- package/src/components/tileselectable/MTileSelectable.vue +142 -0
- package/src/components/tileselectable/README.md +44 -0
- package/src/components/toaster/README.md +1 -1
- package/src/components/tooltip/MTooltip.vue +5 -0
- package/src/components/tooltip/README.md +16 -1
- package/src/main.ts +15 -0
- package/src/utils/use-is-mobile.composable.ts +20 -0
- 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.
|
|
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.
|
|
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.
|
|
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": "^
|
|
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": "^
|
|
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": "^
|
|
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
|
-
|
|
44
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
118
|
-
const wrapper =
|
|
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
|
-
|
|
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
|
|
3
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
*
|
|
75
|
+
* title displayed in mobile version.
|
|
64
76
|
*/
|
|
65
|
-
|
|
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
|
-
*
|
|
80
|
+
* Defines the position of the listbox relative to its trigger or container.
|
|
76
81
|
*/
|
|
77
|
-
|
|
82
|
+
position?: 'top' | 'bottom' | 'left' | 'right';
|
|
78
83
|
/**
|
|
79
|
-
*
|
|
84
|
+
* An array of objects that allows you to provide all the data needed to generate the content for each item.
|
|
80
85
|
*/
|
|
81
|
-
|
|
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
|
```
|
|
@@ -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
|
|
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',
|