@mozaic-ds/vue 2.10.0 → 2.12.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 +417 -212
- package/dist/mozaic-vue.js +1737 -1231
- 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 +2 -2
- package/src/components/builtinmenu/MBuiltInMenu.spec.ts +111 -0
- package/src/components/builtinmenu/MBuiltInMenu.stories.ts +58 -0
- package/src/components/builtinmenu/MBuiltInMenu.vue +110 -0
- package/src/components/builtinmenu/README.md +18 -0
- package/src/components/checklistmenu/MCheckListMenu.spec.ts +77 -0
- package/src/components/checklistmenu/MCheckListMenu.stories.ts +46 -0
- package/src/components/checklistmenu/MCheckListMenu.vue +61 -0
- package/src/components/checklistmenu/README.md +18 -0
- package/src/components/kpiitem/MKpiItem.spec.ts +71 -0
- package/src/components/kpiitem/MKpiItem.stories.ts +69 -0
- package/src/components/kpiitem/MKpiItem.vue +89 -0
- package/src/components/kpiitem/README.md +15 -0
- package/src/components/phonenumber/README.md +2 -0
- package/src/components/starrating/MStarRating.spec.ts +203 -0
- package/src/components/starrating/MStarRating.stories.ts +82 -0
- package/src/components/starrating/MStarRating.vue +187 -0
- package/src/components/starrating/README.md +31 -0
- package/src/components/statusbadge/README.md +1 -1
- package/src/components/statusdot/README.md +1 -1
- package/src/components/statusmessage/MStatusMessage.spec.ts +76 -0
- package/src/components/statusmessage/MStatusMessage.stories.ts +52 -0
- package/src/components/statusmessage/MStatusMessage.vue +70 -0
- package/src/components/statusmessage/README.md +11 -0
- package/src/components/statusnotification/README.md +1 -1
- package/src/components/steppercompact/MStepperCompact.spec.ts +98 -0
- package/src/components/steppercompact/MStepperCompact.stories.ts +43 -0
- package/src/components/steppercompact/MStepperCompact.vue +105 -0
- package/src/components/steppercompact/README.md +13 -0
- package/src/components/stepperinline/MStepperInline.spec.ts +78 -0
- package/src/components/stepperinline/MStepperInline.stories.ts +49 -0
- package/src/components/stepperinline/MStepperInline.vue +94 -0
- package/src/components/stepperinline/README.md +11 -0
- package/src/components/tag/MTag.vue +2 -1
- package/src/components/tag/README.md +1 -1
- package/src/components/toaster/README.md +1 -1
- package/src/main.ts +6 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { mount } from '@vue/test-utils';
|
|
2
|
+
import { describe, it, expect } from 'vitest';
|
|
3
|
+
import MStatusMessage from './MStatusMessage.vue';
|
|
4
|
+
|
|
5
|
+
import InfoCircleFilled24 from '@mozaic-ds/icons-vue/src/components/InfoCircleFilled24/InfoCircleFilled24.vue';
|
|
6
|
+
import WarningCircleFilled24 from '@mozaic-ds/icons-vue/src/components/WarningCircleFilled24/WarningCircleFilled24.vue';
|
|
7
|
+
import CrossCircleFilled24 from '@mozaic-ds/icons-vue/src/components/CrossCircleFilled24/CrossCircleFilled24.vue';
|
|
8
|
+
import CheckCircleFilled24 from '@mozaic-ds/icons-vue/src/components/CheckCircleFilled24/CheckCircleFilled24.vue';
|
|
9
|
+
|
|
10
|
+
describe('MStatusMessage.vue', () => {
|
|
11
|
+
it('renders the label', () => {
|
|
12
|
+
const wrapper = mount(MStatusMessage, {
|
|
13
|
+
props: { label: 'Hello world' },
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
expect(wrapper.find('.mc-status-message__description').text()).toBe(
|
|
17
|
+
'Hello world',
|
|
18
|
+
);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('uses the info icon by default', () => {
|
|
22
|
+
const wrapper = mount(MStatusMessage, {
|
|
23
|
+
props: { label: 'Info message' },
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
expect(wrapper.findComponent(InfoCircleFilled24).exists()).toBe(true);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('renders the success icon when status is success', () => {
|
|
30
|
+
const wrapper = mount(MStatusMessage, {
|
|
31
|
+
props: { status: 'success', label: 'Success' },
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
expect(wrapper.findComponent(CheckCircleFilled24).exists()).toBe(true);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('renders the warning icon when status is warning', () => {
|
|
38
|
+
const wrapper = mount(MStatusMessage, {
|
|
39
|
+
props: { status: 'warning', label: 'Warning' },
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
expect(wrapper.findComponent(WarningCircleFilled24).exists()).toBe(true);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('renders the error icon when status is error', () => {
|
|
46
|
+
const wrapper = mount(MStatusMessage, {
|
|
47
|
+
props: { status: 'error', label: 'Error' },
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
expect(wrapper.findComponent(CrossCircleFilled24).exists()).toBe(true);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('adds correct modifier class for non-info statuses', () => {
|
|
54
|
+
const wrapper = mount(MStatusMessage, {
|
|
55
|
+
props: { status: 'warning', label: 'Warn' },
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
expect(wrapper.classes()).toContain('mc-status-message--warning');
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('does NOT add modifier class for info', () => {
|
|
62
|
+
const wrapper = mount(MStatusMessage, { props: { label: 'Info' } });
|
|
63
|
+
|
|
64
|
+
expect(wrapper.classes()).not.toContain('mc-status-message--info');
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('shows loader instead of icon when status is inprogress', () => {
|
|
68
|
+
const wrapper = mount(MStatusMessage, {
|
|
69
|
+
props: { status: 'inprogress', label: 'Loading' },
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
expect(wrapper.findComponent({ name: 'MLoader' }).exists()).toBe(true);
|
|
73
|
+
|
|
74
|
+
expect(wrapper.find('.mc-status-message__icon').exists()).toBe(false);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3-vite';
|
|
2
|
+
import MStatusMessage from './MStatusMessage.vue';
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof MStatusMessage> = {
|
|
5
|
+
title: 'Status/Status Message',
|
|
6
|
+
component: MStatusMessage,
|
|
7
|
+
tags: ['v2'],
|
|
8
|
+
parameters: {
|
|
9
|
+
docs: {
|
|
10
|
+
description: {
|
|
11
|
+
component:
|
|
12
|
+
'A Status Message is a compact component that combines an icon and concise text to communicate system states or user feedback in limited interface space. The icon and message work together as a unified structure to provide clear, immediate understanding of the current status. Status Messages are designed for contexts where space is constrained but clear communication is essential, offering quick recognition through color-coded icons paired with brief, actionable text.',
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
args: {
|
|
17
|
+
label: 'Brief status message',
|
|
18
|
+
},
|
|
19
|
+
render: (args) => ({
|
|
20
|
+
components: { MStatusMessage },
|
|
21
|
+
setup() {
|
|
22
|
+
return { args };
|
|
23
|
+
},
|
|
24
|
+
template: `
|
|
25
|
+
<MStatusMessage v-bind="args"></MStatusMessage>
|
|
26
|
+
`,
|
|
27
|
+
}),
|
|
28
|
+
};
|
|
29
|
+
export default meta;
|
|
30
|
+
type Story = StoryObj<typeof MStatusMessage>;
|
|
31
|
+
|
|
32
|
+
export const Info: Story = {};
|
|
33
|
+
|
|
34
|
+
export const Success: Story = {
|
|
35
|
+
args: { status: 'success' },
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const Warning: Story = {
|
|
39
|
+
args: { status: 'warning' },
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const Error: Story = {
|
|
43
|
+
args: { status: 'error' },
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const Neutral: Story = {
|
|
47
|
+
args: { status: 'neutral' },
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export const InProgress: Story = {
|
|
51
|
+
args: { status: 'inprogress' },
|
|
52
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="mc-status-message" :class="classObject">
|
|
3
|
+
<component
|
|
4
|
+
v-if="status != 'inprogress'"
|
|
5
|
+
:is="iconComponent"
|
|
6
|
+
class="mc-status-message__icon"
|
|
7
|
+
aria-hidden="true"
|
|
8
|
+
/>
|
|
9
|
+
<MLoader v-else size="s" />
|
|
10
|
+
<p class="mc-status-message__description">{{ label }}</p>
|
|
11
|
+
</div>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script setup lang="ts">
|
|
15
|
+
import { computed } from 'vue';
|
|
16
|
+
import InfoCircleFilled24 from '@mozaic-ds/icons-vue/src/components/InfoCircleFilled24/InfoCircleFilled24.vue';
|
|
17
|
+
import WarningCircleFilled24 from '@mozaic-ds/icons-vue/src/components/WarningCircleFilled24/WarningCircleFilled24.vue';
|
|
18
|
+
import CrossCircleFilled24 from '@mozaic-ds/icons-vue/src/components/CrossCircleFilled24/CrossCircleFilled24.vue';
|
|
19
|
+
import CheckCircleFilled24 from '@mozaic-ds/icons-vue/src/components/CheckCircleFilled24/CheckCircleFilled24.vue';
|
|
20
|
+
import MLoader from '../loader/MLoader.vue';
|
|
21
|
+
/**
|
|
22
|
+
* A Status Message is a compact component that combines an icon and concise text to communicate system states or user feedback in limited interface space. The icon and message work together as a unified structure to provide clear, immediate understanding of the current status. Status Messages are designed for contexts where space is constrained but clear communication is essential, offering quick recognition through color-coded icons paired with brief, actionable text.
|
|
23
|
+
*/
|
|
24
|
+
const props = withDefaults(
|
|
25
|
+
defineProps<{
|
|
26
|
+
/**
|
|
27
|
+
* Allows to define the status message style.
|
|
28
|
+
*/
|
|
29
|
+
status?:
|
|
30
|
+
| 'info'
|
|
31
|
+
| 'success'
|
|
32
|
+
| 'warning'
|
|
33
|
+
| 'error'
|
|
34
|
+
| 'neutral'
|
|
35
|
+
| 'inprogress';
|
|
36
|
+
/**
|
|
37
|
+
* Label of the status message.
|
|
38
|
+
*/
|
|
39
|
+
label: string;
|
|
40
|
+
}>(),
|
|
41
|
+
{
|
|
42
|
+
status: 'info',
|
|
43
|
+
},
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const classObject = computed(() => {
|
|
47
|
+
return {
|
|
48
|
+
[`mc-status-message--${props.status}`]:
|
|
49
|
+
props.status && props.status != 'info',
|
|
50
|
+
};
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const iconComponent = computed(() => {
|
|
54
|
+
switch (props.status) {
|
|
55
|
+
case 'success':
|
|
56
|
+
return CheckCircleFilled24;
|
|
57
|
+
case 'warning':
|
|
58
|
+
return WarningCircleFilled24;
|
|
59
|
+
case 'error':
|
|
60
|
+
return CrossCircleFilled24;
|
|
61
|
+
case 'info':
|
|
62
|
+
default:
|
|
63
|
+
return InfoCircleFilled24;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
</script>
|
|
67
|
+
|
|
68
|
+
<style lang="scss" scoped>
|
|
69
|
+
@use '@mozaic-ds/styles/components/status-message';
|
|
70
|
+
</style>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# MStatusMessage
|
|
2
|
+
|
|
3
|
+
A Status Message is a compact component that combines an icon and concise text to communicate system states or user feedback in limited interface space. The icon and message work together as a unified structure to provide clear, immediate understanding of the current status. Status Messages are designed for contexts where space is constrained but clear communication is essential, offering quick recognition through color-coded icons paired with brief, actionable text.
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
## Props
|
|
7
|
+
|
|
8
|
+
| Name | Description | Type | Default |
|
|
9
|
+
| --- | --- | --- | --- |
|
|
10
|
+
| `status` | Allows to define the status message style. | `"info"` `"warning"` `"error"` `"success"` `"neutral"` `"inprogress"` | `"info"` |
|
|
11
|
+
| `label*` | Label of the status message. | `string` | - |
|
|
@@ -9,7 +9,7 @@ A Status Notification is used to draw the user’s attention to important inform
|
|
|
9
9
|
| --- | --- | --- | --- |
|
|
10
10
|
| `title*` | Title of the status notification. | `string` | - |
|
|
11
11
|
| `description*` | Description of the status notification. | `string` | - |
|
|
12
|
-
| `status` | Allows to define the status notification type. | `"info"` `"
|
|
12
|
+
| `status` | Allows to define the status notification type. | `"info"` `"warning"` `"error"` `"success"` | `"info"` |
|
|
13
13
|
| `closable` | if `true`, display the close button. | `boolean` | - |
|
|
14
14
|
|
|
15
15
|
## Slots
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { mount } from '@vue/test-utils';
|
|
3
|
+
import MStepperCompact from './MStepperCompact.vue';
|
|
4
|
+
|
|
5
|
+
describe('MStepperCompact component', () => {
|
|
6
|
+
it('renders with required label and optional description', () => {
|
|
7
|
+
const wrapper = mount(MStepperCompact, {
|
|
8
|
+
props: {
|
|
9
|
+
label: 'Current Step',
|
|
10
|
+
},
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
expect(wrapper.find('.mc-stepper-compact').exists()).toBe(true);
|
|
14
|
+
expect(wrapper.find('.mc-stepper-compact__progress').exists()).toBe(true);
|
|
15
|
+
expect(wrapper.find('.mc-stepper-compact__label').text()).toBe(
|
|
16
|
+
'Current Step',
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
// description should NOT be rendered by default
|
|
20
|
+
expect(wrapper.find('.mc-stepper-compact__description').exists()).toBe(
|
|
21
|
+
false,
|
|
22
|
+
);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('calculates progress value correctly', () => {
|
|
26
|
+
const wrapper = mount(MStepperCompact, {
|
|
27
|
+
props: {
|
|
28
|
+
label: 'Current Step',
|
|
29
|
+
value: 2,
|
|
30
|
+
maxSteps: 5,
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const progressbar = wrapper.findComponent({ name: 'MCircularProgressbar' });
|
|
35
|
+
|
|
36
|
+
expect(progressbar.props('value')).toBe(40); // (2/5) * 100
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('displays correct content value (current step / total)', () => {
|
|
40
|
+
const wrapper = mount(MStepperCompact, {
|
|
41
|
+
props: {
|
|
42
|
+
label: 'Current Step',
|
|
43
|
+
value: 3,
|
|
44
|
+
maxSteps: 7,
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const progressbar = wrapper.findComponent({ name: 'MCircularProgressbar' });
|
|
49
|
+
|
|
50
|
+
expect(progressbar.props('contentValue')).toBe('3 / 7');
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('passes correct props to MCircularProgressbar', () => {
|
|
54
|
+
const wrapper = mount(MStepperCompact, {
|
|
55
|
+
props: {
|
|
56
|
+
label: 'Current Step',
|
|
57
|
+
value: 2,
|
|
58
|
+
maxSteps: 4,
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const progressbar = wrapper.findComponent({ name: 'MCircularProgressbar' });
|
|
63
|
+
|
|
64
|
+
expect(progressbar.props('type')).toBe('content');
|
|
65
|
+
expect(progressbar.props('size')).toBe('m');
|
|
66
|
+
expect(progressbar.props('value')).toBe(50); // (2/4) * 100
|
|
67
|
+
expect(progressbar.props('contentValue')).toBe('2 / 4');
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('renders custom label and description when provided', () => {
|
|
71
|
+
const wrapper = mount(MStepperCompact, {
|
|
72
|
+
props: {
|
|
73
|
+
label: 'Custom Label',
|
|
74
|
+
description: 'Custom Description',
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
expect(wrapper.find('.mc-stepper-compact__label').text()).toBe(
|
|
79
|
+
'Custom Label',
|
|
80
|
+
);
|
|
81
|
+
expect(wrapper.find('.mc-stepper-compact__description').text()).toBe(
|
|
82
|
+
'Custom Description',
|
|
83
|
+
);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('does not render description element when description is empty', () => {
|
|
87
|
+
const wrapper = mount(MStepperCompact, {
|
|
88
|
+
props: {
|
|
89
|
+
label: 'Label Only',
|
|
90
|
+
description: undefined,
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
expect(wrapper.find('.mc-stepper-compact__description').exists()).toBe(
|
|
95
|
+
false,
|
|
96
|
+
);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3-vite';
|
|
2
|
+
import MStepperCompact from './MStepperCompact.vue';
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof MStepperCompact> = {
|
|
5
|
+
title: 'Indicators/Stepper Compact',
|
|
6
|
+
component: MStepperCompact,
|
|
7
|
+
tags: ['v2'],
|
|
8
|
+
parameters: {
|
|
9
|
+
docs: {
|
|
10
|
+
description: {
|
|
11
|
+
component:
|
|
12
|
+
'A stepper is a navigation component that guides users through a sequence of steps in a structured process. It visually represents progress, completed steps, and upcoming steps, helping users understand their position within a workflow. Steppers are commonly used in multi-step forms, onboarding flows, checkout processes, and task completion sequences to improve clarity and reduce cognitive load.',
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
argTypes: {
|
|
17
|
+
value: {
|
|
18
|
+
control: { type: 'number', min: 1, max: 10 },
|
|
19
|
+
},
|
|
20
|
+
maxSteps: {
|
|
21
|
+
control: { type: 'number', min: 2, max: 10 },
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
args: {
|
|
25
|
+
value: 1,
|
|
26
|
+
maxSteps: 4,
|
|
27
|
+
label: 'Current Step',
|
|
28
|
+
description: 'Next: Step label',
|
|
29
|
+
},
|
|
30
|
+
render: (args) => ({
|
|
31
|
+
components: { MStepperCompact },
|
|
32
|
+
setup() {
|
|
33
|
+
return { args };
|
|
34
|
+
},
|
|
35
|
+
template: `
|
|
36
|
+
<MStepperCompact v-bind="args"></MStepperCompact>
|
|
37
|
+
`,
|
|
38
|
+
}),
|
|
39
|
+
};
|
|
40
|
+
export default meta;
|
|
41
|
+
type Story = StoryObj<typeof MStepperCompact>;
|
|
42
|
+
|
|
43
|
+
export const Default: Story = {};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="mc-stepper-compact">
|
|
3
|
+
<div class="mc-circular-progressbar mc-stepper-compact__progress">
|
|
4
|
+
<MCircularProgressbar
|
|
5
|
+
aria-label="Progress bar"
|
|
6
|
+
type="content"
|
|
7
|
+
size="m"
|
|
8
|
+
:value="progressValue"
|
|
9
|
+
:content-value="contentValue"
|
|
10
|
+
class="mc-stepper-compact__indicator mc-stepper-compact__number"
|
|
11
|
+
/>
|
|
12
|
+
</div>
|
|
13
|
+
<div class="mc-stepper-compact__label-container">
|
|
14
|
+
<p class="mc-stepper-compact__label">
|
|
15
|
+
{{ label }}
|
|
16
|
+
</p>
|
|
17
|
+
<p v-if="description" class="mc-stepper-compact__description">
|
|
18
|
+
{{ description }}
|
|
19
|
+
</p>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
</template>
|
|
23
|
+
|
|
24
|
+
<script setup lang="ts">
|
|
25
|
+
import { computed } from 'vue';
|
|
26
|
+
import MCircularProgressbar from '../circularprogressbar/MCircularProgressbar.vue';
|
|
27
|
+
/**
|
|
28
|
+
* A stepper is a navigation component that guides users through a sequence of steps in a structured process. It visually represents progress, completed steps, and upcoming steps, helping users understand their position within a workflow. Steppers are commonly used in multi-step forms, onboarding flows, checkout processes, and task completion sequences to improve clarity and reduce cognitive load.
|
|
29
|
+
*/
|
|
30
|
+
const props = withDefaults(
|
|
31
|
+
defineProps<{
|
|
32
|
+
/**
|
|
33
|
+
* Current step of the stepper compact.
|
|
34
|
+
*/
|
|
35
|
+
value?: number;
|
|
36
|
+
/**
|
|
37
|
+
* Maximum number of steps for the stepper compact.
|
|
38
|
+
*/
|
|
39
|
+
maxSteps?: number;
|
|
40
|
+
/**
|
|
41
|
+
* Label of the stepper compact.
|
|
42
|
+
*/
|
|
43
|
+
label: string;
|
|
44
|
+
/**
|
|
45
|
+
* Description displayed below the label of the stepper compact.
|
|
46
|
+
*/
|
|
47
|
+
description?: string;
|
|
48
|
+
}>(),
|
|
49
|
+
{
|
|
50
|
+
value: 1,
|
|
51
|
+
maxSteps: 4,
|
|
52
|
+
},
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
const progressValue = computed(() => {
|
|
56
|
+
const value = props.value ?? 0;
|
|
57
|
+
const max = props.maxSteps ?? 1;
|
|
58
|
+
return Math.round((value / max) * 100);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const contentValue = computed(() => {
|
|
62
|
+
return `${props.value} / ${props.maxSteps}`;
|
|
63
|
+
});
|
|
64
|
+
</script>
|
|
65
|
+
|
|
66
|
+
<style lang="scss" scoped>
|
|
67
|
+
@use '@mozaic-ds/styles/components/stepper-compact';
|
|
68
|
+
@use '@mozaic-ds/styles/components/circular-progressbar/_t.circular-progressbar'
|
|
69
|
+
as *;
|
|
70
|
+
|
|
71
|
+
.mc-stepper-compact__progress {
|
|
72
|
+
width: $spacing-600;
|
|
73
|
+
height: $spacing-600;
|
|
74
|
+
|
|
75
|
+
::v-deep(.mc-circular-progressbar__content) {
|
|
76
|
+
display: block;
|
|
77
|
+
visibility: visible;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
::v-deep(.mc-circular-progressbar__number) {
|
|
81
|
+
display: block;
|
|
82
|
+
visibility: visible;
|
|
83
|
+
opacity: 1;
|
|
84
|
+
color: inherit;
|
|
85
|
+
font-size: inherit;
|
|
86
|
+
line-height: inherit;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
::v-deep(.mc-circular-progressbar__number) {
|
|
90
|
+
display: block;
|
|
91
|
+
visibility: visible;
|
|
92
|
+
opacity: 1;
|
|
93
|
+
color: inherit;
|
|
94
|
+
font-size: inherit;
|
|
95
|
+
line-height: inherit;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
::v-deep(.mc-circular-progressbar__indicator) {
|
|
99
|
+
@include calculate-border-width(4, 48, 100);
|
|
100
|
+
stroke: $stepper-color-progress-bar-indicator;
|
|
101
|
+
fill: none;
|
|
102
|
+
stroke-linecap: round;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
</style>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# MStepperCompact
|
|
2
|
+
|
|
3
|
+
A stepper is a navigation component that guides users through a sequence of steps in a structured process. It visually represents progress, completed steps, and upcoming steps, helping users understand their position within a workflow. Steppers are commonly used in multi-step forms, onboarding flows, checkout processes, and task completion sequences to improve clarity and reduce cognitive load.
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
## Props
|
|
7
|
+
|
|
8
|
+
| Name | Description | Type | Default |
|
|
9
|
+
| --- | --- | --- | --- |
|
|
10
|
+
| `value` | Current step of the stepper compact. | `number` | `1` |
|
|
11
|
+
| `maxSteps` | Maximum number of steps for the stepper compact. | `number` | `4` |
|
|
12
|
+
| `label*` | Label of the stepper compact. | `string` | - |
|
|
13
|
+
| `description` | Description displayed below the label of the stepper compact. | `string` | - |
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { mount } from '@vue/test-utils';
|
|
2
|
+
import MStepperInline from './MStepperInline.vue';
|
|
3
|
+
import { describe, it, expect } from 'vitest';
|
|
4
|
+
|
|
5
|
+
describe('MStepperInline', () => {
|
|
6
|
+
const defaultSteps = [
|
|
7
|
+
{ label: 'Step 1' },
|
|
8
|
+
{ label: 'Step 2' },
|
|
9
|
+
{ label: 'Step 3' },
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
it('renders correctly with default props', () => {
|
|
13
|
+
const wrapper = mount(MStepperInline, {
|
|
14
|
+
props: {
|
|
15
|
+
currentStep: 1,
|
|
16
|
+
steps: defaultSteps,
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
expect(wrapper.exists()).toBe(true);
|
|
21
|
+
expect(wrapper.findAll('.mc-stepper-inline__item').length).toBe(
|
|
22
|
+
defaultSteps.length,
|
|
23
|
+
);
|
|
24
|
+
expect(wrapper.find('.mc-stepper-inline__label').text()).toContain(
|
|
25
|
+
'Step 1',
|
|
26
|
+
);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('displays additional information when provided', () => {
|
|
30
|
+
const stepsWithInfo = [
|
|
31
|
+
{ label: 'Step 1', additionalInfo: 'Info 1' },
|
|
32
|
+
{ label: 'Step 2', additionalInfo: 'Info 2' },
|
|
33
|
+
];
|
|
34
|
+
const wrapper = mount(MStepperInline, {
|
|
35
|
+
props: {
|
|
36
|
+
currentStep: 1,
|
|
37
|
+
steps: stepsWithInfo,
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
expect(wrapper.findAll('.mc-stepper-inline__additional').length).toBe(
|
|
42
|
+
stepsWithInfo.length,
|
|
43
|
+
);
|
|
44
|
+
expect(wrapper.find('.mc-stepper-inline__additional').text()).toBe(
|
|
45
|
+
'Info 1',
|
|
46
|
+
);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('marks the correct step as active', async () => {
|
|
50
|
+
const wrapper = mount(MStepperInline, {
|
|
51
|
+
props: {
|
|
52
|
+
currentStep: 2,
|
|
53
|
+
steps: defaultSteps,
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const labels = wrapper.findAll('.mc-stepper-inline__label');
|
|
58
|
+
expect(labels[1].classes()).toContain('is-current');
|
|
59
|
+
expect(labels[0].classes()).not.toContain('is-current');
|
|
60
|
+
|
|
61
|
+
await wrapper.setProps({ currentStep: 3 });
|
|
62
|
+
expect(labels[2].classes()).toContain('is-current');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('marks completed steps', () => {
|
|
66
|
+
const wrapper = mount(MStepperInline, {
|
|
67
|
+
props: {
|
|
68
|
+
currentStep: 3,
|
|
69
|
+
steps: defaultSteps,
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
const items = wrapper.findAll('.mc-stepper-inline__item');
|
|
74
|
+
expect(items[0].classes()).toContain('is-completed');
|
|
75
|
+
expect(items[1].classes()).toContain('is-completed');
|
|
76
|
+
expect(items[2].classes()).not.toContain('is-completed');
|
|
77
|
+
});
|
|
78
|
+
});
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3-vite';
|
|
2
|
+
import MStepperInline from './MStepperInline.vue';
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof MStepperInline> = {
|
|
5
|
+
title: 'Indicators/Stepper Inline',
|
|
6
|
+
component: MStepperInline,
|
|
7
|
+
tags: ['v2'],
|
|
8
|
+
parameters: {
|
|
9
|
+
docs: {
|
|
10
|
+
description: {
|
|
11
|
+
component:
|
|
12
|
+
'A stepper is a navigation component that guides users through a sequence of steps in a structured process. It visually represents progress, completed steps, and upcoming steps, helping users understand their position within a workflow. Steppers are commonly used in multi-step forms, onboarding flows, checkout processes, and task completion sequences to improve clarity and reduce cognitive load.',
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
args: {
|
|
17
|
+
currentStep: 1,
|
|
18
|
+
steps: [
|
|
19
|
+
{ label: 'Cart' },
|
|
20
|
+
{ label: 'Delivery address' },
|
|
21
|
+
{ label: 'Payment' },
|
|
22
|
+
{ label: 'Order confirmation' },
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
render: (args) => ({
|
|
26
|
+
components: { MStepperInline },
|
|
27
|
+
setup() {
|
|
28
|
+
return { args };
|
|
29
|
+
},
|
|
30
|
+
template: `<MStepperInline v-bind="args" />`,
|
|
31
|
+
}),
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export default meta;
|
|
35
|
+
type Story = StoryObj<typeof MStepperInline>;
|
|
36
|
+
|
|
37
|
+
export const Default: Story = {};
|
|
38
|
+
|
|
39
|
+
export const AditionnalInfo: Story = {
|
|
40
|
+
args: {
|
|
41
|
+
currentStep: 2,
|
|
42
|
+
steps: [
|
|
43
|
+
{ label: 'Cart', additionalInfo: 'Additional information' },
|
|
44
|
+
{ label: 'Delivery address', additionalInfo: 'Additional information' },
|
|
45
|
+
{ label: 'Payment', additionalInfo: 'Additional information' },
|
|
46
|
+
{ label: 'Order confirmation', additionalInfo: 'Additional information' },
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
};
|