@mozaic-ds/vue 2.13.0 → 2.14.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.
Files changed (90) hide show
  1. package/dist/mozaic-vue.css +1 -1
  2. package/dist/mozaic-vue.d.ts +1088 -378
  3. package/dist/mozaic-vue.js +2662 -1854
  4. package/dist/mozaic-vue.js.map +1 -1
  5. package/dist/mozaic-vue.umd.cjs +5 -5
  6. package/dist/mozaic-vue.umd.cjs.map +1 -1
  7. package/package.json +4 -4
  8. package/src/components/actionlistbox/MActionListbox.spec.ts +53 -59
  9. package/src/components/actionlistbox/MActionListbox.stories.ts +22 -1
  10. package/src/components/actionlistbox/MActionListbox.vue +91 -28
  11. package/src/components/actionlistbox/README.md +15 -0
  12. package/src/components/breadcrumb/MBreadcrumb.vue +5 -0
  13. package/src/components/button/README.md +4 -0
  14. package/src/components/checkbox/README.md +2 -0
  15. package/src/components/divider/README.md +4 -0
  16. package/src/components/iconbutton/MIconButton.stories.ts +12 -0
  17. package/src/components/iconbutton/MIconButton.vue +13 -1
  18. package/src/components/iconbutton/README.md +27 -0
  19. package/src/components/loader/README.md +2 -0
  20. package/src/components/navigationindicator/MNavigationIndicator.spec.ts +152 -0
  21. package/src/components/navigationindicator/MNavigationIndicator.stories.ts +41 -0
  22. package/src/components/navigationindicator/MNavigationIndicator.vue +132 -0
  23. package/src/components/navigationindicator/README.md +37 -0
  24. package/src/components/pageheader/MPageHeader.spec.ts +142 -0
  25. package/src/components/pageheader/MPageHeader.stories.ts +125 -0
  26. package/src/components/pageheader/MPageHeader.vue +133 -0
  27. package/src/components/pageheader/README.md +46 -0
  28. package/src/components/popover/MPopover.spec.ts +106 -0
  29. package/src/components/popover/MPopover.stories.ts +126 -0
  30. package/src/components/popover/MPopover.vue +131 -0
  31. package/src/components/popover/README.md +42 -0
  32. package/src/components/radio/README.md +2 -0
  33. package/src/components/select/MSelect.spec.ts +2 -1
  34. package/src/components/select/MSelect.vue +30 -25
  35. package/src/components/sidebar/MSidebar.const.ts +6 -0
  36. package/src/components/sidebar/MSidebar.spec.ts +110 -0
  37. package/src/components/sidebar/MSidebar.stories.ts +108 -0
  38. package/src/components/sidebar/MSidebar.vue +124 -0
  39. package/src/components/sidebar/README.md +59 -0
  40. package/src/components/sidebar/stories/DefaultCase.stories.vue +120 -0
  41. package/src/components/sidebar/stories/README.md +27 -0
  42. package/src/components/sidebar/stories/WithExpandOnly.stories.vue +112 -0
  43. package/src/components/sidebar/stories/WithProfileInfoOnly.stories.vue +119 -0
  44. package/src/components/sidebar/stories/WithSingleLevel.stories.vue +98 -0
  45. package/src/components/sidebar/use-floating-item.composable.ts +135 -0
  46. package/src/components/sidebar/use-floating-item.spec.ts +251 -0
  47. package/src/components/sidebarexpandableitem/MSidebarExpandableItem.spec.ts +151 -0
  48. package/src/components/sidebarexpandableitem/MSidebarExpandableItem.vue +113 -0
  49. package/src/components/sidebarexpandableitem/README.md +36 -0
  50. package/src/components/sidebarfooter/MSidebarFooter.spec.ts +276 -0
  51. package/src/components/sidebarfooter/MSidebarFooter.vue +201 -0
  52. package/src/components/sidebarfooter/README.md +52 -0
  53. package/src/components/sidebarfooter/_MSidebarFooterMenu.vue +64 -0
  54. package/src/components/sidebarheader/MSidebarHeader.vue +36 -0
  55. package/src/components/sidebarheader/README.md +31 -0
  56. package/src/components/sidebarnavitem/MSidebarNavItem.spec.ts +127 -0
  57. package/src/components/sidebarnavitem/MSidebarNavItem.vue +113 -0
  58. package/src/components/sidebarnavitem/README.md +56 -0
  59. package/src/components/sidebarshortcutitem/MSidebarShortcutItem.spec.ts +59 -0
  60. package/src/components/sidebarshortcutitem/MSidebarShortcutItem.vue +52 -0
  61. package/src/components/sidebarshortcutitem/README.md +32 -0
  62. package/src/components/sidebarshortcuts/MSidebarShortcuts.spec.ts +87 -0
  63. package/src/components/sidebarshortcuts/MSidebarShortcuts.vue +101 -0
  64. package/src/components/sidebarshortcuts/README.md +36 -0
  65. package/src/components/statusbadge/README.md +12 -0
  66. package/src/components/textinput/MTextInput.stories.ts +13 -1
  67. package/src/components/textinput/MTextInput.vue +12 -0
  68. package/src/components/textinput/README.md +3 -1
  69. package/src/components/tile/MTile.spec.ts +61 -0
  70. package/src/components/tile/MTile.stories.ts +102 -0
  71. package/src/components/tile/MTile.vue +68 -0
  72. package/src/components/tile/README.md +19 -0
  73. package/src/components/tileclickable/MTileClickable.spec.ts +130 -0
  74. package/src/components/tileclickable/MTileClickable.stories.ts +60 -0
  75. package/src/components/tileclickable/MTileClickable.vue +106 -0
  76. package/src/components/tileclickable/README.md +30 -0
  77. package/src/components/tileexpandable/MTileExpandable.spec.ts +121 -0
  78. package/src/components/tileexpandable/MTileExpandable.stories.ts +50 -0
  79. package/src/components/tileexpandable/MTileExpandable.vue +131 -0
  80. package/src/components/tileexpandable/README.md +36 -0
  81. package/src/components/tileselectable/MTileSelectable.spec.ts +177 -0
  82. package/src/components/tileselectable/MTileSelectable.stories.ts +55 -0
  83. package/src/components/tileselectable/MTileSelectable.vue +142 -0
  84. package/src/components/tileselectable/README.md +44 -0
  85. package/src/components/toaster/README.md +1 -1
  86. package/src/components/tooltip/MTooltip.vue +5 -0
  87. package/src/components/tooltip/README.md +16 -1
  88. package/src/main.ts +12 -2
  89. package/src/utils/use-is-mobile.composable.ts +20 -0
  90. package/src/utils/use-is-mobile.spec.ts +70 -0
@@ -0,0 +1,133 @@
1
+ <template>
2
+ <div
3
+ :class="{
4
+ 'mc-page-header': true,
5
+ 'mc-page-header--with-shadow': shadow,
6
+ }"
7
+ >
8
+ <div class="mc-page-header__top-wrapper">
9
+ <div class="mc-page-header__top-content">
10
+ <MIconButton
11
+ v-if="backButton"
12
+ ghost
13
+ aria-label="Back button"
14
+ @click="emit('back')"
15
+ >
16
+ <template #icon>
17
+ <ArrowBack24 />
18
+ </template>
19
+ </MIconButton>
20
+
21
+ <div class="mc-page-header__content-wrapper">
22
+ <span class="mc-page-header__title">
23
+ {{ title }}
24
+ </span>
25
+
26
+ <div
27
+ v-if="status || extraInfo"
28
+ class="mc-page-header__info-wrapper"
29
+ >
30
+ <MStatusBadge
31
+ v-if="statusLabel && status"
32
+ :label="statusLabel"
33
+ :status="status"
34
+ />
35
+
36
+ <span v-if="extraInfo" class="mc-page-header__extra-info">
37
+ {{ extraInfo }}
38
+ </span>
39
+ </div>
40
+
41
+ <slot name="content" />
42
+ </div>
43
+ </div>
44
+
45
+ <div class="mc-page-header__actions-wrapper">
46
+ <MIconButton
47
+ class="mc-page-header__burger-menu"
48
+ ghost
49
+ aria-label="Burger menu"
50
+ @click="emit('toggle-menu')"
51
+ >
52
+ <template #icon>
53
+ <Menu24 />
54
+ </template>
55
+ </MIconButton>
56
+
57
+ <div class="mc-page-header__actions-content">
58
+ <slot name="actions"/>
59
+ </div>
60
+ </div>
61
+ </div>
62
+
63
+ <div class="mc-page-header__tabs">
64
+ <slot name="tabs"/>
65
+ </div>
66
+ </div>
67
+ </template>
68
+
69
+ <script setup lang="ts">
70
+ import { type VNode } from 'vue';
71
+ import { ArrowBack24, Menu24 } from '@mozaic-ds/icons-vue';
72
+ import MIconButton from '../iconbutton/MIconButton.vue';
73
+ import MStatusBadge from '../statusbadge/MStatusBadge.vue';
74
+ /**
75
+ * The Page Header is a fundamental component that structures the top part of an interface, serving as a cognitive anchor point for users. It establishes page context, facilitates navigation, and provides the main actions available within the current scope.
76
+ */
77
+ defineProps<{
78
+ /**
79
+ * Main title displayed in the page header.
80
+ */
81
+ title: string;
82
+ /**
83
+ * Enables a drop shadow under the page header.
84
+ */
85
+ shadow?: boolean;
86
+ /**
87
+ * Displays a back icon button in the header.
88
+ */
89
+ backButton?: boolean;
90
+ /**
91
+ * Component status.
92
+ */
93
+ status?: 'info' | 'success' | 'warning' | 'error' | 'neutral';
94
+ /**
95
+ * Label text displayed inside the status badge.
96
+ */
97
+ statusLabel?: string;
98
+ /**
99
+ * Additional information text shown below the title.
100
+ */
101
+ extraInfo?: string;
102
+ }>();
103
+
104
+ const emit = defineEmits<{
105
+ /**
106
+ * Emits when the back button is clicked.
107
+ */
108
+ (on: 'back'): void;
109
+ /**
110
+ * Emits when the burger menu button is clicked.
111
+ */
112
+ (on: 'toggle-menu'): void;
113
+ }>();
114
+
115
+ defineSlots<{
116
+ /**
117
+ * Use this slot to insert action items in the top content.
118
+ */
119
+ actions?: VNode;
120
+ /**
121
+ * Use this slot to insert any content below the Page Header top content.
122
+ */
123
+ content?: VNode;
124
+ /**
125
+ * Use this slot to insert a tab in the header.
126
+ */
127
+ tabs?: VNode;
128
+ }>();
129
+ </script>
130
+
131
+ <style lang="scss" scoped>
132
+ @use '@mozaic-ds/styles/components/page-header';
133
+ </style>
@@ -0,0 +1,46 @@
1
+ # MPageHeader
2
+
3
+ The Page Header is a fundamental component that structures the top part of an interface, serving as a cognitive anchor point for users. It establishes page context, facilitates navigation, and provides the main actions available within the current scope.
4
+
5
+
6
+ ## Props
7
+
8
+ | Name | Description | Type | Default |
9
+ | --- | --- | --- | --- |
10
+ | `title*` | Main title displayed in the page header. | `string` | - |
11
+ | `shadow` | Enables a drop shadow under the page header. | `boolean` | - |
12
+ | `backButton` | Displays a back icon button in the header. | `boolean` | - |
13
+ | `status` | Component status. | `"info"` `"warning"` `"error"` `"success"` `"neutral"` | - |
14
+ | `statusLabel` | Label text displayed inside the status badge. | `string` | - |
15
+ | `extraInfo` | Additional information text shown below the title. | `string` | - |
16
+
17
+ ## Slots
18
+
19
+ | Name | Description |
20
+ | --- | --- |
21
+ | `actions` | Use this slot to insert action items in the top content. |
22
+ | `content` | Use this slot to insert any content below the Page Header top content. |
23
+ | `tabs` | Use this slot to insert a tab in the header. |
24
+
25
+ ## Events
26
+
27
+ | Name | Description | Type |
28
+ | --- | --- | --- |
29
+ | `back` | Emits when the back button is clicked. | [] |
30
+ | `toggle-menu` | Emits when the burger menu button is clicked. | [] |
31
+
32
+ ## Dependencies
33
+
34
+ ### Depends on
35
+
36
+ - [MIconButton](../iconbutton)
37
+ - [MStatusBadge](../statusbadge)
38
+
39
+ ### Graph
40
+
41
+ ```mermaid
42
+ graph TD;
43
+ MPageHeader --> MIconButton
44
+ MPageHeader --> MStatusBadge
45
+ style MPageHeader fill:#008240,stroke:#333,stroke-width:4px
46
+ ```
@@ -0,0 +1,106 @@
1
+ import { h } from 'vue';
2
+ import { mount } from '@vue/test-utils';
3
+ import { describe, it, expect } from 'vitest';
4
+ import MPopover from './MPopover.vue';
5
+ import MIconButton from '../iconbutton/MIconButton.vue';
6
+
7
+ describe('MPopover.vue', () => {
8
+ it('applies classes based on props', () => {
9
+ const wrapper = mount(MPopover, {
10
+ props: {
11
+ appearance: 'inverse',
12
+ position: 'right',
13
+ pointer: false,
14
+ size: 'l',
15
+ },
16
+ });
17
+
18
+ const rootDiv = wrapper.find('.mc-popover');
19
+ expect(rootDiv.exists()).toBe(true);
20
+ expect(rootDiv.classes()).toContain('mc-popover');
21
+ expect(rootDiv.classes()).toContain('mc-popover--inverse');
22
+ expect(rootDiv.classes()).toContain('mc-popover--right');
23
+ expect(rootDiv.classes()).toContain('mc-popover--no-pointer');
24
+ expect(rootDiv.classes()).toContain('mc-popover--l');
25
+ });
26
+
27
+ it('sets aria-labelledby and aria-describedby when title/description provided', () => {
28
+ const wrapper = mount(MPopover, {
29
+ props: { title: 'My title', description: 'My description' },
30
+ });
31
+
32
+ const wrapperEl = wrapper.find('.mc-popover__wrapper');
33
+ const id = wrapperEl.attributes('id');
34
+ expect(id).toBeTruthy();
35
+ expect(wrapperEl.attributes('aria-labelledby')).toBe(`${id}-title`);
36
+ expect(wrapperEl.attributes('aria-describedby')).toBe(`${id}-description`);
37
+ });
38
+
39
+ it('renders title and description', () => {
40
+ const wrapper = mount(MPopover, {
41
+ props: { title: 'T', description: 'D' },
42
+ });
43
+
44
+ const wrapperEl = wrapper.find('.mc-popover__wrapper');
45
+ const id = wrapperEl.attributes('id');
46
+
47
+ const title = wrapper.find(`#${id}-title`);
48
+ const description = wrapper.find(`#${id}-description`);
49
+ expect(title.exists()).toBe(true);
50
+ expect(title.text()).toBe('T');
51
+ expect(description.exists()).toBe(true);
52
+ expect(description.text()).toBe('D');
53
+ });
54
+
55
+ it('renders default slot content', () => {
56
+ const wrapper = mount(MPopover, {
57
+ slots: { default: '<div class="slot-content">Hello</div>' },
58
+ });
59
+
60
+ expect(wrapper.find('.slot-content').exists()).toBe(true);
61
+ expect(wrapper.find('.slot-content').text()).toBe('Hello');
62
+ });
63
+
64
+ it('renders footer slot when provided', () => {
65
+ const wrapper = mount(MPopover, {
66
+ slots: { footer: '<button class="footer-button">OK</button>' },
67
+ });
68
+
69
+ const footer = wrapper.find('.mc-popover__footer');
70
+ expect(footer.exists()).toBe(true);
71
+ const button = footer.find('button');
72
+ expect(button.exists()).toBe(true);
73
+ expect(button.text()).toBe('OK');
74
+ });
75
+
76
+ it('renders close button when closable is true and binds id', () => {
77
+ const wrapper = mount(MPopover, { props: { closable: true } });
78
+
79
+ const closeButton = wrapper.findComponent(MIconButton);
80
+ expect(closeButton.exists()).toBe(true);
81
+
82
+ const wrapperEl = wrapper.find('.mc-popover__wrapper');
83
+ const id = wrapperEl.attributes('id');
84
+ expect(closeButton.attributes('popovertarget')).toBe(id);
85
+ expect(closeButton.attributes('aria-label')).toBe('Close button');
86
+ });
87
+
88
+ it('activator slot receives id and can bind popovertarget', () => {
89
+ const wrapper = mount(MPopover, {
90
+ slots: {
91
+ activator: (slotProps: { id: string }) =>
92
+ h(
93
+ 'button',
94
+ { popovertarget: slotProps.id, class: 'activator' },
95
+ 'Open',
96
+ ),
97
+ },
98
+ });
99
+
100
+ const wrapperEl = wrapper.find('.mc-popover__wrapper');
101
+ const id = wrapperEl.attributes('id');
102
+ const activator = wrapper.find('.activator');
103
+ expect(activator.exists()).toBe(true);
104
+ expect(activator.attributes('popovertarget')).toBe(id);
105
+ });
106
+ });
@@ -0,0 +1,126 @@
1
+ import type { Meta, StoryObj } from '@storybook/vue3-vite';
2
+ import { action } from 'storybook/actions';
3
+
4
+ import MPopover from './MPopover.vue';
5
+ import MButton from '../button/MButton.vue';
6
+ import MLink from '../link/MLink.vue';
7
+ import { ExternalLink24 } from '@mozaic-ds/icons-vue';
8
+
9
+ const meta: Meta<typeof MPopover> = {
10
+ title: 'Overlay/Popover',
11
+ component: MPopover,
12
+ tags: ['v2'],
13
+ parameters: {
14
+ layout: 'centered',
15
+ docs: {
16
+ description: {
17
+ component:
18
+ 'A popover is a small overlay that appears above other content, typically triggered by a user interaction such as clicking or hovering over an element. It is used to display contextual information, additional actions, or interactive content without navigating away from the main interface. Popovers often include a title, description, and action buttons, and they automatically close when clicking outside or selecting an action.',
19
+ },
20
+ },
21
+ },
22
+ args: {
23
+ title: 'Title',
24
+ description: 'Description',
25
+ footer: `
26
+ <MButton
27
+ size="s"
28
+ aria-label="Popover action button"
29
+ >
30
+ Button label
31
+ </MButton>
32
+ `,
33
+ activator: `
34
+ <MButton :popovertarget="id">
35
+ Activator
36
+ </MButton>
37
+ `,
38
+ },
39
+ render: (args) => ({
40
+ components: { MPopover, MButton, MLink, ExternalLink24 },
41
+ setup() {
42
+ const handleAction = action('action');
43
+
44
+ return { args, handleAction };
45
+ },
46
+ template: `
47
+ <MPopover
48
+ v-bind="args"
49
+ @action="handleAction"
50
+ >
51
+ <template v-if="${'footer' in args}" v-slot:footer>${args.footer}</template>
52
+ <template #activator="{ id }" v-slot:activator>${args.activator}</template>
53
+ </MPopover>
54
+ `,
55
+ }),
56
+ };
57
+ export default meta;
58
+ type Story = StoryObj<typeof MPopover>;
59
+
60
+ export const Default: Story = {};
61
+
62
+ export const Inverse = {
63
+ args: {
64
+ appearance: 'inverse',
65
+ footer: `
66
+ <MLink appearance="inverse" href="#" size="s" icon-position="right">
67
+ Stand-alone link
68
+ <template #icon><ExternalLink24 /></template>
69
+ </MLink>
70
+ <MButton appearance="inverse" size="s" aria-label="Popover action button">
71
+ Button label
72
+ </MButton>
73
+ `,
74
+ },
75
+ };
76
+
77
+ export const ValidationOnly = {
78
+ args: {
79
+ footer: `
80
+ <MButton size="s" aria-label="Popover action button">
81
+ Button label
82
+ </MButton>
83
+ `,
84
+ },
85
+ };
86
+
87
+ export const TwoOptions = {
88
+ args: {
89
+ footer: `
90
+ <MButton size="s" outlined aria-label="Popover action button">
91
+ Button label
92
+ </MButton>
93
+ <MButton size="s" aria-label="Popover action button">
94
+ Button label
95
+ </MButton>
96
+ `,
97
+ },
98
+ };
99
+
100
+ export const Link = {
101
+ args: {
102
+ footer: `
103
+ <MLink href="#" size="s" icon-position="right">
104
+ Stand-alone link
105
+ <template #icon><ExternalLink24 /></template>
106
+ </MLink>
107
+ <MButton
108
+ size="s"
109
+ aria-label="Popover action button"
110
+ >
111
+ Button label
112
+ </MButton>
113
+ `,
114
+ },
115
+ };
116
+
117
+ export const Navigation = {
118
+ args: {
119
+ footer: `
120
+ <MLink href="#" size="s" icon-position="right">
121
+ Stand-alone link
122
+ <template #icon><ExternalLink24 /></template>
123
+ </MLink>
124
+ `,
125
+ },
126
+ };
@@ -0,0 +1,131 @@
1
+ <template>
2
+ <div
3
+ :class="{
4
+ 'mc-popover': true,
5
+ [`mc-popover--${appearance}`]: true,
6
+ [`mc-popover--${position}`]: true,
7
+ 'mc-popover--no-pointer': !pointer,
8
+ [`mc-popover--${size}`]: true,
9
+ }"
10
+ >
11
+ <div
12
+ :id="id"
13
+ class="mc-popover__wrapper"
14
+ popover
15
+ :aria-labelledby="title && `${id}-title`"
16
+ :aria-describedby="description && `${id}-description`"
17
+ >
18
+ <div class="mc-popover__content">
19
+ <div v-if="title || description" class="mc-popover__headings">
20
+ <p v-if="title" :id="`${id}-title`" class="mc-popover__title">
21
+ {{ title }}
22
+ </p>
23
+ <p
24
+ v-if="description"
25
+ :id="`${id}-description`"
26
+ class="mc-popover__description"
27
+ >
28
+ {{ description }}
29
+ </p>
30
+ </div>
31
+
32
+ <div v-if="$slots.default">
33
+ <slot />
34
+ </div>
35
+
36
+ <MIconButton
37
+ v-if="closable"
38
+ ghost
39
+ :popovertarget="id"
40
+ :appearance="appearance"
41
+ icon-position="only"
42
+ aria-label="Close button"
43
+ class="mc-popover__close"
44
+ >
45
+ <template #icon>
46
+ <Cross20 />
47
+ </template>
48
+ </MIconButton>
49
+
50
+ <footer v-if="$slots.footer" class="mc-popover__footer">
51
+ <slot name="footer" />
52
+ </footer>
53
+ </div>
54
+ </div>
55
+ </div>
56
+
57
+ <slot name="activator" v-bind="{ id }" />
58
+ </template>
59
+
60
+ <script setup lang="ts">
61
+ import { useId, type VNode } from 'vue';
62
+ import { Cross20 } from '@mozaic-ds/icons-vue';
63
+ import MIconButton from '../iconbutton/MIconButton.vue';
64
+ /**
65
+ * A popover is a small overlay that appears above other content, typically triggered by a user interaction such as clicking or hovering over an element. It is used to display contextual information, additional actions, or interactive content without navigating away from the main interface. Popovers often include a title, description, and action buttons, and they automatically close when clicking outside or selecting an action.
66
+ */
67
+ withDefaults(
68
+ defineProps<{
69
+ /**
70
+ * Allows to define the popover appearance.
71
+ */
72
+ appearance?: 'standard' | 'inverse';
73
+ /**
74
+ * Defines the preferred position of the popover relative to its activator.
75
+ */
76
+ position?: 'top' | 'right' | 'bottom' | 'left';
77
+ /**
78
+ * Controls the visibility of the popover pointer (arrow).
79
+ */
80
+ pointer?: boolean;
81
+ /**
82
+ * Sets the overall size of the popover.
83
+ */
84
+ size?: 's' | 'm' | 'l';
85
+ /**
86
+ * Displays a close icon button inside the popover.
87
+ * Clicking the button will close the popover.
88
+ */
89
+ closable?: boolean;
90
+ /**
91
+ * Title displayed at the top of the popover.
92
+ */
93
+ title?: string;
94
+ /**
95
+ * Supplementary text displayed below the title.
96
+ */
97
+ description?: string;
98
+ }>(),
99
+ {
100
+ closable: true,
101
+ pointer: true,
102
+ appearance: 'standard',
103
+ position: 'top',
104
+ size: 's',
105
+ },
106
+ );
107
+
108
+ defineSlots<{
109
+ /**
110
+ * Main content of the popover.
111
+ */
112
+ default?: () => VNode[];
113
+ /**
114
+ * Activator element that triggers the popover.
115
+ * Must contain a single <button> or element with [type="button"] attribute.
116
+ * Receives the popover `id` as a slot prop and must bind it
117
+ * to the `popovertarget` attribute.
118
+ */
119
+ activator?: (props: { id: string }) => VNode[];
120
+ /**
121
+ * Use this slot to insert buttons or link in the footer.
122
+ */
123
+ footer?: VNode;
124
+ }>();
125
+
126
+ const id = useId();
127
+ </script>
128
+
129
+ <style lang="scss" scoped>
130
+ @use '@mozaic-ds/styles/components/popover';
131
+ </style>
@@ -0,0 +1,42 @@
1
+ # MPopover
2
+
3
+ A popover is a small overlay that appears above other content, typically triggered by a user interaction such as clicking or hovering over an element. It is used to display contextual information, additional actions, or interactive content without navigating away from the main interface. Popovers often include a title, description, and action buttons, and they automatically close when clicking outside or selecting an action.
4
+
5
+
6
+ ## Props
7
+
8
+ | Name | Description | Type | Default |
9
+ | --- | --- | --- | --- |
10
+ | `appearance` | Allows to define the popover appearance. | `"standard"` `"inverse"` | `"standard"` |
11
+ | `position` | Defines the preferred position of the popover relative to its activator. | `"bottom"` `"top"` `"left"` `"right"` | `"top"` |
12
+ | `pointer` | Controls the visibility of the popover pointer (arrow). | `boolean` | `true` |
13
+ | `size` | Sets the overall size of the popover. | `"s"` `"m"` `"l"` | `"s"` |
14
+ | `closable` | Displays a close icon button inside the popover.
15
+ Clicking the button will close the popover. | `boolean` | `true` |
16
+ | `title` | Title displayed at the top of the popover. | `string` | - |
17
+ | `description` | Supplementary text displayed below the title. | `string` | - |
18
+
19
+ ## Slots
20
+
21
+ | Name | Description |
22
+ | --- | --- |
23
+ | `default` | Main content of the popover. |
24
+ | `activator` | Activator element that triggers the popover.
25
+ Must contain a single <button> or element with [type="button"] attribute.
26
+ Receives the popover `id` as a slot prop and must bind it
27
+ to the `popovertarget` attribute. |
28
+ | `footer` | Use this slot to insert buttons or link in the footer. |
29
+
30
+ ## Dependencies
31
+
32
+ ### Depends on
33
+
34
+ - [MIconButton](../iconbutton)
35
+
36
+ ### Graph
37
+
38
+ ```mermaid
39
+ graph TD;
40
+ MPopover --> MIconButton
41
+ style MPopover fill:#008240,stroke:#333,stroke-width:4px
42
+ ```
@@ -25,11 +25,13 @@ A radio button is a selection control that allows users to choose a single optio
25
25
  ### Used By
26
26
 
27
27
  - [MRadioGroup](../radiogroup)
28
+ - [MTileSelectable](../tileselectable)
28
29
 
29
30
  ### Graph
30
31
 
31
32
  ```mermaid
32
33
  graph TD;
33
34
  MRadioGroup --> MRadio
35
+ MTileSelectable --> MRadio
34
36
  style MRadio fill:#008240,stroke:#333,stroke-width:4px
35
37
  ```
@@ -92,9 +92,10 @@ describe('Select.vue', () => {
92
92
  },
93
93
  });
94
94
 
95
+ const selectWrapper = wrapper.find('.mc-select');
95
96
  const select = wrapper.find('select');
96
97
 
97
- expect(select.classes()).toContain('mc-select--s');
98
+ expect(selectWrapper.classes()).toContain('mc-select--s');
98
99
 
99
100
  expect(select.classes()).toContain('is-invalid');
100
101
  });
@@ -1,29 +1,35 @@
1
1
  <template>
2
- <select
3
- :id="id"
4
- class="mc-select"
5
- :name="name"
6
- :value="modelValue"
7
- :class="classObject"
8
- :disabled="disabled"
9
- v-bind="$attrs"
10
- @change="
11
- emit('update:modelValue', ($event.target as HTMLSelectElement).value)
12
- "
2
+ <div :class="{
3
+ 'mc-select': true,
4
+ [`mc-select--${size}`]: props.size && props.size != 'm',
5
+ }"
13
6
  >
14
- <option v-if="placeholder" value="" disabled>
15
- -- {{ placeholder }} --
16
- </option>
17
- <option
18
- v-for="(option, index) in options"
19
- :key="index"
20
- :value="option.value"
21
- v-bind="option.attributes"
22
- :disabled="option.disabled"
7
+ <select
8
+ :id="id"
9
+ class="mc-select__control"
10
+ :class="classObject"
11
+ :name="name"
12
+ :value="modelValue"
13
+ :disabled="disabled"
14
+ v-bind="$attrs"
15
+ @change="
16
+ emit('update:modelValue', ($event.target as HTMLSelectElement).value)
17
+ "
23
18
  >
24
- {{ option.text }}
25
- </option>
26
- </select>
19
+ <option v-if="placeholder" value="" disabled>
20
+ -- {{ placeholder }} --
21
+ </option>
22
+ <option
23
+ v-for="(option, index) in options"
24
+ :key="index"
25
+ :value="option.value"
26
+ v-bind="option.attributes"
27
+ :disabled="option.disabled"
28
+ >
29
+ {{ option.text }}
30
+ </option>
31
+ </select>
32
+ </div>
27
33
  </template>
28
34
 
29
35
  <script setup lang="ts">
@@ -84,8 +90,7 @@ const props = withDefaults(
84
90
 
85
91
  const classObject = computed(() => {
86
92
  return {
87
- [`mc-select--${props.size}`]: props.size && props.size != 'm',
88
- 'mc-select--readonly': props.readonly,
93
+ 'mc-select__control--readonly': props.readonly,
89
94
  'is-invalid': props.isInvalid,
90
95
  };
91
96
  });
@@ -0,0 +1,6 @@
1
+ import type { InjectionKey, Ref } from 'vue';
2
+
3
+ export const EXPANDED_SIDEBAR_KEY = Symbol() as InjectionKey<Ref<boolean>>;
4
+ export const TOGGLE_SIDEBAR_KEY = Symbol() as InjectionKey<() => void>;
5
+ export const SUB_ITEM_KEY = Symbol() as InjectionKey<boolean>;
6
+ export const STACKED_SHORTCUTS_KEY = Symbol() as InjectionKey<boolean>;