@mozaic-ds/vue 2.4.0 → 2.5.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 +527 -338
- package/dist/mozaic-vue.js +941 -795
- package/dist/mozaic-vue.js.map +1 -1
- package/dist/mozaic-vue.umd.cjs +1 -1
- package/dist/mozaic-vue.umd.cjs.map +1 -1
- package/package.json +4 -4
- package/src/components/avatar/MAvatar.spec.ts +49 -0
- package/src/components/avatar/MAvatar.stories.ts +53 -0
- package/src/components/avatar/MAvatar.vue +47 -0
- package/src/components/callout/MCallout.spec.ts +99 -0
- package/src/components/callout/MCallout.stories.ts +87 -0
- package/src/components/callout/MCallout.vue +66 -0
- package/src/components/checkbox/MCheckbox.spec.ts +54 -4
- package/src/components/checkbox/MCheckbox.vue +11 -1
- package/src/components/checkboxgroup/MCheckboxGroup.vue +2 -0
- package/src/components/container/MContainer.vue +8 -1
- package/src/components/divider/MDivider.vue +8 -1
- package/src/components/drawer/MDrawer.stories.ts +11 -0
- package/src/components/loadingoverlay/MLoadingOverlay.stories.ts +11 -0
- package/src/components/modal/MModal.stories.ts +11 -0
- package/src/components/overlay/MOverlay.stories.ts +11 -0
- package/src/components/textinput/MTextInput.spec.ts +2 -2
- package/src/components/textinput/MTextInput.stories.ts +9 -3
- package/src/components/textinput/MTextInput.vue +3 -5
- package/src/components/toaster/MToaster.spec.ts +122 -0
- package/src/components/toaster/MToaster.stories.ts +105 -0
- package/src/components/toaster/MToaster.vue +181 -0
- package/src/components/tooltip/MTooltip.stories.ts +11 -0
- package/src/main.ts +3 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mozaic-ds/vue",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.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",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"*.d.ts"
|
|
41
41
|
],
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@mozaic-ds/styles": "2.0.0-beta.
|
|
43
|
+
"@mozaic-ds/styles": "2.0.0-beta.5",
|
|
44
44
|
"@mozaic-ds/web-fonts": "1.65.0",
|
|
45
45
|
"postcss-scss": "^4.0.9",
|
|
46
46
|
"vue": "^3.5.13"
|
|
@@ -50,11 +50,11 @@
|
|
|
50
50
|
"@commitlint/config-conventional": "^19.8.0",
|
|
51
51
|
"@mozaic-ds/css-dev-tools": "1.75.0",
|
|
52
52
|
"@mozaic-ds/icons-vue": "^1.0.0",
|
|
53
|
-
"@release-it/conventional-changelog": "^
|
|
53
|
+
"@release-it/conventional-changelog": "^10.0.1",
|
|
54
54
|
"@storybook/addon-a11y": "^9.0.18",
|
|
55
|
+
"@storybook/addon-docs": "^9.0.18",
|
|
55
56
|
"@storybook/addon-themes": "^9.0.18",
|
|
56
57
|
"@storybook/vue3-vite": "^9.0.18",
|
|
57
|
-
"@storybook/addon-docs": "^9.0.18",
|
|
58
58
|
"@types/jsdom": "^21.1.7",
|
|
59
59
|
"@vitejs/plugin-vue": "^6.0.1",
|
|
60
60
|
"@vitest/coverage-v8": "^3.0.9",
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { mount } from '@vue/test-utils';
|
|
3
|
+
import MAvatar from './MAvatar.vue';
|
|
4
|
+
|
|
5
|
+
describe('MAvatar.vue', () => {
|
|
6
|
+
it('renders the component with default size (s)', () => {
|
|
7
|
+
const wrapper = mount(MAvatar, {
|
|
8
|
+
slots: {
|
|
9
|
+
default: '<span>AB</span>',
|
|
10
|
+
},
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
expect(wrapper.classes()).toContain('mc-avatar');
|
|
14
|
+
expect(wrapper.classes().some((cls) => cls.startsWith('mc-avatar--'))).toBe(
|
|
15
|
+
false,
|
|
16
|
+
);
|
|
17
|
+
expect(wrapper.text()).toContain('AB');
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('applies the correct class for size "m"', () => {
|
|
21
|
+
const wrapper = mount(MAvatar, {
|
|
22
|
+
props: {
|
|
23
|
+
size: 'm',
|
|
24
|
+
},
|
|
25
|
+
slots: {
|
|
26
|
+
default: '<span>CD</span>',
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
expect(wrapper.classes()).toContain('mc-avatar');
|
|
31
|
+
expect(wrapper.classes()).toContain('mc-avatar--m');
|
|
32
|
+
expect(wrapper.text()).toContain('CD');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('applies the correct class for size "l"', () => {
|
|
36
|
+
const wrapper = mount(MAvatar, {
|
|
37
|
+
props: {
|
|
38
|
+
size: 'l',
|
|
39
|
+
},
|
|
40
|
+
slots: {
|
|
41
|
+
default: '<span>EF</span>',
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
expect(wrapper.classes()).toContain('mc-avatar');
|
|
46
|
+
expect(wrapper.classes()).toContain('mc-avatar--l');
|
|
47
|
+
expect(wrapper.text()).toContain('EF');
|
|
48
|
+
});
|
|
49
|
+
});
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3-vite';
|
|
2
|
+
|
|
3
|
+
import MAvatar from './MAvatar.vue';
|
|
4
|
+
import Profile24 from '@mozaic-ds/icons-vue/src/components/Profile24/Profile24.vue';
|
|
5
|
+
|
|
6
|
+
const meta: Meta<typeof MAvatar> = {
|
|
7
|
+
title: 'Content/Avatar',
|
|
8
|
+
component: MAvatar,
|
|
9
|
+
parameters: {
|
|
10
|
+
docs: {
|
|
11
|
+
description: {
|
|
12
|
+
component:
|
|
13
|
+
'An avatar is a graphical representation of a user, entity, or group, commonly displayed as an image, initials, or an icon. It helps identify individuals or accounts in profiles, comments, chat interfaces, and user lists. Avatars can be customized with different styles, sizes, and fallback options (such as initials or placeholders) to ensure consistency and recognition across interfaces. When multiple users are represented, Avatar groups provide a compact way to display them collectively.',
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
args: {
|
|
18
|
+
default: `
|
|
19
|
+
<img src="/images/Avatar.png" alt="Dieter Rams" loading="lazy"/>
|
|
20
|
+
`,
|
|
21
|
+
},
|
|
22
|
+
render: (args) => ({
|
|
23
|
+
components: { MAvatar, Profile24 },
|
|
24
|
+
setup() {
|
|
25
|
+
return { args };
|
|
26
|
+
},
|
|
27
|
+
template: `
|
|
28
|
+
<MAvatar v-bind="args">
|
|
29
|
+
${args.default}
|
|
30
|
+
</MAvatar>
|
|
31
|
+
`,
|
|
32
|
+
}),
|
|
33
|
+
};
|
|
34
|
+
export default meta;
|
|
35
|
+
type Story = StoryObj<typeof MAvatar>;
|
|
36
|
+
|
|
37
|
+
export const Default: Story = {};
|
|
38
|
+
|
|
39
|
+
export const Initials: Story = {
|
|
40
|
+
args: {
|
|
41
|
+
default: `
|
|
42
|
+
DS
|
|
43
|
+
`,
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const Icon: Story = {
|
|
48
|
+
args: {
|
|
49
|
+
default: `
|
|
50
|
+
<Profile24/>
|
|
51
|
+
`,
|
|
52
|
+
},
|
|
53
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<span class="mc-avatar" :class="classObject">
|
|
3
|
+
<slot />
|
|
4
|
+
</span>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script setup lang="ts">
|
|
8
|
+
import { computed, type VNode } from 'vue';
|
|
9
|
+
/**
|
|
10
|
+
* An avatar is a graphical representation of a user, entity, or group, commonly displayed as an image, initials, or an icon. It helps identify individuals or accounts in profiles, comments, chat interfaces, and user lists. Avatars can be customized with different styles, sizes, and fallback options (such as initials or placeholders) to ensure consistency and recognition across interfaces. When multiple users are represented, Avatar groups provide a compact way to display them collectively.
|
|
11
|
+
*/
|
|
12
|
+
const props = withDefaults(
|
|
13
|
+
defineProps<{
|
|
14
|
+
/**
|
|
15
|
+
* Allows to define the avatar size
|
|
16
|
+
*/
|
|
17
|
+
size?: 's' | 'm' | 'l';
|
|
18
|
+
}>(),
|
|
19
|
+
{
|
|
20
|
+
size: 's',
|
|
21
|
+
},
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
const classObject = computed(() => {
|
|
25
|
+
return {
|
|
26
|
+
[`mc-avatar--${props.size}`]: props.size && props.size != 's',
|
|
27
|
+
};
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
defineSlots<{
|
|
31
|
+
/**
|
|
32
|
+
* Use this slot to insert the image, icon or intials of the avatar
|
|
33
|
+
*/
|
|
34
|
+
default: VNode;
|
|
35
|
+
}>();
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
<style lang="scss" scoped>
|
|
39
|
+
@use '@mozaic-ds/styles/components/avatar';
|
|
40
|
+
|
|
41
|
+
::v-deep(img) {
|
|
42
|
+
display: block;
|
|
43
|
+
width: 100%;
|
|
44
|
+
height: 100%;
|
|
45
|
+
object-fit: contain;
|
|
46
|
+
}
|
|
47
|
+
</style>
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import { mount } from '@vue/test-utils';
|
|
3
|
+
import MCallout from './MCallout.vue';
|
|
4
|
+
|
|
5
|
+
vi.mock(
|
|
6
|
+
'@mozaic-ds/icons-vue/src/components/ImageAlt32/ImageAlt32.vue',
|
|
7
|
+
() => ({
|
|
8
|
+
default: {
|
|
9
|
+
name: 'ImageAlt32',
|
|
10
|
+
template: '<svg class="mock-icon" />',
|
|
11
|
+
},
|
|
12
|
+
}),
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
describe('MCallout.vue', () => {
|
|
16
|
+
it('renders title and description correctly', () => {
|
|
17
|
+
const wrapper = mount(MCallout, {
|
|
18
|
+
props: {
|
|
19
|
+
title: 'Callout Title',
|
|
20
|
+
description: 'This is a description',
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
expect(wrapper.find('.mc-callout__title').text()).toBe('Callout Title');
|
|
25
|
+
expect(wrapper.find('.mc-callout__message').text()).toBe(
|
|
26
|
+
'This is a description',
|
|
27
|
+
);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('renders with default appearance (standard)', () => {
|
|
31
|
+
const wrapper = mount(MCallout, {
|
|
32
|
+
props: {
|
|
33
|
+
title: 'Title',
|
|
34
|
+
description: 'Description',
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
expect(wrapper.classes()).toContain('mc-callout');
|
|
39
|
+
// No modifier class for 'standard' appearance
|
|
40
|
+
expect(
|
|
41
|
+
wrapper.classes().some((cls) => cls.startsWith('mc-callout--')),
|
|
42
|
+
).toBe(false);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('applies the correct class for appearance "accent"', () => {
|
|
46
|
+
const wrapper = mount(MCallout, {
|
|
47
|
+
props: {
|
|
48
|
+
title: 'Title',
|
|
49
|
+
description: 'Description',
|
|
50
|
+
appearance: 'accent',
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
expect(wrapper.classes()).toContain('mc-callout--accent');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('renders the icon slot content', () => {
|
|
58
|
+
const wrapper = mount(MCallout, {
|
|
59
|
+
props: {
|
|
60
|
+
title: 'Title',
|
|
61
|
+
description: 'Description',
|
|
62
|
+
},
|
|
63
|
+
slots: {
|
|
64
|
+
icon: '<svg class="test-icon" />',
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const iconContainer = wrapper.find('.mc-callout__icon');
|
|
69
|
+
expect(iconContainer.exists()).toBe(true);
|
|
70
|
+
expect(iconContainer.find('svg.test-icon').exists()).toBe(true);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('renders footer slot when provided', () => {
|
|
74
|
+
const wrapper = mount(MCallout, {
|
|
75
|
+
props: {
|
|
76
|
+
title: 'Title',
|
|
77
|
+
description: 'Description',
|
|
78
|
+
},
|
|
79
|
+
slots: {
|
|
80
|
+
footer: '<button class="footer-button">Click me</button>',
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const footer = wrapper.find('.mc-callout__footer');
|
|
85
|
+
expect(footer.exists()).toBe(true);
|
|
86
|
+
expect(footer.find('button.footer-button').text()).toBe('Click me');
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('does not render footer section when slot is not provided', () => {
|
|
90
|
+
const wrapper = mount(MCallout, {
|
|
91
|
+
props: {
|
|
92
|
+
title: 'Title',
|
|
93
|
+
description: 'Description',
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
expect(wrapper.find('.mc-callout__footer').exists()).toBe(false);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3-vite';
|
|
2
|
+
import MCallout from './MCallout.vue';
|
|
3
|
+
import MButton from '../button/MButton.vue';
|
|
4
|
+
import MLink from '../link/MLink.vue';
|
|
5
|
+
import ArrowNext20 from '@mozaic-ds/icons-vue/src/components/ArrowNext20/ArrowNext20.vue';
|
|
6
|
+
import ImageAlt32 from '@mozaic-ds/icons-vue/src/components/ImageAlt32/ImageAlt32.vue';
|
|
7
|
+
|
|
8
|
+
const meta: Meta<typeof MCallout> = {
|
|
9
|
+
title: 'Content/Callout',
|
|
10
|
+
component: MCallout,
|
|
11
|
+
parameters: {
|
|
12
|
+
docs: {
|
|
13
|
+
description: {
|
|
14
|
+
component:
|
|
15
|
+
'A callout is used to highlight additional information that can assist users with tips, extra details, or helpful guidance, without signaling a critical status or alert. Unlike notifications, callouts are not triggered by user actions and do not correspond to specific system states. They are designed to enhance the user experience by providing contextually relevant information that supports comprehension and usability.',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
args: {
|
|
20
|
+
icon: '<ImageAlt32 aria-hidden="true" />',
|
|
21
|
+
title:
|
|
22
|
+
'This is a title, be concise and use the description message to give details.',
|
|
23
|
+
description: 'Description message.',
|
|
24
|
+
},
|
|
25
|
+
render: (args) => ({
|
|
26
|
+
components: { MCallout, MButton, MLink, ArrowNext20, ImageAlt32 },
|
|
27
|
+
setup() {
|
|
28
|
+
return { args };
|
|
29
|
+
},
|
|
30
|
+
template: `
|
|
31
|
+
<MCallout
|
|
32
|
+
v-bind="args"
|
|
33
|
+
>
|
|
34
|
+
<template v-if="${'icon' in args}" v-slot:icon>${args.icon}</template>
|
|
35
|
+
<template v-if="${'footer' in args}" v-slot:footer>${args.footer}</template>
|
|
36
|
+
</MCallout>
|
|
37
|
+
`,
|
|
38
|
+
}),
|
|
39
|
+
};
|
|
40
|
+
export default meta;
|
|
41
|
+
type Story = StoryObj<typeof MCallout>;
|
|
42
|
+
|
|
43
|
+
export const Standard: Story = {};
|
|
44
|
+
|
|
45
|
+
export const Accent: Story = {
|
|
46
|
+
args: { appearance: 'accent' },
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export const Tips: Story = {
|
|
50
|
+
args: { appearance: 'tips' },
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export const Inverse: Story = {
|
|
54
|
+
globals: {
|
|
55
|
+
backgrounds: { value: 'inverse' },
|
|
56
|
+
},
|
|
57
|
+
args: { appearance: 'inverse' },
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export const WithButton = {
|
|
61
|
+
args: {
|
|
62
|
+
footer: `
|
|
63
|
+
<MButton outlined>Button Label</MButton>
|
|
64
|
+
`,
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export const WithButtons = {
|
|
69
|
+
args: {
|
|
70
|
+
footer: `
|
|
71
|
+
<MButton>Button Label</MButton>
|
|
72
|
+
<MButton outlined>Button Label</MButton>
|
|
73
|
+
`,
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const WithLink = {
|
|
78
|
+
args: {
|
|
79
|
+
footer: `
|
|
80
|
+
<MLink href="#" iconPosition="right">
|
|
81
|
+
Stand-alone link
|
|
82
|
+
|
|
83
|
+
<template #icon><ArrowNext20 /></template>
|
|
84
|
+
</MLink>
|
|
85
|
+
`,
|
|
86
|
+
},
|
|
87
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<section class="mc-callout" role="status" :class="classObject">
|
|
3
|
+
<div class="mc-callout__icon">
|
|
4
|
+
<slot name="icon" />
|
|
5
|
+
</div>
|
|
6
|
+
<div class="mc-callout__content">
|
|
7
|
+
<h2 class="mc-callout__title">{{ title }}</h2>
|
|
8
|
+
|
|
9
|
+
<p class="mc-callout__message">
|
|
10
|
+
{{ description }}
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
<div v-if="$slots.footer" class="mc-callout__footer">
|
|
14
|
+
<slot name="footer" />
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|
|
17
|
+
</section>
|
|
18
|
+
</template>
|
|
19
|
+
|
|
20
|
+
<script setup lang="ts">
|
|
21
|
+
import { computed, type VNode } from 'vue';
|
|
22
|
+
/**
|
|
23
|
+
* A callout is used to highlight additional information that can assist users with tips, extra details, or helpful guidance, without signaling a critical status or alert. Unlike notifications, callouts are not triggered by user actions and do not correspond to specific system states. They are designed to enhance the user experience by providing contextually relevant information that supports comprehension and usability.
|
|
24
|
+
*/
|
|
25
|
+
const props = withDefaults(
|
|
26
|
+
defineProps<{
|
|
27
|
+
/**
|
|
28
|
+
* Title of the callout
|
|
29
|
+
*/
|
|
30
|
+
title: string;
|
|
31
|
+
/**
|
|
32
|
+
* Description of the callout
|
|
33
|
+
*/
|
|
34
|
+
description: string;
|
|
35
|
+
/**
|
|
36
|
+
* Allows to define the callout style
|
|
37
|
+
*/
|
|
38
|
+
appearance?: 'standard' | 'accent' | 'tips' | 'inverse';
|
|
39
|
+
}>(),
|
|
40
|
+
{
|
|
41
|
+
appearance: 'standard',
|
|
42
|
+
},
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
defineSlots<{
|
|
46
|
+
/**
|
|
47
|
+
* Use this slot to insert an icon
|
|
48
|
+
*/
|
|
49
|
+
icon?: VNode;
|
|
50
|
+
/**
|
|
51
|
+
* Use this slot to insert a button or a link in the footer of the callout
|
|
52
|
+
*/
|
|
53
|
+
footer?: VNode;
|
|
54
|
+
}>();
|
|
55
|
+
|
|
56
|
+
const classObject = computed(() => {
|
|
57
|
+
return {
|
|
58
|
+
[`mc-callout--${props.appearance}`]:
|
|
59
|
+
props.appearance && props.appearance != 'standard',
|
|
60
|
+
};
|
|
61
|
+
});
|
|
62
|
+
</script>
|
|
63
|
+
|
|
64
|
+
<style lang="scss" scoped>
|
|
65
|
+
@use '@mozaic-ds/styles/components/callout';
|
|
66
|
+
</style>
|
|
@@ -3,7 +3,7 @@ import MCheckbox from './MCheckbox.vue';
|
|
|
3
3
|
import { describe, it, expect } from 'vitest';
|
|
4
4
|
|
|
5
5
|
describe('MCheckbox', () => {
|
|
6
|
-
it('renders with label', () => {
|
|
6
|
+
it('renders with label when label prop is provided', () => {
|
|
7
7
|
const wrapper = mount(MCheckbox, {
|
|
8
8
|
props: {
|
|
9
9
|
id: 'test-checkbox',
|
|
@@ -12,7 +12,20 @@ describe('MCheckbox', () => {
|
|
|
12
12
|
},
|
|
13
13
|
});
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
const label = wrapper.find('label');
|
|
16
|
+
expect(label.exists()).toBe(true);
|
|
17
|
+
expect(label.text()).toBe('Accept terms');
|
|
18
|
+
expect(label.attributes('for')).toBe('test-checkbox');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('does not render label when label prop is not provided', () => {
|
|
22
|
+
const wrapper = mount(MCheckbox, {
|
|
23
|
+
props: {
|
|
24
|
+
id: 'test-checkbox',
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
expect(wrapper.find('label').exists()).toBe(false);
|
|
16
29
|
});
|
|
17
30
|
|
|
18
31
|
it('renders the checkbox as checked when modelValue is true', () => {
|
|
@@ -50,6 +63,7 @@ describe('MCheckbox', () => {
|
|
|
50
63
|
const checkbox = wrapper.find('input');
|
|
51
64
|
await checkbox.setChecked(true);
|
|
52
65
|
|
|
66
|
+
expect(wrapper.emitted()['update:modelValue']).toBeTruthy();
|
|
53
67
|
expect(wrapper.emitted()['update:modelValue'][0]).toEqual([true]);
|
|
54
68
|
});
|
|
55
69
|
|
|
@@ -91,7 +105,19 @@ describe('MCheckbox', () => {
|
|
|
91
105
|
expect(checkbox.element.indeterminate).toBe(true);
|
|
92
106
|
});
|
|
93
107
|
|
|
94
|
-
it('applies is-invalid class when isInvalid is true', () => {
|
|
108
|
+
it('applies "is-invalid" class when isInvalid is true', () => {
|
|
109
|
+
const wrapper = mount(MCheckbox, {
|
|
110
|
+
props: {
|
|
111
|
+
id: 'test-checkbox',
|
|
112
|
+
isInvalid: true,
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
const checkbox = wrapper.find('input');
|
|
117
|
+
expect(checkbox.classes()).toContain('is-invalid');
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('adds "aria-invalid" attribute when isInvalid is true', () => {
|
|
95
121
|
const wrapper = mount(MCheckbox, {
|
|
96
122
|
props: {
|
|
97
123
|
id: 'test-checkbox',
|
|
@@ -99,6 +125,30 @@ describe('MCheckbox', () => {
|
|
|
99
125
|
},
|
|
100
126
|
});
|
|
101
127
|
|
|
102
|
-
|
|
128
|
+
const checkbox = wrapper.find('input');
|
|
129
|
+
expect(checkbox.attributes('aria-invalid')).toBe('true');
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('applies "mc-checkbox--indented" class when indented is true', () => {
|
|
133
|
+
const wrapper = mount(MCheckbox, {
|
|
134
|
+
props: {
|
|
135
|
+
id: 'test-checkbox',
|
|
136
|
+
indented: true,
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
expect(wrapper.classes()).toContain('mc-checkbox--indented');
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it('sets the name attribute when name prop is provided', () => {
|
|
144
|
+
const wrapper = mount(MCheckbox, {
|
|
145
|
+
props: {
|
|
146
|
+
id: 'test-checkbox',
|
|
147
|
+
name: 'accept',
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
const checkbox = wrapper.find('input');
|
|
152
|
+
expect(checkbox.attributes('name')).toBe('accept');
|
|
103
153
|
});
|
|
104
154
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="mc-checkbox">
|
|
2
|
+
<div class="mc-checkbox" :class="classObjectCheckbox">
|
|
3
3
|
<input
|
|
4
4
|
:id="id"
|
|
5
5
|
type="checkbox"
|
|
@@ -56,6 +56,10 @@ const props = defineProps<{
|
|
|
56
56
|
* If `true`, disables the checkbox, making it non-interactive.
|
|
57
57
|
*/
|
|
58
58
|
disabled?: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* If `true`, indent the checkbox.
|
|
61
|
+
*/
|
|
62
|
+
indented?: boolean;
|
|
59
63
|
}>();
|
|
60
64
|
|
|
61
65
|
const classObject = computed(() => {
|
|
@@ -64,6 +68,12 @@ const classObject = computed(() => {
|
|
|
64
68
|
};
|
|
65
69
|
});
|
|
66
70
|
|
|
71
|
+
const classObjectCheckbox = computed(() => {
|
|
72
|
+
return {
|
|
73
|
+
'mc-checkbox--indented': props.indented,
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
|
|
67
77
|
const emit = defineEmits<{
|
|
68
78
|
/**
|
|
69
79
|
* Emits when the checkbox value changes, updating the modelValue prop.
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
:class="classObjectItem"
|
|
12
12
|
:model-value="modelValue ? modelValue.includes(option.value) : undefined"
|
|
13
13
|
:disabled="option.disabled"
|
|
14
|
+
:indented="option.indented"
|
|
14
15
|
@update:model-value="(v: boolean) => onChange(v, option.value)"
|
|
15
16
|
/>
|
|
16
17
|
</div>
|
|
@@ -42,6 +43,7 @@ const props = defineProps<{
|
|
|
42
43
|
value: string;
|
|
43
44
|
disabled?: boolean;
|
|
44
45
|
isInvalid?: boolean;
|
|
46
|
+
indented?: boolean;
|
|
45
47
|
}>;
|
|
46
48
|
/**
|
|
47
49
|
* If `true`, make the form element of the group inline.
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
</template>
|
|
6
6
|
|
|
7
7
|
<script setup lang="ts">
|
|
8
|
-
import { computed } from 'vue';
|
|
8
|
+
import { computed, type VNode } from 'vue';
|
|
9
9
|
/**
|
|
10
10
|
* A Divider serves as a visual divider to separate content, providing a clear distinction between sections.
|
|
11
11
|
*/
|
|
@@ -16,6 +16,13 @@ const props = defineProps<{
|
|
|
16
16
|
fluid?: boolean;
|
|
17
17
|
}>();
|
|
18
18
|
|
|
19
|
+
defineSlots<{
|
|
20
|
+
/**
|
|
21
|
+
* Use this slot to insert the content of the container
|
|
22
|
+
*/
|
|
23
|
+
default?: VNode;
|
|
24
|
+
}>();
|
|
25
|
+
|
|
19
26
|
const classObject = computed(() => {
|
|
20
27
|
return {
|
|
21
28
|
'ml-container--fluid': props.fluid,
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
</template>
|
|
7
7
|
|
|
8
8
|
<script setup lang="ts">
|
|
9
|
-
import { computed } from 'vue';
|
|
9
|
+
import { computed, type VNode } from 'vue';
|
|
10
10
|
/**
|
|
11
11
|
* A Divider serves as a visual divider to separate content, providing a clear distinction between sections.
|
|
12
12
|
*/
|
|
@@ -32,6 +32,13 @@ const props = withDefaults(
|
|
|
32
32
|
},
|
|
33
33
|
);
|
|
34
34
|
|
|
35
|
+
defineSlots<{
|
|
36
|
+
/**
|
|
37
|
+
* Use this slot to insert the content who need a vertical divider
|
|
38
|
+
*/
|
|
39
|
+
default?: VNode;
|
|
40
|
+
}>();
|
|
41
|
+
|
|
35
42
|
const classObject = computed(() => {
|
|
36
43
|
return {
|
|
37
44
|
[`mc-divider-${props.orientation}`]: props.orientation,
|
|
@@ -40,6 +40,17 @@ const meta: Meta<typeof MDrawer> = {
|
|
|
40
40
|
<MButton ghost>Button label</MButton>
|
|
41
41
|
`,
|
|
42
42
|
},
|
|
43
|
+
argTypes: {
|
|
44
|
+
'--drawer-z-index': {
|
|
45
|
+
description: 'Customise the z-index of the drawer',
|
|
46
|
+
control: false,
|
|
47
|
+
table: {
|
|
48
|
+
category: 'Custom Properties',
|
|
49
|
+
type: { summary: 'number' },
|
|
50
|
+
defaultValue: { summary: '3' },
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
},
|
|
43
54
|
render: (args) => ({
|
|
44
55
|
components: { MDrawer, MButton },
|
|
45
56
|
setup() {
|
|
@@ -18,6 +18,17 @@ const meta: Meta<typeof MLoadingOverlay> = {
|
|
|
18
18
|
isVisible: true,
|
|
19
19
|
ariaLabel: 'Page loading',
|
|
20
20
|
},
|
|
21
|
+
argTypes: {
|
|
22
|
+
'--overlay-z-index': {
|
|
23
|
+
description: 'Customise the z-index of the overlay',
|
|
24
|
+
control: false,
|
|
25
|
+
table: {
|
|
26
|
+
category: 'Custom Properties',
|
|
27
|
+
type: { summary: 'number' },
|
|
28
|
+
defaultValue: { summary: '2' },
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
},
|
|
21
32
|
render: (args) => ({
|
|
22
33
|
components: { MLoadingOverlay },
|
|
23
34
|
setup() {
|
|
@@ -29,6 +29,17 @@ const meta: Meta<typeof MModal> = {
|
|
|
29
29
|
<MButton>Primary action</MButton>
|
|
30
30
|
`,
|
|
31
31
|
},
|
|
32
|
+
argTypes: {
|
|
33
|
+
'--modal-z-index': {
|
|
34
|
+
description: 'Customise the z-index of the modal',
|
|
35
|
+
control: false,
|
|
36
|
+
table: {
|
|
37
|
+
category: 'Custom Properties',
|
|
38
|
+
type: { summary: 'number' },
|
|
39
|
+
defaultValue: { summary: '3' },
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
},
|
|
32
43
|
render: (args) => ({
|
|
33
44
|
components: { MModal, MButton, MLink, InfoCircle32, ExternalLink24 },
|
|
34
45
|
setup() {
|