@mozaic-ds/vue 1.0.0-rc.3 → 2.2.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/LICENSE +51 -0
- package/README.md +76 -77
- package/dist/mozaic-vue.css +1 -1
- package/dist/mozaic-vue.d.ts +1718 -0
- package/dist/mozaic-vue.js +1971 -0
- package/dist/mozaic-vue.js.map +1 -0
- package/dist/mozaic-vue.umd.cjs +2 -0
- package/dist/mozaic-vue.umd.cjs.map +1 -0
- package/env.d.ts +1 -0
- package/package.json +78 -51
- package/src/components/Contributing.mdx +118 -0
- package/src/components/GettingStarted.mdx +45 -0
- package/src/components/Introduction.mdx +100 -0
- package/src/components/Support.mdx +18 -0
- package/src/components/breadcrumb/MBreadcrumb.spec.ts +105 -0
- package/src/components/breadcrumb/MBreadcrumb.stories.ts +82 -0
- package/src/components/breadcrumb/MBreadcrumb.vue +52 -55
- package/src/components/button/MButton.spec.ts +191 -0
- package/src/components/button/MButton.stories.ts +59 -0
- package/src/components/button/MButton.vue +98 -154
- package/src/components/checkbox/MCheckbox.spec.ts +104 -0
- package/src/components/checkbox/MCheckbox.stories.ts +83 -0
- package/src/components/checkbox/MCheckbox.vue +60 -101
- package/src/components/checkboxgroup/MCheckboxGroup.spec.ts +78 -0
- package/src/components/checkboxgroup/MCheckboxGroup.stories.ts +61 -0
- package/src/components/checkboxgroup/MCheckboxGroup.vue +97 -0
- package/src/components/datepicker/MDatepicker.spec.ts +95 -0
- package/src/components/datepicker/MDatepicker.stories.ts +75 -0
- package/src/components/datepicker/MDatepicker.vue +114 -0
- package/src/components/divider/MDivider.spec.ts +57 -0
- package/src/components/divider/MDivider.stories.ts +64 -0
- package/src/components/divider/MDivider.vue +56 -0
- package/src/components/drawer/MDrawer.spec.ts +100 -0
- package/src/components/drawer/MDrawer.stories.ts +128 -0
- package/src/components/drawer/MDrawer.vue +140 -0
- package/src/components/field/MField.spec.ts +166 -0
- package/src/components/field/MField.stories.ts +369 -0
- package/src/components/field/MField.vue +78 -61
- package/src/components/fieldgroup/MFieldGroup.spec.ts +165 -0
- package/src/components/fieldgroup/MFieldGroup.stories.ts +416 -0
- package/src/components/fieldgroup/MFieldGroup.vue +79 -0
- package/src/components/flag/MFlag.spec.ts +46 -0
- package/src/components/flag/MFlag.stories.ts +46 -0
- package/src/components/flag/MFlag.vue +28 -39
- package/src/components/iconbutton/MIconButton.spec.ts +108 -0
- package/src/components/iconbutton/MIconButton.stories.ts +74 -0
- package/src/components/iconbutton/MIconButton.vue +73 -0
- package/src/components/link/MLink.spec.ts +154 -0
- package/src/components/link/MLink.stories.ts +89 -0
- package/src/components/link/MLink.vue +86 -120
- package/src/components/loader/MLoader.spec.ts +104 -0
- package/src/components/loader/MLoader.stories.ts +43 -0
- package/src/components/loader/MLoader.vue +66 -55
- package/src/components/loadingoverlay/MLoadingOverlay.spec.ts +37 -0
- package/src/components/loadingoverlay/MLoadingOverlay.stories.ts +40 -0
- package/src/components/loadingoverlay/MLoadingOverlay.vue +28 -0
- package/src/components/modal/MModal.spec.ts +103 -0
- package/src/components/modal/MModal.stories.ts +127 -0
- package/src/components/modal/MModal.vue +111 -159
- package/src/components/numberbadge/MNumberBadge.spec.ts +56 -0
- package/src/components/numberbadge/MNumberBadge.stories.ts +48 -0
- package/src/components/numberbadge/MNumberBadge.vue +45 -0
- package/src/components/overlay/MOverlay.spec.ts +51 -0
- package/src/components/overlay/MOverlay.stories.ts +35 -0
- package/src/components/overlay/MOverlay.vue +27 -19
- package/src/components/pagination/MPagination.spec.ts +123 -0
- package/src/components/pagination/MPagination.stories.ts +83 -0
- package/src/components/pagination/MPagination.vue +120 -140
- package/src/components/passwordinput/MPasswordInput.spec.ts +104 -0
- package/src/components/passwordinput/MPasswordInput.stories.ts +75 -0
- package/src/components/passwordinput/MPasswordInput.vue +126 -77
- package/src/components/pincode/MPincode.spec.ts +126 -0
- package/src/components/pincode/MPincode.stories.ts +68 -0
- package/src/components/pincode/MPincode.vue +148 -0
- package/src/components/quantityselector/MQuantitySelector.spec.ts +262 -0
- package/src/components/quantityselector/MQuantitySelector.stories.ts +89 -0
- package/src/components/quantityselector/MQuantitySelector.vue +159 -148
- package/src/components/radio/MRadio.spec.ts +104 -0
- package/src/components/radio/MRadio.stories.ts +68 -0
- package/src/components/radio/MRadio.vue +56 -39
- package/src/components/radiogroup/MRadioGroup.spec.ts +54 -0
- package/src/components/radiogroup/MRadioGroup.stories.ts +61 -0
- package/src/components/radiogroup/MRadioGroup.vue +79 -0
- package/src/components/select/MSelect.spec.ts +114 -0
- package/src/components/select/MSelect.stories.ts +101 -0
- package/src/components/select/MSelect.vue +77 -119
- package/src/components/statusbadge/MStatusBadge.stories.ts +45 -0
- package/src/components/statusbadge/MStatusBadge.vue +40 -0
- package/src/components/statusbadge/MstatusBadge.spec.ts +16 -0
- package/src/components/statusdot/MStatusDot.spec.ts +51 -0
- package/src/components/statusdot/MStatusDot.stories.ts +48 -0
- package/src/components/statusdot/MStatusDot.vue +36 -0
- package/src/components/statusnotification/MStatusNotification.spec.ts +103 -0
- package/src/components/statusnotification/MStatusNotification.stories.ts +89 -0
- package/src/components/statusnotification/MStatusNotification.vue +106 -0
- package/src/components/tabs/MTabs.stories.ts +104 -0
- package/src/components/tabs/MTabs.vue +113 -0
- package/src/components/tabs/Mtabs.spec.ts +149 -0
- package/src/components/tag/MTag.spec.ts +107 -0
- package/src/components/tag/MTag.stories.ts +75 -0
- package/src/components/tag/MTag.vue +151 -0
- package/src/components/textarea/MTextArea.spec.ts +112 -0
- package/src/components/textarea/MTextArea.stories.ts +67 -0
- package/src/components/textarea/MTextArea.vue +81 -43
- package/src/components/textinput/MTextInput.spec.ts +121 -0
- package/src/components/textinput/MTextInput.stories.ts +107 -0
- package/src/components/textinput/MTextInput.vue +127 -47
- package/src/components/toggle/MToggle.spec.ts +99 -0
- package/src/components/toggle/MToggle.stories.ts +68 -0
- package/src/components/toggle/MToggle.vue +63 -103
- package/src/components/togglegroup/MToggleGroup.spec.ts +78 -0
- package/src/components/togglegroup/MToggleGroup.stories.ts +61 -0
- package/src/components/togglegroup/MToggleGroup.vue +97 -0
- package/src/components/tooltip/MTooltip.spec.ts +47 -0
- package/src/components/tooltip/MTooltip.stories.ts +59 -0
- package/src/components/tooltip/MTooltip.vue +49 -32
- package/src/components/usingIcons.mdx +35 -0
- package/src/components/usingPresets.mdx +128 -0
- package/src/main.ts +33 -0
- package/dist/demo.html +0 -1
- package/dist/mozaic-vue.adeo.css +0 -47
- package/dist/mozaic-vue.adeo.umd.js +0 -31341
- package/dist/mozaic-vue.common.js +0 -31331
- package/dist/mozaic-vue.common.js.map +0 -1
- package/dist/mozaic-vue.umd.js +0 -31342
- package/dist/mozaic-vue.umd.js.map +0 -1
- package/dist/mozaic-vue.umd.min.js +0 -4
- package/dist/mozaic-vue.umd.min.js.map +0 -1
- package/postinstall.js +0 -3
- package/src/components/accordion/MAccordion.vue +0 -128
- package/src/components/accordion/index.js +0 -7
- package/src/components/autocomplete/MAutocomplete.vue +0 -380
- package/src/components/autocomplete/index.js +0 -7
- package/src/components/badge/MBadge.vue +0 -43
- package/src/components/badge/index.js +0 -7
- package/src/components/breadcrumb/index.js +0 -7
- package/src/components/button/index.js +0 -7
- package/src/components/card/MCard.vue +0 -78
- package/src/components/card/index.js +0 -7
- package/src/components/checkbox/MCheckboxGroup.vue +0 -163
- package/src/components/checkbox/index.js +0 -12
- package/src/components/container/MContainer.vue +0 -33
- package/src/components/container/index.js +0 -7
- package/src/components/datatable/MDataTable.vue +0 -651
- package/src/components/datatable/MDataTableHeader.vue +0 -55
- package/src/components/datatable/MDataTableTop.vue +0 -35
- package/src/components/datatable/helpers.js +0 -132
- package/src/components/datatable/index.js +0 -12
- package/src/components/dropdown/MDropdown.vue +0 -317
- package/src/components/dropdown/index.js +0 -7
- package/src/components/field/index.js +0 -7
- package/src/components/fileuploader/MFileResult.vue +0 -149
- package/src/components/fileuploader/MFileUploader.vue +0 -142
- package/src/components/fileuploader/index.js +0 -7
- package/src/components/flag/index.js +0 -7
- package/src/components/heading/MHeading.vue +0 -75
- package/src/components/heading/index.js +0 -7
- package/src/components/hero/MHero.vue +0 -93
- package/src/components/hero/index.js +0 -7
- package/src/components/icon/MIcon.vue +0 -136
- package/src/components/icon/index.js +0 -7
- package/src/components/index.js +0 -44
- package/src/components/layer/MLayer.vue +0 -208
- package/src/components/layer/index.js +0 -7
- package/src/components/link/index.js +0 -7
- package/src/components/listbox/MListBox.vue +0 -146
- package/src/components/listbox/MListBoxActions.vue +0 -251
- package/src/components/listbox/index.js +0 -12
- package/src/components/loader/index.js +0 -7
- package/src/components/modal/index.js +0 -7
- package/src/components/notification/MNotification.vue +0 -110
- package/src/components/notification/index.js +0 -7
- package/src/components/optionbutton/MOptionButton.vue +0 -67
- package/src/components/optionbutton/index.js +0 -7
- package/src/components/optioncard/MOptionCard.vue +0 -132
- package/src/components/optioncard/index.js +0 -7
- package/src/components/optiongroup/MOptionGroup.vue +0 -18
- package/src/components/optiongroup/index.js +0 -7
- package/src/components/overlay/MOverlayLoader.vue +0 -43
- package/src/components/overlay/index.js +0 -12
- package/src/components/pagination/index.js +0 -7
- package/src/components/passwordinput/index.js +0 -7
- package/src/components/phonenumber/MPhoneNumber.vue +0 -398
- package/src/components/phonenumber/index.js +0 -7
- package/src/components/progressbar/MProgress.vue +0 -102
- package/src/components/progressbar/index.js +0 -7
- package/src/components/quantityselector/index.js +0 -7
- package/src/components/radio/MRadioGroup.vue +0 -111
- package/src/components/radio/index.js +0 -12
- package/src/components/ratingstars/MStarsInput.vue +0 -119
- package/src/components/ratingstars/MStarsResult.vue +0 -89
- package/src/components/ratingstars/index.js +0 -12
- package/src/components/select/index.js +0 -7
- package/src/components/stepper/MStepper.vue +0 -111
- package/src/components/stepper/index.js +0 -7
- package/src/components/tabs/MTab.vue +0 -204
- package/src/components/tabs/index.js +0 -7
- package/src/components/tags/MTag.vue +0 -175
- package/src/components/tags/index.js +0 -7
- package/src/components/textarea/index.js +0 -7
- package/src/components/textinput/MTextInputField.vue +0 -105
- package/src/components/textinput/MTextInputIcon.vue +0 -42
- package/src/components/textinput/index.js +0 -7
- package/src/components/toggle/index.js +0 -7
- package/src/components/tooltip/index.js +0 -7
- package/src/index.js +0 -63
- package/src/shims-tsx.d.ts +0 -13
- package/src/shims.vue.d.ts +0 -4
- package/src/tokens/adeo/android/colors.xml +0 -452
- package/src/tokens/adeo/android/font_dimens.xml +0 -18
- package/src/tokens/adeo/css/_variables.scss +0 -446
- package/src/tokens/adeo/css/root.scss +0 -448
- package/src/tokens/adeo/ios/StyleDictionaryColor.h +0 -460
- package/src/tokens/adeo/ios/StyleDictionaryColor.m +0 -472
- package/src/tokens/adeo/ios/StyleDictionaryColor.swift +0 -455
- package/src/tokens/adeo/ios/StyleDictionarySize.h +0 -69
- package/src/tokens/adeo/ios/StyleDictionarySize.m +0 -70
- package/src/tokens/adeo/ios/StyleDictionarySize.swift +0 -71
- package/src/tokens/adeo/js/tokens.js +0 -544
- package/src/tokens/adeo/js/tokensObject.js +0 -11733
- package/src/tokens/adeo/scss/_tokens.scss +0 -1522
- package/src/utils/mozaicClasses.js +0 -16
- package/src/utils/theme.validator.js +0 -19
- package/types/index.d.ts +0 -104
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3-vite';
|
|
2
|
+
import { action } from 'storybook/actions';
|
|
3
|
+
|
|
4
|
+
import MToggle from './MToggle.vue';
|
|
5
|
+
|
|
6
|
+
const meta: Meta<typeof MToggle> = {
|
|
7
|
+
title: 'Form Elements/Toggle',
|
|
8
|
+
component: MToggle,
|
|
9
|
+
parameters: {
|
|
10
|
+
docs: {
|
|
11
|
+
description: {
|
|
12
|
+
component:
|
|
13
|
+
'A toggle is a switch component that allows users to enable or disable a setting, representing a binary state such as on/off or active/inactive. It provides a quick and intuitive way to control preferences or system settings. Toggles are commonly used in settings menus, dark mode switches, and feature activations, offering an alternative to checkboxes for immediate visual feedback.',
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
args: {
|
|
18
|
+
id: 'ToggleId',
|
|
19
|
+
label: 'Toggle Label',
|
|
20
|
+
},
|
|
21
|
+
render: (args) => ({
|
|
22
|
+
components: { MToggle },
|
|
23
|
+
setup() {
|
|
24
|
+
const handleUpdate = action('update:modelValue');
|
|
25
|
+
|
|
26
|
+
return { args, handleUpdate };
|
|
27
|
+
},
|
|
28
|
+
template: `
|
|
29
|
+
<MToggle
|
|
30
|
+
v-bind="args"
|
|
31
|
+
@update:modelValue="handleUpdate"
|
|
32
|
+
/>
|
|
33
|
+
`,
|
|
34
|
+
}),
|
|
35
|
+
};
|
|
36
|
+
export default meta;
|
|
37
|
+
type Story = StoryObj<typeof MToggle>;
|
|
38
|
+
|
|
39
|
+
export const Default: Story = {};
|
|
40
|
+
|
|
41
|
+
export const Checked: Story = {
|
|
42
|
+
args: {
|
|
43
|
+
modelValue: true,
|
|
44
|
+
id: 'checkedId',
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const Disabled: Story = {
|
|
49
|
+
args: {
|
|
50
|
+
disabled: true,
|
|
51
|
+
id: 'disabledId',
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const Size: Story = {
|
|
56
|
+
args: {
|
|
57
|
+
id: 'sizeId',
|
|
58
|
+
size: 's',
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export const HideLabel: Story = {
|
|
63
|
+
args: {
|
|
64
|
+
id: 'hideLabelId',
|
|
65
|
+
label: undefined,
|
|
66
|
+
ariaLabel: 'Label',
|
|
67
|
+
},
|
|
68
|
+
};
|
|
@@ -1,117 +1,77 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="mc-toggle" :class="
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
2
|
+
<div class="mc-toggle" :class="classObject">
|
|
3
|
+
<label class="mc-toggle__container" :for="id">
|
|
4
|
+
<input
|
|
5
|
+
:id="id"
|
|
6
|
+
type="checkbox"
|
|
7
|
+
class="mc-toggle__input"
|
|
8
|
+
:name="name"
|
|
9
|
+
:checked="modelValue"
|
|
10
|
+
:disabled="disabled"
|
|
11
|
+
v-bind="$attrs"
|
|
12
|
+
@change="
|
|
13
|
+
emit('update:modelValue', ($event.target as HTMLInputElement).checked)
|
|
14
|
+
"
|
|
15
|
+
/>
|
|
16
|
+
<span v-if="label" :for="id" class="mc-toggle__label">
|
|
14
17
|
{{ label }}
|
|
15
|
-
<span
|
|
16
|
-
v-if="stateLabelOff && stateLabelOn"
|
|
17
|
-
class="mc-toggle__state"
|
|
18
|
-
aria-hidden="true"
|
|
19
|
-
>
|
|
20
|
-
<span class="mc-toggle__off">{{ stateLabelOff }}</span>
|
|
21
|
-
<span class="mc-toggle__on">{{ stateLabelOn }}</span>
|
|
22
|
-
</span>
|
|
23
18
|
</span>
|
|
24
19
|
</label>
|
|
25
20
|
</div>
|
|
26
21
|
</template>
|
|
27
22
|
|
|
28
|
-
<script>
|
|
29
|
-
import {
|
|
30
|
-
responsiveModifierValidators,
|
|
31
|
-
responsiveModifiers,
|
|
32
|
-
} from '../../utils/mozaicClasses';
|
|
23
|
+
<script setup lang="ts">
|
|
24
|
+
import { computed } from 'vue';
|
|
33
25
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
name
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
size
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
default: null,
|
|
67
|
-
validator: (array) =>
|
|
68
|
-
array.every((e) =>
|
|
69
|
-
responsiveModifierValidators(e, [
|
|
70
|
-
's@from-m',
|
|
71
|
-
's@from-l',
|
|
72
|
-
's@from-xl',
|
|
73
|
-
's@from-xxl',
|
|
74
|
-
'm@from-m',
|
|
75
|
-
'm@from-l',
|
|
76
|
-
'm@from-xl',
|
|
77
|
-
'm@from-xxl',
|
|
78
|
-
])
|
|
79
|
-
),
|
|
80
|
-
},
|
|
81
|
-
stateLabelOff: {
|
|
82
|
-
type: String,
|
|
83
|
-
default: null,
|
|
84
|
-
},
|
|
85
|
-
stateLabelOn: {
|
|
86
|
-
type: String,
|
|
87
|
-
default: null,
|
|
88
|
-
},
|
|
26
|
+
/**
|
|
27
|
+
* A toggle is used to choose between two possibilities and when the user needs instant feedback. It is common to use toggles when you need to show or hide content and "on/off" switch.
|
|
28
|
+
*/
|
|
29
|
+
const props = withDefaults(
|
|
30
|
+
defineProps<{
|
|
31
|
+
/**
|
|
32
|
+
* A unique identifier for the toggle, used to associate the label with the form element.
|
|
33
|
+
*/
|
|
34
|
+
id: string;
|
|
35
|
+
/**
|
|
36
|
+
* The name attribute for the toggle element, typically used for form submission.
|
|
37
|
+
*/
|
|
38
|
+
name?: string;
|
|
39
|
+
/**
|
|
40
|
+
* The text label displayed next to the toggle.
|
|
41
|
+
*/
|
|
42
|
+
label?: string;
|
|
43
|
+
/**
|
|
44
|
+
* The toggle's checked state, bound via v-model.
|
|
45
|
+
*/
|
|
46
|
+
modelValue?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Determines the size of the toggle
|
|
49
|
+
*/
|
|
50
|
+
size?: 's' | 'm';
|
|
51
|
+
/**
|
|
52
|
+
* If `true`, disables the toggle, making it non-interactive.
|
|
53
|
+
*/
|
|
54
|
+
disabled?: boolean;
|
|
55
|
+
}>(),
|
|
56
|
+
{
|
|
57
|
+
size: 's',
|
|
89
58
|
},
|
|
59
|
+
);
|
|
90
60
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
classes.push(`mc-toggle--${this.size}`);
|
|
97
|
-
}
|
|
61
|
+
const classObject = computed(() => {
|
|
62
|
+
return {
|
|
63
|
+
[`mc-toggle--${props.size}`]: props.size && props.size != 's',
|
|
64
|
+
};
|
|
65
|
+
});
|
|
98
66
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
return classes;
|
|
109
|
-
},
|
|
110
|
-
},
|
|
111
|
-
};
|
|
67
|
+
const emit = defineEmits<{
|
|
68
|
+
/**
|
|
69
|
+
* Emits when the toggle value changes, updating the modelValue prop.
|
|
70
|
+
*/
|
|
71
|
+
(on: 'update:modelValue', value: boolean): void;
|
|
72
|
+
}>();
|
|
112
73
|
</script>
|
|
113
74
|
|
|
114
|
-
<style lang="scss">
|
|
115
|
-
@
|
|
116
|
-
@import 'components/c.toggle';
|
|
75
|
+
<style lang="scss" scoped>
|
|
76
|
+
@use '@mozaic-ds/styles/components/toggle';
|
|
117
77
|
</style>
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { mount } from '@vue/test-utils';
|
|
2
|
+
import { describe, it, expect } from 'vitest';
|
|
3
|
+
import MToggleGroup from './MToggleGroup.vue';
|
|
4
|
+
import MToggle from '@/components/toggle/MToggle.vue';
|
|
5
|
+
|
|
6
|
+
describe('MToggleGroup.vue', () => {
|
|
7
|
+
it('renders toggles based on options', async () => {
|
|
8
|
+
const options = [
|
|
9
|
+
{ id: '1', label: 'Option 1', value: 'option1' },
|
|
10
|
+
{ id: '2', label: 'Option 2', value: 'option2' },
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
const wrapper = mount(MToggleGroup, {
|
|
14
|
+
props: {
|
|
15
|
+
name: 'test-name',
|
|
16
|
+
options,
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const toggles = wrapper.findAllComponents(MToggle);
|
|
21
|
+
expect(toggles.length).toBe(2);
|
|
22
|
+
|
|
23
|
+
expect(toggles[0].props('label')).toBe('Option 1');
|
|
24
|
+
expect(toggles[1].props('label')).toBe('Option 2');
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('updates modelValue when a toggle is checked', async () => {
|
|
28
|
+
const options = [
|
|
29
|
+
{ id: '1', label: 'Option 1', value: 'option1' },
|
|
30
|
+
{ id: '2', label: 'Option 2', value: 'option2' },
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
const wrapper = mount(MToggleGroup, {
|
|
34
|
+
props: {
|
|
35
|
+
name: 'test-name',
|
|
36
|
+
options,
|
|
37
|
+
modelValue: [],
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const toggle1 = wrapper.findAllComponents(MToggle)[0].find('input');
|
|
42
|
+
await toggle1.setChecked(true);
|
|
43
|
+
|
|
44
|
+
expect(wrapper.emitted('update:modelValue')).toBeTruthy();
|
|
45
|
+
expect(wrapper.emitted('update:modelValue')[0]).toEqual([['option1']]);
|
|
46
|
+
|
|
47
|
+
const toggle2 = wrapper.findAllComponents(MToggle)[1].find('input');
|
|
48
|
+
await toggle2.setChecked(true);
|
|
49
|
+
|
|
50
|
+
expect(wrapper.emitted('update:modelValue')[1]).toEqual([
|
|
51
|
+
['option1', 'option2'],
|
|
52
|
+
]);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('syncs with the v-model when initial value is passed', async () => {
|
|
56
|
+
const options = [
|
|
57
|
+
{ id: '1', label: 'Option 1', value: 'option1' },
|
|
58
|
+
{ id: '2', label: 'Option 2', value: 'option2' },
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
const wrapper = mount(MToggleGroup, {
|
|
62
|
+
props: {
|
|
63
|
+
name: 'test-name',
|
|
64
|
+
options,
|
|
65
|
+
modelValue: ['option1'],
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const toggles = wrapper.findAllComponents(MToggle);
|
|
70
|
+
expect(toggles[0].props('modelValue')).toBe(true);
|
|
71
|
+
expect(toggles[1].props('modelValue')).toBe(false);
|
|
72
|
+
|
|
73
|
+
await wrapper.setProps({ modelValue: ['option2'] });
|
|
74
|
+
|
|
75
|
+
expect(toggles[0].props('modelValue')).toBe(false);
|
|
76
|
+
expect(toggles[1].props('modelValue')).toBe(true);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3-vite';
|
|
2
|
+
import { action } from 'storybook/actions';
|
|
3
|
+
|
|
4
|
+
import MToggleGroup from './MToggleGroup.vue';
|
|
5
|
+
|
|
6
|
+
const meta: Meta<typeof MToggleGroup> = {
|
|
7
|
+
title: 'Form Elements/Toggle Group',
|
|
8
|
+
component: MToggleGroup,
|
|
9
|
+
parameters: {
|
|
10
|
+
docs: {
|
|
11
|
+
description: {
|
|
12
|
+
component:
|
|
13
|
+
'A toggle is a switch component that allows users to enable or disable a setting, representing a binary state such as on/off or active/inactive. It provides a quick and intuitive way to control preferences or system settings. Toggles are commonly used in settings menus, dark mode switches, and feature activations, offering an alternative to checkboxes for immediate visual feedback.<br><br> To put a label, requierement text, help text or to apply a valid or invalid message, the examples are available in the [Field Group section](/docs/form-elements-field-group--docs#toggle-group).',
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
args: {
|
|
18
|
+
name: 'toggleGroupName',
|
|
19
|
+
modelValue: ['toggle2'],
|
|
20
|
+
options: [
|
|
21
|
+
{
|
|
22
|
+
id: 'toggle-01',
|
|
23
|
+
label: 'Toggle Label',
|
|
24
|
+
value: 'toggle1',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
id: 'toggle-02',
|
|
28
|
+
label: 'Toggle Label',
|
|
29
|
+
value: 'toggle2',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
id: 'toggle-03',
|
|
33
|
+
label: 'Toggle Label',
|
|
34
|
+
value: 'toggle3',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
id: 'toggle-04',
|
|
38
|
+
label: 'Toggle Label',
|
|
39
|
+
value: 'toggle4',
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
render: (args) => ({
|
|
44
|
+
components: { MToggleGroup },
|
|
45
|
+
setup() {
|
|
46
|
+
const handleUpdate = action('update:modelValue');
|
|
47
|
+
|
|
48
|
+
return { args, handleUpdate };
|
|
49
|
+
},
|
|
50
|
+
template: `
|
|
51
|
+
<MToggleGroup
|
|
52
|
+
v-bind="args"
|
|
53
|
+
@update:modelValue="handleUpdate"
|
|
54
|
+
/>
|
|
55
|
+
`,
|
|
56
|
+
}),
|
|
57
|
+
};
|
|
58
|
+
export default meta;
|
|
59
|
+
type Story = StoryObj<typeof MToggleGroup>;
|
|
60
|
+
|
|
61
|
+
export const Default: Story = {};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="classObjectContainer">
|
|
3
|
+
<MToggle
|
|
4
|
+
v-for="option in options"
|
|
5
|
+
:id="option.id"
|
|
6
|
+
:key="option.id"
|
|
7
|
+
:label="option.label"
|
|
8
|
+
:is-invalid="option.isInvalid"
|
|
9
|
+
:name="name"
|
|
10
|
+
:class="classObjectItem"
|
|
11
|
+
:model-value="modelValue ? modelValue.includes(option.value) : undefined"
|
|
12
|
+
:disabled="option.disabled"
|
|
13
|
+
@update:model-value="(v: boolean) => onChange(v, option.value)"
|
|
14
|
+
/>
|
|
15
|
+
</div>
|
|
16
|
+
</template>
|
|
17
|
+
|
|
18
|
+
<script setup lang="ts">
|
|
19
|
+
import { computed, ref, watch } from 'vue';
|
|
20
|
+
import MToggle from '../toggle/MToggle.vue';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* A toggle is used to choose between two possibilities and when the user needs instant feedback. It is common to use toggles when you need to show or hide content and "on/off" switch.
|
|
24
|
+
*/
|
|
25
|
+
const props = defineProps<{
|
|
26
|
+
/**
|
|
27
|
+
* The name attribute for the toggle element, typically used for form submission.
|
|
28
|
+
*/
|
|
29
|
+
name: string;
|
|
30
|
+
/**
|
|
31
|
+
* Property used to manage the values checked by v-model
|
|
32
|
+
* (Do not use directly)
|
|
33
|
+
*/
|
|
34
|
+
modelValue?: Array<string>;
|
|
35
|
+
/**
|
|
36
|
+
* list of properties of each toggle of the toggle group
|
|
37
|
+
*/
|
|
38
|
+
options: Array<{
|
|
39
|
+
id: string;
|
|
40
|
+
label: string;
|
|
41
|
+
value: string;
|
|
42
|
+
disabled?: boolean;
|
|
43
|
+
isInvalid?: boolean;
|
|
44
|
+
size?: 's' | 'm';
|
|
45
|
+
}>;
|
|
46
|
+
/**
|
|
47
|
+
* If `true`, make the form element of the group inline.
|
|
48
|
+
*/
|
|
49
|
+
inline?: boolean;
|
|
50
|
+
}>();
|
|
51
|
+
|
|
52
|
+
const selectedValue = ref<string[]>([]);
|
|
53
|
+
|
|
54
|
+
watch(
|
|
55
|
+
() => props.modelValue,
|
|
56
|
+
(newValue) => {
|
|
57
|
+
selectedValue.value = newValue || [];
|
|
58
|
+
},
|
|
59
|
+
{ immediate: true },
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
const onChange = (isChecked: boolean, value: string) => {
|
|
63
|
+
let values = [...selectedValue.value];
|
|
64
|
+
|
|
65
|
+
if (isChecked && !values.includes(value)) {
|
|
66
|
+
values.push(value);
|
|
67
|
+
} else {
|
|
68
|
+
values = values.filter((val) => val !== value);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
emit('update:modelValue', values);
|
|
72
|
+
selectedValue.value = values;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const classObjectContainer = computed(() => {
|
|
76
|
+
return {
|
|
77
|
+
'mc-field__container--inline': props.inline,
|
|
78
|
+
};
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const classObjectItem = computed(() => {
|
|
82
|
+
return {
|
|
83
|
+
'mc-field__container--inline__item': props.inline,
|
|
84
|
+
};
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
const emit = defineEmits<{
|
|
88
|
+
/**
|
|
89
|
+
* Emits when the toggle group value changes, updating the modelValue prop.
|
|
90
|
+
*/
|
|
91
|
+
(on: 'update:modelValue', value: Array<string>): void;
|
|
92
|
+
}>();
|
|
93
|
+
</script>
|
|
94
|
+
|
|
95
|
+
<style lang="scss" scoped>
|
|
96
|
+
@use '@mozaic-ds/styles/components/field';
|
|
97
|
+
</style>
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { mount } from '@vue/test-utils';
|
|
2
|
+
import { describe, it, expect } from 'vitest';
|
|
3
|
+
import MTooltip from './MTooltip.vue';
|
|
4
|
+
|
|
5
|
+
describe('MTooltip.vue', () => {
|
|
6
|
+
const defaultProps = {
|
|
7
|
+
id: 'tooltip-1',
|
|
8
|
+
text: 'Tooltip content',
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
it('renders tooltip text', () => {
|
|
12
|
+
const wrapper = mount(MTooltip, {
|
|
13
|
+
props: { ...defaultProps },
|
|
14
|
+
slots: { default: 'Hover me' }
|
|
15
|
+
});
|
|
16
|
+
expect(wrapper.text()).toContain(defaultProps.text);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('sets aria-describedby attribute correctly', () => {
|
|
20
|
+
const wrapper = mount(MTooltip, {
|
|
21
|
+
props: { ...defaultProps }
|
|
22
|
+
});
|
|
23
|
+
const tooltipDiv = wrapper.find('.mc-tooltip');
|
|
24
|
+
expect(tooltipDiv.attributes('aria-describedby')).toBe(defaultProps.id);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('applies position class based on prop', () => {
|
|
28
|
+
const wrapper = mount(MTooltip, {
|
|
29
|
+
props: { ...defaultProps, position: 'bottom' }
|
|
30
|
+
});
|
|
31
|
+
expect(wrapper.find('.mc-tooltip').classes()).toContain('mc-tooltip--bottom');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('applies no-pointer class when pointer is false', () => {
|
|
35
|
+
const wrapper = mount(MTooltip, {
|
|
36
|
+
props: { ...defaultProps, pointer: false }
|
|
37
|
+
});
|
|
38
|
+
expect(wrapper.find('.mc-tooltip').classes()).toContain('mc-tooltip--no-pointer');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('does not apply no-pointer class when pointer is true', () => {
|
|
42
|
+
const wrapper = mount(MTooltip, {
|
|
43
|
+
props: { ...defaultProps, pointer: true }
|
|
44
|
+
});
|
|
45
|
+
expect(wrapper.find('.mc-tooltip').classes()).not.toContain('mc-tooltip--no-pointer');
|
|
46
|
+
});
|
|
47
|
+
});
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3-vite';
|
|
2
|
+
import MTooltip from './MTooltip.vue';
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof MTooltip> = {
|
|
5
|
+
title: 'Overlay/Tooltip',
|
|
6
|
+
component: MTooltip,
|
|
7
|
+
parameters: {
|
|
8
|
+
docs: {
|
|
9
|
+
description: {
|
|
10
|
+
component:
|
|
11
|
+
'A tooltip is a small, contextual message that appears when users hover over, focus on, or tap an element, providing additional information or guidance without cluttering the interface. Tooltips are commonly used to explain icons, abbreviations, or complex actions. They typically disappear automatically when the user moves away from the trigger element.',
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
args: {
|
|
16
|
+
id: 'tooltipId',
|
|
17
|
+
text: 'Keep the tooltip text concise.',
|
|
18
|
+
default: 'Tooltip on the top',
|
|
19
|
+
},
|
|
20
|
+
render: (args) => ({
|
|
21
|
+
components: { MTooltip },
|
|
22
|
+
setup() {
|
|
23
|
+
return { args };
|
|
24
|
+
},
|
|
25
|
+
template: `
|
|
26
|
+
<MTooltip v-bind="args">
|
|
27
|
+
${args.default}
|
|
28
|
+
</MTooltip>
|
|
29
|
+
`,
|
|
30
|
+
}),
|
|
31
|
+
};
|
|
32
|
+
export default meta;
|
|
33
|
+
type Story = StoryObj<typeof MTooltip>;
|
|
34
|
+
|
|
35
|
+
export const Default: Story = {};
|
|
36
|
+
|
|
37
|
+
export const Pointer: Story = {
|
|
38
|
+
args: {
|
|
39
|
+
pointer: false
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const Right: Story = {
|
|
44
|
+
args: {
|
|
45
|
+
position: 'right'
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export const Left: Story = {
|
|
50
|
+
args: {
|
|
51
|
+
position: 'left'
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const Bottom: Story = {
|
|
56
|
+
args: {
|
|
57
|
+
position: 'bottom'
|
|
58
|
+
}
|
|
59
|
+
};
|
|
@@ -1,42 +1,59 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
3
|
-
class="mc-tooltip"
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
>
|
|
7
|
-
<slot />
|
|
8
|
-
|
|
9
|
-
<span :id="id" class="mc-tooltip__content" role="tooltip">
|
|
2
|
+
<div class="tooltip-story-wrapper">
|
|
3
|
+
<div class="mc-tooltip" :class="classObject" :aria-describedby="id">
|
|
4
|
+
<slot/>
|
|
5
|
+
<span :id="id" class="mc-tooltip__content" role="tooltip">
|
|
10
6
|
{{ text }}
|
|
11
|
-
|
|
7
|
+
</span>
|
|
8
|
+
</div>
|
|
12
9
|
</div>
|
|
13
10
|
</template>
|
|
14
11
|
|
|
15
|
-
<script>
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
<script setup lang="ts">
|
|
13
|
+
import { computed } from 'vue';
|
|
14
|
+
/**
|
|
15
|
+
* A tooltip is a small, contextual message that appears when users hover over, focus on, or tap an element, providing additional information or guidance without cluttering the interface. Tooltips are commonly used to explain icons, abbreviations, or complex actions. They typically disappear automatically when the user moves away from the trigger element.
|
|
16
|
+
*/
|
|
17
|
+
const props = withDefaults(
|
|
18
|
+
defineProps<{
|
|
19
|
+
/**
|
|
20
|
+
* A unique identifier for the tooltip, used to describe the tooltip.
|
|
21
|
+
*/
|
|
22
|
+
id: string;
|
|
23
|
+
/**
|
|
24
|
+
* Content of the tooltip
|
|
25
|
+
*/
|
|
26
|
+
text: string;
|
|
27
|
+
/**
|
|
28
|
+
* Determines the position of the tooltip
|
|
29
|
+
*/
|
|
30
|
+
position?: 'top' | 'bottom' | 'left' | 'right';
|
|
31
|
+
/**
|
|
32
|
+
* if `true`, the tooltip display a pointer.
|
|
33
|
+
*/
|
|
34
|
+
pointer?: boolean;
|
|
35
|
+
}>(),
|
|
36
|
+
{
|
|
37
|
+
position: 'top',
|
|
38
|
+
pointer: true
|
|
39
|
+
},
|
|
40
|
+
);
|
|
18
41
|
|
|
19
|
-
|
|
42
|
+
defineSlots<{
|
|
43
|
+
/**
|
|
44
|
+
* The tooltip will point to the content of the slot.
|
|
45
|
+
*/
|
|
46
|
+
default: string;
|
|
47
|
+
}>();
|
|
20
48
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
type: String,
|
|
28
|
-
required: true,
|
|
29
|
-
},
|
|
30
|
-
position: {
|
|
31
|
-
type: String,
|
|
32
|
-
default: 'top',
|
|
33
|
-
validator: (value) => ['top', 'right', 'bottom', 'left'].includes(value),
|
|
34
|
-
},
|
|
35
|
-
},
|
|
36
|
-
};
|
|
49
|
+
const classObject = computed(() => {
|
|
50
|
+
return {
|
|
51
|
+
[`mc-tooltip--${props.position}`]: props.position,
|
|
52
|
+
'mc-tooltip--no-pointer': !props.pointer,
|
|
53
|
+
};
|
|
54
|
+
});
|
|
37
55
|
</script>
|
|
38
56
|
|
|
39
|
-
<style lang="scss">
|
|
40
|
-
@
|
|
41
|
-
@import 'components/_c.tooltip';
|
|
57
|
+
<style lang="scss" scoped>
|
|
58
|
+
@use '@mozaic-ds/styles/components/tooltip';
|
|
42
59
|
</style>
|