@mozaic-ds/vue 2.16.0 → 2.18.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 +2 -1
- package/dist/mozaic-vue.d.ts +258 -137
- package/dist/mozaic-vue.js +14054 -10878
- package/dist/mozaic-vue.js.map +1 -1
- package/dist/mozaic-vue.umd.cjs +7 -25
- package/dist/mozaic-vue.umd.cjs.map +1 -1
- package/package.json +22 -11
- package/src/components/BrandPresets.mdx +2 -2
- package/src/components/Migration.mdx +651 -0
- package/src/components/accordionlist/MAccordionList.figma.ts +43 -0
- package/src/components/accordionlistitem/MAccordionListItem.figma.ts +27 -0
- package/src/components/accordionlistitem/MAccordionListItem.spec.ts +22 -3
- package/src/components/accordionlistitem/MAccordionListItem.vue +38 -28
- package/src/components/actionbottombar/MActionBottomBar.figma.ts +24 -0
- package/src/components/actionlistbox/MActionListbox.figma.ts +30 -0
- package/src/components/avatar/MAvatar.figma.ts +31 -0
- package/src/components/breadcrumb/MBreadcrumb.figma.ts +31 -0
- package/src/components/builtinmenu/MBuiltInMenu.figma.ts +23 -0
- package/src/components/builtinmenu/MBuiltInMenu.spec.ts +30 -1
- package/src/components/builtinmenu/MBuiltInMenu.vue +26 -17
- package/src/components/builtinmenu/README.md +2 -0
- package/src/components/button/MButton.figma.ts +41 -0
- package/src/components/callout/MCallout.figma.ts +29 -0
- package/src/components/callout/MCallout.spec.ts +35 -0
- package/src/components/callout/MCallout.vue +22 -4
- package/src/components/callout/README.md +2 -0
- package/src/components/carousel/MCarousel.figma.ts +32 -0
- package/src/components/checkbox/MCheckbox.figma.ts +45 -0
- package/src/components/checkboxgroup/MCheckboxGroup.figma.ts +30 -0
- package/src/components/checklistmenu/MCheckListMenu.figma.ts +29 -0
- package/src/components/checklistmenu/MCheckListMenu.spec.ts +12 -1
- package/src/components/checklistmenu/MCheckListMenu.vue +6 -0
- package/src/components/checklistmenu/README.md +2 -0
- package/src/components/circularprogressbar/MCircularProgressbar.figma.ts +31 -0
- package/src/components/combobox/MCombobox.figma.ts +48 -0
- package/src/components/combobox/MCombobox.spec.ts +1 -1
- package/src/components/combobox/MCombobox.vue +18 -9
- package/src/components/combobox/README.md +2 -2
- package/src/components/container/MContainer.figma.ts +30 -0
- package/src/components/datatable/DataTable.stories.ts +277 -0
- package/src/components/datatable/DataTableCells.stories.ts +251 -0
- package/src/components/datatable/DataTableEmpty.stories.ts +102 -0
- package/src/components/datatable/DataTableExpandable.stories.ts +95 -0
- package/src/components/datatable/DataTableNested.stories.ts +96 -0
- package/src/components/datatable/DataTableSelectable.stories.ts +124 -0
- package/src/components/datatable/DataTableSortable.stories.ts +164 -0
- package/src/components/datatable/MDataTable.types.ts +54 -0
- package/src/components/datatable/assets/styles.scss +10 -0
- package/src/components/datatable/datatable.mdx +63 -0
- package/src/components/datatable/tools/data.js +8 -0
- package/src/components/datatable/tools/data.json +2018 -0
- package/src/components/datatable/utils.js +19 -0
- package/src/components/datepicker/MDatepicker.figma.ts +20 -0
- package/src/components/divider/MDivider.figma.ts +30 -0
- package/src/components/drawer/MDrawer.figma.ts +37 -0
- package/src/components/drawer/README.md +1 -1
- package/src/components/field/MField.figma.ts +30 -0
- package/src/components/fileuploader/MFileUploader.figma.ts +23 -0
- package/src/components/fileuploaderitem/MFileUploaderItem.figma.ts +27 -0
- package/src/components/flag/MFlag.figma.ts +26 -0
- package/src/components/iconbutton/MIconButton.figma.ts +54 -0
- package/src/components/kpiitem/MKpiItem.figma.ts +33 -0
- package/src/components/linearprogressbarbuffer/MLinearProgressbarBuffer.figma.ts +31 -0
- package/src/components/linearprogressbarpercentage/MLinearProgressbarPercentage.figma.ts +26 -0
- package/src/components/link/MLink.figma.ts +32 -0
- package/src/components/loader/MLoader.figma.ts +30 -0
- package/src/components/loadingoverlay/MLoadingOverlay.figma.ts +18 -0
- package/src/components/modal/MModal.figma.ts +27 -0
- package/src/components/navigationindicator/MNavigationIndicator.figma.ts +24 -0
- package/src/components/navigationindicator/MNavigationIndicator.spec.ts +75 -18
- package/src/components/navigationindicator/MNavigationIndicator.vue +10 -12
- package/src/components/numberbadge/MNumberBadge.figma.ts +31 -0
- package/src/components/optionListbox/MOptionListbox.figma.ts +36 -0
- package/src/components/optionListbox/MOptionListbox.vue +34 -19
- package/src/components/optionListbox/README.md +1 -1
- package/src/components/overlay/MOverlay.figma.ts +20 -0
- package/src/components/pageheader/MPageHeader.figma.ts +21 -0
- package/src/components/pagination/MPagination.figma.ts +34 -0
- package/src/components/passwordinput/MPasswordInput.figma.ts +30 -0
- package/src/components/phonenumber/MPhoneNumber.figma.ts +47 -0
- package/src/components/pincode/MPincode.figma.ts +41 -0
- package/src/components/pincode/MPincode.spec.ts +1 -4
- package/src/components/pincode/MPincode.vue +11 -15
- package/src/components/popover/MPopover.figma.ts +42 -0
- package/src/components/popover/MPopover.spec.ts +126 -0
- package/src/components/popover/MPopover.vue +36 -1
- package/src/components/quantityselector/MQuantitySelector.figma.ts +50 -0
- package/src/components/radio/MRadio.figma.ts +40 -0
- package/src/components/radiogroup/MRadioGroup.figma.ts +30 -0
- package/src/components/segmentedcontrol/MSegmentedControl.figma.ts +33 -0
- package/src/components/segmentedcontrol/MSegmentedControl.spec.ts +92 -0
- package/src/components/segmentedcontrol/MSegmentedControl.vue +61 -2
- package/src/components/select/MSelect.figma.ts +49 -0
- package/src/components/sidebar/MSidebar.figma.ts +28 -0
- package/src/components/sidebarexpandableitem/MSidebarExpandableItem.figma.ts +19 -0
- package/src/components/sidebarfooter/MSidebarFooter.figma.ts +21 -0
- package/src/components/sidebarheader/MSidebarHeader.figma.ts +18 -0
- package/src/components/sidebarnavitem/MSidebarNavItem.figma.ts +23 -0
- package/src/components/sidebarshortcutitem/MSidebarShortcutItem.figma.ts +20 -0
- package/src/components/starrating/MStarRating.figma.ts +35 -0
- package/src/components/starrating/MStarRating.spec.ts +19 -22
- package/src/components/starrating/MStarRating.vue +3 -2
- package/src/components/statusbadge/MStatusBadge.figma.ts +27 -0
- package/src/components/statusdot/MStatusDot.figma.ts +31 -0
- package/src/components/statusmessage/MStatusMessage.figma.ts +28 -0
- package/src/components/statusmessage/MStatusMessage.spec.ts +15 -0
- package/src/components/statusmessage/MStatusMessage.stories.ts +4 -0
- package/src/components/statusmessage/MStatusMessage.vue +7 -0
- package/src/components/statusmessage/README.md +2 -0
- package/src/components/statusnotification/MStatusNotification.figma.ts +29 -0
- package/src/components/stepperbottombar/MStepperBottomBar.figma.ts +20 -0
- package/src/components/steppercompact/MStepperCompact.figma.ts +21 -0
- package/src/components/stepperinline/MStepperInline.figma.ts +23 -0
- package/src/components/stepperstacked/MStepperStacked.figma.ts +23 -0
- package/src/components/tabs/MTabs.figma.ts +33 -0
- package/src/components/tabs/MTabs.vue +90 -4
- package/src/components/tabs/Mtabs.spec.ts +162 -0
- package/src/components/tag/MTag.figma.ts +26 -0
- package/src/components/tag/MTag.stories.ts +13 -3
- package/src/components/tag/MTag.vue +11 -1
- package/src/components/tag/README.md +6 -0
- package/src/components/textarea/MTextArea.figma.ts +28 -0
- package/src/components/textinput/MTextInput.figma.ts +51 -0
- package/src/components/tile/MTile.figma.ts +31 -0
- package/src/components/tileclickable/MTileClickable.figma.ts +31 -0
- package/src/components/tileexpandable/MTileExpandable.figma.ts +31 -0
- package/src/components/tileselectable/MTileSelectable.figma.ts +29 -0
- package/src/components/toaster/MToaster.figma.ts +25 -0
- package/src/components/toggle/MToggle.figma.ts +39 -0
- package/src/components/togglegroup/MToggleGroup.figma.ts +30 -0
- package/src/components/tooltip/MTooltip.figma.ts +29 -0
- package/src/main.ts +1 -0
|
@@ -4,20 +4,6 @@ import { nextTick } from 'vue';
|
|
|
4
4
|
import MStarRating from './MStarRating.vue';
|
|
5
5
|
import { StarFilled24, StarHalf24 } from '@mozaic-ds/icons-vue';
|
|
6
6
|
|
|
7
|
-
function mockRect(el: Element, { left = 0, width = 100 } = {}) {
|
|
8
|
-
Object.defineProperty(el, 'getBoundingClientRect', {
|
|
9
|
-
value: () => ({
|
|
10
|
-
left,
|
|
11
|
-
width,
|
|
12
|
-
top: 0,
|
|
13
|
-
bottom: 0,
|
|
14
|
-
right: left + width,
|
|
15
|
-
height: 0,
|
|
16
|
-
}),
|
|
17
|
-
configurable: true,
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
|
|
21
7
|
describe('MStarRating', () => {
|
|
22
8
|
it('renders 5 stars by default', () => {
|
|
23
9
|
const wrapper = shallowMount(MStarRating, { props: { modelValue: 0 } });
|
|
@@ -39,8 +25,7 @@ describe('MStarRating', () => {
|
|
|
39
25
|
});
|
|
40
26
|
const stars = wrapper.findAll('.mc-star-rating__icon');
|
|
41
27
|
const first = stars[0];
|
|
42
|
-
|
|
43
|
-
await first.trigger('mousemove', { clientX: 10 });
|
|
28
|
+
await first.trigger('pointermove', { pointerType: 'mouse' });
|
|
44
29
|
expect(wrapper.findComponent(StarHalf24).exists()).toBe(false);
|
|
45
30
|
});
|
|
46
31
|
|
|
@@ -60,8 +45,7 @@ describe('MStarRating', () => {
|
|
|
60
45
|
});
|
|
61
46
|
const stars = wrapper.findAll('.mc-star-rating__icon');
|
|
62
47
|
const first = stars[0];
|
|
63
|
-
|
|
64
|
-
await first.trigger('click', { clientX: 10 });
|
|
48
|
+
await first.trigger('click');
|
|
65
49
|
const emitted = wrapper.emitted('update:modelValue') || [];
|
|
66
50
|
expect(emitted.length).toBe(1);
|
|
67
51
|
expect(emitted[0][0]).toBe(1);
|
|
@@ -109,9 +93,8 @@ describe('MStarRating', () => {
|
|
|
109
93
|
|
|
110
94
|
const stars = wrapper.findAll('.mc-star-rating__icon');
|
|
111
95
|
const first = stars[0];
|
|
112
|
-
mockRect(first.element, { left: 0, width: 100 });
|
|
113
96
|
|
|
114
|
-
await first.trigger('
|
|
97
|
+
await first.trigger('pointermove', { pointerType: 'mouse' });
|
|
115
98
|
await nextTick();
|
|
116
99
|
|
|
117
100
|
// aria-label should reflect hovered value (0.5) not modelValue (2)
|
|
@@ -124,6 +107,21 @@ describe('MStarRating', () => {
|
|
|
124
107
|
expect(root.attributes('aria-label')).toContain('2');
|
|
125
108
|
});
|
|
126
109
|
|
|
110
|
+
it('ignores non-mouse pointermove events for hover state', async () => {
|
|
111
|
+
const wrapper = shallowMount(MStarRating, {
|
|
112
|
+
props: { modelValue: 3, size: 'm', readonly: false },
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
const stars = wrapper.findAll('.mc-star-rating__icon');
|
|
116
|
+
const first = stars[0];
|
|
117
|
+
const root = wrapper.find('[role="slider"]');
|
|
118
|
+
|
|
119
|
+
await first.trigger('pointermove', { pointerType: 'touch' });
|
|
120
|
+
await nextTick();
|
|
121
|
+
|
|
122
|
+
expect(root.attributes('aria-label')).toContain('3');
|
|
123
|
+
});
|
|
124
|
+
|
|
127
125
|
it('resets hover to null on blur (aria-label falls back to modelValue)', async () => {
|
|
128
126
|
const wrapper = shallowMount(MStarRating, {
|
|
129
127
|
props: { modelValue: 3, size: 'm', readonly: false },
|
|
@@ -131,12 +129,11 @@ describe('MStarRating', () => {
|
|
|
131
129
|
|
|
132
130
|
const stars = wrapper.findAll('.mc-star-rating__icon');
|
|
133
131
|
const secondStar = stars[1];
|
|
134
|
-
mockRect(secondStar.element, { left: 0, width: 100 });
|
|
135
132
|
|
|
136
133
|
const root = wrapper.find('[role="slider"]');
|
|
137
134
|
|
|
138
135
|
await root.trigger('focus');
|
|
139
|
-
await secondStar.trigger('
|
|
136
|
+
await secondStar.trigger('pointermove', { pointerType: 'mouse' });
|
|
140
137
|
await nextTick();
|
|
141
138
|
expect(root.attributes('aria-label')).toContain('2');
|
|
142
139
|
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
v-on="
|
|
41
41
|
!isReadonly
|
|
42
42
|
? {
|
|
43
|
-
|
|
43
|
+
pointermove: (event: PointerEvent) => onHover(event, index),
|
|
44
44
|
click: () => onClick(index),
|
|
45
45
|
}
|
|
46
46
|
: {}
|
|
@@ -152,7 +152,8 @@ function getStarComponent(index: number) {
|
|
|
152
152
|
}
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
-
function onHover(index: number) {
|
|
155
|
+
function onHover(event: PointerEvent, index: number) {
|
|
156
|
+
if (event.pointerType !== 'mouse') return;
|
|
156
157
|
hover.value = index + 1;
|
|
157
158
|
}
|
|
158
159
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code Connect mapping for MStatusBadge
|
|
3
|
+
* Links Figma Status badge (ADS2) to @mozaic-ds/vue
|
|
4
|
+
*/
|
|
5
|
+
import figma, { html } from '@figma/code-connect/html';
|
|
6
|
+
|
|
7
|
+
figma.connect(
|
|
8
|
+
'https://www.figma.com/design/Zyh9RyabNaqkjbuFWP9Aqj/%E2%9C%A8-Components--ADS2---Stable-version-?node-id=6-21619',
|
|
9
|
+
{
|
|
10
|
+
props: {
|
|
11
|
+
label: figma.string('Label'),
|
|
12
|
+
status: figma.enum('Status', {
|
|
13
|
+
Information: 'info',
|
|
14
|
+
Success: 'success',
|
|
15
|
+
Warning: 'warning',
|
|
16
|
+
Error: 'error',
|
|
17
|
+
Neutral: 'neutral',
|
|
18
|
+
}),
|
|
19
|
+
},
|
|
20
|
+
example: ({ label, status }) =>
|
|
21
|
+
html`<script setup>
|
|
22
|
+
import { MStatusBadge } from '@mozaic-ds/vue';
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<MStatusBadge label=${label} status=${status}></MStatusBadge>`,
|
|
26
|
+
},
|
|
27
|
+
);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code Connect mapping for MStatusDot
|
|
3
|
+
* Links Figma Status dot (ADS2) to @mozaic-ds/vue
|
|
4
|
+
*/
|
|
5
|
+
import figma, { html } from '@figma/code-connect/html';
|
|
6
|
+
|
|
7
|
+
figma.connect(
|
|
8
|
+
'https://www.figma.com/design/Zyh9RyabNaqkjbuFWP9Aqj/%E2%9C%A8-Components--ADS2---Stable-version-?node-id=6-21635',
|
|
9
|
+
{
|
|
10
|
+
props: {
|
|
11
|
+
status: figma.enum('Status', {
|
|
12
|
+
Information: 'info',
|
|
13
|
+
Success: 'success',
|
|
14
|
+
Warning: 'warning',
|
|
15
|
+
Error: 'error',
|
|
16
|
+
Neutral: 'neutral',
|
|
17
|
+
}),
|
|
18
|
+
size: figma.enum('Size', {
|
|
19
|
+
'S (4px)': 's',
|
|
20
|
+
'M (8px)': 'm',
|
|
21
|
+
'L (16px)': 'l',
|
|
22
|
+
}),
|
|
23
|
+
},
|
|
24
|
+
example: ({ status, size }) =>
|
|
25
|
+
html`<script setup>
|
|
26
|
+
import { MStatusDot } from '@mozaic-ds/vue';
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
<MStatusDot status=${status} size=${size}></MStatusDot>`,
|
|
30
|
+
},
|
|
31
|
+
);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code Connect mapping for MStatusMessage
|
|
3
|
+
* Links Figma Status message to @mozaic-ds/vue
|
|
4
|
+
*/
|
|
5
|
+
import figma, { html } from '@figma/code-connect/html';
|
|
6
|
+
|
|
7
|
+
figma.connect(
|
|
8
|
+
'https://www.figma.com/design/Zyh9RyabNaqkjbuFWP9Aqj/%E2%9C%A8-Components--ADS2---Stable-version-?node-id=20807-13948',
|
|
9
|
+
{
|
|
10
|
+
props: {
|
|
11
|
+
label: figma.string('Status message'),
|
|
12
|
+
status: figma.enum('Status', {
|
|
13
|
+
Information: 'info',
|
|
14
|
+
Success: 'success',
|
|
15
|
+
Warning: 'warning',
|
|
16
|
+
Error: 'error',
|
|
17
|
+
Neutral: 'neutral',
|
|
18
|
+
'In progress': 'inprogress',
|
|
19
|
+
}),
|
|
20
|
+
},
|
|
21
|
+
example: ({ label, status }) =>
|
|
22
|
+
html`<script setup>
|
|
23
|
+
import { MStatusMessage } from '@mozaic-ds/vue';
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<MStatusMessage label=${label} status=${status}></MStatusMessage>`,
|
|
27
|
+
},
|
|
28
|
+
);
|
|
@@ -20,6 +20,21 @@ describe('MStatusMessage.vue', () => {
|
|
|
20
20
|
);
|
|
21
21
|
});
|
|
22
22
|
|
|
23
|
+
it('adds the accent modifier class when appearance is accent', () => {
|
|
24
|
+
const wrapper = mount(MStatusMessage, {
|
|
25
|
+
props: { label: 'Accent', appearance: 'accent' },
|
|
26
|
+
});
|
|
27
|
+
expect(wrapper.classes()).toContain('mc-status-message--accent');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('does NOT add the accent modifier class when appearance is standard', () => {
|
|
31
|
+
const wrapper = mount(MStatusMessage, {
|
|
32
|
+
props: { label: 'Standard', appearance: 'standard' },
|
|
33
|
+
});
|
|
34
|
+
expect(wrapper.classes()).not.toContain('mc-status-message--accent');
|
|
35
|
+
expect(wrapper.classes()).not.toContain('mc-status-message--standard');
|
|
36
|
+
});
|
|
37
|
+
|
|
23
38
|
it('uses the info icon by default', () => {
|
|
24
39
|
const wrapper = mount(MStatusMessage, {
|
|
25
40
|
props: { label: 'Info message' },
|
|
@@ -35,6 +35,11 @@ const props = withDefaults(
|
|
|
35
35
|
| 'error'
|
|
36
36
|
| 'neutral'
|
|
37
37
|
| 'inprogress';
|
|
38
|
+
/**
|
|
39
|
+
* Allows to define the status message appearance.
|
|
40
|
+
* The accent status is used to highlight a specific message.
|
|
41
|
+
*/
|
|
42
|
+
appearance?: 'standard' | 'accent';
|
|
38
43
|
/**
|
|
39
44
|
* Label of the status message.
|
|
40
45
|
*/
|
|
@@ -42,6 +47,7 @@ const props = withDefaults(
|
|
|
42
47
|
}>(),
|
|
43
48
|
{
|
|
44
49
|
status: 'info',
|
|
50
|
+
appearance: 'standard',
|
|
45
51
|
},
|
|
46
52
|
);
|
|
47
53
|
|
|
@@ -49,6 +55,7 @@ const classObject = computed(() => {
|
|
|
49
55
|
return {
|
|
50
56
|
[`mc-status-message--${props.status}`]:
|
|
51
57
|
props.status && props.status != 'info',
|
|
58
|
+
[`mc-status-message--${props.appearance}`]: props.appearance != 'standard',
|
|
52
59
|
};
|
|
53
60
|
});
|
|
54
61
|
|
|
@@ -8,6 +8,8 @@ A Status Message is a compact component that combines an icon and concise text t
|
|
|
8
8
|
| Name | Description | Type | Default |
|
|
9
9
|
| --- | --- | --- | --- |
|
|
10
10
|
| `status` | Allows to define the status message style. | `"info"` `"warning"` `"error"` `"success"` `"neutral"` `"inprogress"` | `"info"` |
|
|
11
|
+
| `appearance` | Allows to define the status message appearance.
|
|
12
|
+
The accent status is used to highlight a specific message. | `"standard"` `"accent"` | `"standard"` |
|
|
11
13
|
| `label*` | Label of the status message. | `string` | - |
|
|
12
14
|
|
|
13
15
|
## Dependencies
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code Connect mapping for MStatusNotification
|
|
3
|
+
* Links Figma Status notification (ADS2) to @mozaic-ds/vue
|
|
4
|
+
*/
|
|
5
|
+
import figma, { html } from '@figma/code-connect/html';
|
|
6
|
+
|
|
7
|
+
figma.connect(
|
|
8
|
+
'https://www.figma.com/design/Zyh9RyabNaqkjbuFWP9Aqj/%E2%9C%A8-Components--ADS2---Stable-version-?node-id=6-21600',
|
|
9
|
+
{
|
|
10
|
+
props: {
|
|
11
|
+
status: figma.enum('Status', {
|
|
12
|
+
Information: 'info',
|
|
13
|
+
Success: 'success',
|
|
14
|
+
Warning: 'warning',
|
|
15
|
+
Error: 'error',
|
|
16
|
+
}),
|
|
17
|
+
},
|
|
18
|
+
example: ({ status }) =>
|
|
19
|
+
html`<script setup>
|
|
20
|
+
import { MStatusNotification } from '@mozaic-ds/vue';
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<MStatusNotification
|
|
24
|
+
title="Notification title"
|
|
25
|
+
description="Notification description"
|
|
26
|
+
status=${status}
|
|
27
|
+
></MStatusNotification>`,
|
|
28
|
+
},
|
|
29
|
+
);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code Connect mapping for MStepperBottomBar
|
|
3
|
+
* Links Figma Stepper bottom bar (ADS2) to @mozaic-ds/vue
|
|
4
|
+
*/
|
|
5
|
+
import figma, { html } from '@figma/code-connect/html';
|
|
6
|
+
|
|
7
|
+
figma.connect(
|
|
8
|
+
'https://www.figma.com/design/Zyh9RyabNaqkjbuFWP9Aqj/%E2%9C%A8-Components--ADS2---Stable-version-?node-id=10726-18528',
|
|
9
|
+
{
|
|
10
|
+
props: {
|
|
11
|
+
cancel: figma.boolean('Has cancel action'),
|
|
12
|
+
},
|
|
13
|
+
example: ({ cancel }) =>
|
|
14
|
+
html`<script setup>
|
|
15
|
+
import { MStepperBottomBar } from '@mozaic-ds/vue';
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<MStepperBottomBar cancel=${cancel} :steps="3" />`,
|
|
19
|
+
},
|
|
20
|
+
);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code Connect mapping for MStepperCompact
|
|
3
|
+
* Links Figma Stepper (Compact) (ADS2) to @mozaic-ds/vue
|
|
4
|
+
*/
|
|
5
|
+
import figma, { html } from '@figma/code-connect/html';
|
|
6
|
+
|
|
7
|
+
figma.connect(
|
|
8
|
+
'https://www.figma.com/design/Zyh9RyabNaqkjbuFWP9Aqj/%E2%9C%A8-Components--ADS2---Stable-version-?node-id=13297-24864',
|
|
9
|
+
{
|
|
10
|
+
props: {
|
|
11
|
+
label: figma.string('Step label'),
|
|
12
|
+
description: figma.string('Next step label'),
|
|
13
|
+
},
|
|
14
|
+
example: ({ label, description }) =>
|
|
15
|
+
html`<script setup>
|
|
16
|
+
import { MStepperCompact } from '@mozaic-ds/vue';
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<MStepperCompact label=${label} :description=${description} :value="1" :max-steps="4"></MStepperCompact>`,
|
|
20
|
+
},
|
|
21
|
+
);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code Connect mapping for MStepperInline
|
|
3
|
+
* Links Figma Stepper (Inline) to @mozaic-ds/vue
|
|
4
|
+
*/
|
|
5
|
+
import figma, { html } from '@figma/code-connect/html';
|
|
6
|
+
|
|
7
|
+
figma.connect(
|
|
8
|
+
'https://www.figma.com/design/Zyh9RyabNaqkjbuFWP9Aqj/%E2%9C%A8-Components--ADS2---Stable-version-?node-id=13050-10371',
|
|
9
|
+
{
|
|
10
|
+
props: {
|
|
11
|
+
showStep03: figma.boolean('Show Step 03'),
|
|
12
|
+
showStep04: figma.boolean('Show Step 04'),
|
|
13
|
+
showStep05: figma.boolean('Show Step 05'),
|
|
14
|
+
showStep06: figma.boolean('Show Step 06'),
|
|
15
|
+
},
|
|
16
|
+
example: () =>
|
|
17
|
+
html`<script setup>
|
|
18
|
+
import { MStepperInline } from '@mozaic-ds/vue';
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<MStepperInline :current-step="1" :steps="[{ label: 'Step label', additionalInfo: 'Additional information' }, { label: 'Step label', additionalInfo: 'Additional information' }, { label: 'Step label', additionalInfo: 'Additional information' }]"></MStepperInline>`,
|
|
22
|
+
},
|
|
23
|
+
);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code Connect mapping for MStepperStacked
|
|
3
|
+
* Links Figma Stepper (Stacked) (ADS2) to @mozaic-ds/vue
|
|
4
|
+
*/
|
|
5
|
+
import figma, { html } from '@figma/code-connect/html';
|
|
6
|
+
|
|
7
|
+
figma.connect(
|
|
8
|
+
'https://www.figma.com/design/Zyh9RyabNaqkjbuFWP9Aqj/%E2%9C%A8-Components--ADS2---Stable-version-?node-id=13179-6447',
|
|
9
|
+
{
|
|
10
|
+
props: {
|
|
11
|
+
showStep03: figma.boolean('Show Step 03'),
|
|
12
|
+
showStep04: figma.boolean('Show Step 04'),
|
|
13
|
+
showStep05: figma.boolean('Show Step 05'),
|
|
14
|
+
showStep06: figma.boolean('Show Step 06'),
|
|
15
|
+
},
|
|
16
|
+
example: () =>
|
|
17
|
+
html`<script setup>
|
|
18
|
+
import { MStepperStacked } from '@mozaic-ds/vue';
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<MStepperStacked :current-step="1" :steps="[{ label: 'Step label', additionalInfo: 'Additional information' }, { label: 'Step label', additionalInfo: 'Additional information' }, { label: 'Step label', additionalInfo: 'Additional information' }]"></MStepperStacked>`,
|
|
22
|
+
},
|
|
23
|
+
);
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code Connect mapping for MTabs
|
|
3
|
+
* Links Figma Tabs (ADS2) to @mozaic-ds/vue
|
|
4
|
+
*/
|
|
5
|
+
import figma, { html } from '@figma/code-connect/html';
|
|
6
|
+
|
|
7
|
+
figma.connect(
|
|
8
|
+
'https://www.figma.com/design/Zyh9RyabNaqkjbuFWP9Aqj/%E2%9C%A8-Components--ADS2---Stable-version-?node-id=6-11474',
|
|
9
|
+
{
|
|
10
|
+
props: {
|
|
11
|
+
divider: figma.boolean('Show divider'),
|
|
12
|
+
centered: figma.enum('Centered', {
|
|
13
|
+
True: true,
|
|
14
|
+
False: false,
|
|
15
|
+
}),
|
|
16
|
+
},
|
|
17
|
+
example: ({ divider, centered }) =>
|
|
18
|
+
html`<script setup>
|
|
19
|
+
import { MTabs } from '@mozaic-ds/vue';
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<MTabs
|
|
23
|
+
:divider=${divider}
|
|
24
|
+
centered=${centered}
|
|
25
|
+
model-value="label1"
|
|
26
|
+
:tabs="[
|
|
27
|
+
{ id: 'label1', label: 'Label' },
|
|
28
|
+
{ id: 'label2', label: 'Label' },
|
|
29
|
+
{ id: 'label3', label: 'Label' },
|
|
30
|
+
]"
|
|
31
|
+
></MTabs>`,
|
|
32
|
+
},
|
|
33
|
+
);
|
|
@@ -16,11 +16,15 @@
|
|
|
16
16
|
'mc-tabs__tab--disabled': tab.disabled,
|
|
17
17
|
}"
|
|
18
18
|
:aria-selected="isTabSelected(index, tab.id)"
|
|
19
|
+
:aria-disabled="tab.disabled || undefined"
|
|
20
|
+
:disabled="tab.disabled"
|
|
21
|
+
:tabindex="index === focusableTabIndex ? 0 : -1"
|
|
19
22
|
type="button"
|
|
20
23
|
@click="onClickTab(index, tab.id)"
|
|
24
|
+
@keydown="onKeydown($event, index)"
|
|
21
25
|
>
|
|
22
26
|
<span v-if="tab.icon" class="mc-tabs__icon">
|
|
23
|
-
<component :is="tab.icon" />
|
|
27
|
+
<component :is="tab.icon" aria-hidden="true" />
|
|
24
28
|
</span>
|
|
25
29
|
<div class="mc-tabs__label">
|
|
26
30
|
<span>{{ tab.label }}</span>
|
|
@@ -36,7 +40,7 @@
|
|
|
36
40
|
</template>
|
|
37
41
|
|
|
38
42
|
<script setup lang="ts">
|
|
39
|
-
import { computed,
|
|
43
|
+
import { computed, nextTick, useTemplateRef, type Component } from 'vue';
|
|
40
44
|
import MDivider from '../divider/MDivider.vue';
|
|
41
45
|
import MNumberBadge from '../numberbadge/MNumberBadge.vue';
|
|
42
46
|
/**
|
|
@@ -101,7 +105,48 @@ const classObject = computed(() => {
|
|
|
101
105
|
};
|
|
102
106
|
});
|
|
103
107
|
|
|
104
|
-
const modelValue =
|
|
108
|
+
const modelValue = computed({
|
|
109
|
+
get() {
|
|
110
|
+
return props.modelValue;
|
|
111
|
+
},
|
|
112
|
+
set(value: string | number | undefined) {
|
|
113
|
+
emit('update:modelValue', value);
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
const enabledTabs = computed(() => {
|
|
118
|
+
return props.tabs.map((_, i) => i).filter((i) => !props.tabs[i].disabled);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
const selectedTabIndex = computed(() => {
|
|
122
|
+
if (typeof modelValue.value === 'string') {
|
|
123
|
+
return props.tabs.findIndex((tab) => tab.id === modelValue.value);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (
|
|
127
|
+
typeof modelValue.value === 'number' &&
|
|
128
|
+
modelValue.value >= 0 &&
|
|
129
|
+
modelValue.value < props.tabs.length
|
|
130
|
+
) {
|
|
131
|
+
return modelValue.value;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return -1;
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
const focusableTabIndex = computed(() => {
|
|
138
|
+
if (enabledTabs.value.length === 0) {
|
|
139
|
+
return -1;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (enabledTabs.value.includes(selectedTabIndex.value)) {
|
|
143
|
+
return selectedTabIndex.value;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return enabledTabs.value[0];
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
const tabRefs = useTemplateRef<HTMLButtonElement[]>('tab');
|
|
105
150
|
|
|
106
151
|
const onClickTab = (index: number, id?: string) => {
|
|
107
152
|
const tab =
|
|
@@ -114,7 +159,6 @@ const onClickTab = (index: number, id?: string) => {
|
|
|
114
159
|
if (tab?.disabled) return;
|
|
115
160
|
if (value !== modelValue.value) {
|
|
116
161
|
modelValue.value = value;
|
|
117
|
-
emit('update:modelValue', value);
|
|
118
162
|
}
|
|
119
163
|
};
|
|
120
164
|
|
|
@@ -124,6 +168,48 @@ const isTabSelected = (index: number, id?: string) => {
|
|
|
124
168
|
return modelValue.value === value;
|
|
125
169
|
};
|
|
126
170
|
|
|
171
|
+
function onKeydown(event: KeyboardEvent, index: number) {
|
|
172
|
+
if (
|
|
173
|
+
event.key !== 'ArrowRight' &&
|
|
174
|
+
event.key !== 'ArrowLeft' &&
|
|
175
|
+
event.key !== 'Home' &&
|
|
176
|
+
event.key !== 'End'
|
|
177
|
+
) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (enabledTabs.value.length === 0) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const pos = enabledTabs.value.indexOf(index);
|
|
186
|
+
|
|
187
|
+
let nextPos: number | null = null;
|
|
188
|
+
if (event.key === 'ArrowRight') {
|
|
189
|
+
event.preventDefault();
|
|
190
|
+
if (pos < 0) return;
|
|
191
|
+
nextPos = (pos + 1) % enabledTabs.value.length;
|
|
192
|
+
} else if (event.key === 'ArrowLeft') {
|
|
193
|
+
event.preventDefault();
|
|
194
|
+
if (pos < 0) return;
|
|
195
|
+
nextPos = (pos - 1 + enabledTabs.value.length) % enabledTabs.value.length;
|
|
196
|
+
} else if (event.key === 'Home') {
|
|
197
|
+
event.preventDefault();
|
|
198
|
+
nextPos = 0;
|
|
199
|
+
} else if (event.key === 'End') {
|
|
200
|
+
event.preventDefault();
|
|
201
|
+
nextPos = enabledTabs.value.length - 1;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (nextPos !== null) {
|
|
205
|
+
const nextIndex = enabledTabs.value[nextPos];
|
|
206
|
+
onClickTab(nextIndex, props.tabs[nextIndex].id);
|
|
207
|
+
nextTick(() => {
|
|
208
|
+
tabRefs.value?.[nextIndex]?.focus();
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
127
213
|
const emit = defineEmits<{
|
|
128
214
|
/**
|
|
129
215
|
* Emits when the selected tab changes, updating the modelValue prop.
|