@weni/unnnic-system 3.11.3-alpha.3 → 3.12.1-alpha.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/CHANGELOG.md +8 -0
- package/dist/components/AudioRecorder/AudioHandler.vue.d.ts +0 -17
- package/dist/components/AudioRecorder/AudioRecorder.vue.d.ts +0 -34
- package/dist/components/Card/Card.vue.d.ts +0 -17
- package/dist/components/Card/CardStatusesContainer.vue.d.ts +0 -17
- package/dist/components/Card/SimpleCard.vue.d.ts +0 -17
- package/dist/components/Card/TitleCard.vue.d.ts +0 -17
- package/dist/components/CardInformation/CardInformation.vue.d.ts +0 -17
- package/dist/components/ChartBar/ChartBar.vue.d.ts +0 -17
- package/dist/components/ChartLine/ChartLine.vue.d.ts +0 -17
- package/dist/components/ChatText/ChatText.vue.d.ts +0 -17
- package/dist/components/ChatsMessage/ChatsMessage.vue.d.ts +0 -17
- package/dist/components/DataArea/DataArea.vue.d.ts +0 -17
- package/dist/components/DateFilter/DateFilter.vue.d.ts +3 -3
- package/dist/components/FormElement/FormElement.vue.d.ts +2 -2
- package/dist/components/Input/Input.vue.d.ts +3 -3
- package/dist/components/Label/Label.vue.d.ts +1 -1
- package/dist/components/Label/Label.vue.d.ts.map +1 -1
- package/dist/components/ModalNext/ModalNext.vue.d.ts +3 -3
- package/dist/components/MoodRating/MoodRating.vue.d.ts +0 -17
- package/dist/components/Slider/Slider.vue.d.ts +0 -17
- package/dist/components/Switch/Switch.vue.d.ts +1 -1
- package/dist/components/Tab/Tab.vue.d.ts +0 -17
- package/dist/components/TextArea/TextArea.vue.d.ts +3 -3
- package/dist/components/Toast/Toast.vue.d.ts.map +1 -1
- package/dist/components/ToolTip/ToolTip.vue.d.ts +0 -17
- package/dist/components/ToolTip/ToolTip.vue.d.ts.map +1 -1
- package/dist/components/ui/dialog/DialogContent.vue.d.ts.map +1 -1
- package/dist/components/ui/drawer/DrawerContent.vue.d.ts +1 -0
- package/dist/components/ui/drawer/DrawerContent.vue.d.ts.map +1 -1
- package/dist/components/ui/popover/PopoverContent.vue.d.ts.map +1 -1
- package/dist/components/ui/popover/PopoverTrigger.vue.d.ts.map +1 -1
- package/dist/components/ui/tooltip/Tooltip.vue.d.ts.map +1 -1
- package/dist/components/ui/tooltip/TooltipContent.vue.d.ts.map +1 -1
- package/dist/components/ui/tooltip/TooltipTrigger.vue.d.ts.map +1 -1
- package/dist/components/ui/tooltip/index.d.ts +0 -1
- package/dist/components/ui/tooltip/index.d.ts.map +1 -1
- package/dist/{es-99b102dc.mjs → es-38bd0c9c.mjs} +1 -1
- package/dist/{index-c20fa852.mjs → index-561a4027.mjs} +6304 -6265
- package/dist/lib/layer-manager.d.ts +16 -0
- package/dist/lib/layer-manager.d.ts.map +1 -0
- package/dist/{pt-br-b17e69b4.mjs → pt-br-14a3c647.mjs} +1 -1
- package/dist/style.css +1 -1
- package/dist/unnnic.mjs +1 -1
- package/dist/unnnic.umd.js +33 -33
- package/package.json +1 -1
- package/src/components/Alert/__tests__/__snapshots__/Alert.spec.js.snap +1 -1
- package/src/components/Toast/Toast.vue +4 -1
- package/src/components/ToolTip/ToolTip.vue +31 -36
- package/src/components/ToolTip/__tests__/ToolTip.spec.js +0 -6
- package/src/components/index.ts +19 -19
- package/src/components/ui/dialog/DialogContent.vue +6 -0
- package/src/components/ui/drawer/DrawerContent.vue +12 -2
- package/src/components/ui/popover/PopoverContent.vue +4 -0
- package/src/components/ui/popover/PopoverTrigger.vue +5 -1
- package/src/components/ui/tooltip/Tooltip.vue +9 -3
- package/src/components/ui/tooltip/TooltipContent.vue +3 -2
- package/src/components/ui/tooltip/TooltipTrigger.vue +4 -0
- package/src/components/ui/tooltip/index.ts +0 -1
- package/src/lib/layer-manager.ts +84 -0
- package/src/stories/DrawerNext.stories.js +1 -0
- package/src/stories/LayerManager.docs.mdx +40 -0
- package/src/stories/LayerManager.stories.js +364 -0
- package/dist/components/ui/tooltip/TooltipProvider.vue.d.ts +0 -19
- package/dist/components/ui/tooltip/TooltipProvider.vue.d.ts.map +0 -1
- package/src/components/ui/tooltip/TooltipProvider.vue +0 -15
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
exports[`UnnnicAlert.vue > matches the snapshot 1`] = `
|
|
4
4
|
"<transition-stub data-v-c3231c18="" name="toast-slide" appear="true" persisted="false" css="true" data-testid="toast-transition">
|
|
5
|
-
<aside data-v-c3231c18="" class="unnnic-toast unnnic-toast--success" role="status" aria-live="polite" data-testid="toast">
|
|
5
|
+
<aside data-v-c3231c18="" class="unnnic-toast unnnic-toast--success" role="status" aria-live="polite" data-testid="toast" style="z-index: 1405;">
|
|
6
6
|
<section data-v-c3231c18="" class="unnnic-toast__content" data-testid="toast-content">
|
|
7
7
|
<header data-v-c3231c18="" class="unnnic-toast__header" data-testid="toast-header"><span data-v-26446d8e="" data-v-c3231c18="" class="unnnic-icon material-symbols-rounded unnnic-icon-scheme--green-500 unnnic-icon-size--ant unnnic-icon__size--ant" data-testid="toast-type-icon" translate="no">check_circle</span>
|
|
8
8
|
<h3 data-v-c3231c18="" class="unnnic-toast__title" data-testid="toast-title">Test Alert</h3><span data-v-26446d8e="" data-v-c3231c18="" class="unnnic-icon material-symbols-rounded unnnic-icon-scheme--neutral-dark unnnic-icon-size--ant unnnic-icon__size--ant unnnic--clickable unnnic-toast__close" data-testid="toast-close-icon" translate="no">close</span>
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
:role="validType === 'error' ? 'alert' : 'status'"
|
|
12
12
|
:aria-live="validType === 'error' ? 'assertive' : 'polite'"
|
|
13
13
|
data-testid="toast"
|
|
14
|
+
:style="{ zIndex: toastZIndex }"
|
|
14
15
|
>
|
|
15
16
|
<section
|
|
16
17
|
class="unnnic-toast__content"
|
|
@@ -74,6 +75,7 @@ import { ref, computed, onMounted, onUnmounted } from 'vue';
|
|
|
74
75
|
|
|
75
76
|
import UnnnicIcon from '@/components/Icon.vue';
|
|
76
77
|
import UnnnicButton from '@/components/Button/Button.vue';
|
|
78
|
+
import { useLayerZIndex } from '@/lib/layer-manager';
|
|
77
79
|
|
|
78
80
|
import type { ToastProps, ToastEmits } from './types';
|
|
79
81
|
import type { SchemeColor } from '@/types/scheme-colors';
|
|
@@ -113,6 +115,8 @@ const typeConfig = computed(() => {
|
|
|
113
115
|
return configMap[validType.value];
|
|
114
116
|
});
|
|
115
117
|
|
|
118
|
+
const toastZIndex = useLayerZIndex('toast');
|
|
119
|
+
|
|
116
120
|
const handleClose = () => {
|
|
117
121
|
isVisible.value = false;
|
|
118
122
|
emit('close');
|
|
@@ -156,7 +160,6 @@ onUnmounted(() => {
|
|
|
156
160
|
position: fixed;
|
|
157
161
|
bottom: $unnnic-space-4;
|
|
158
162
|
right: $unnnic-space-4;
|
|
159
|
-
z-index: 9999;
|
|
160
163
|
|
|
161
164
|
display: flex;
|
|
162
165
|
align-items: flex-end;
|
|
@@ -1,50 +1,45 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
>
|
|
8
|
-
<
|
|
9
|
-
|
|
10
|
-
</TooltipTrigger>
|
|
2
|
+
<Tooltip
|
|
3
|
+
:disabled="!(enabled || forceOpen)"
|
|
4
|
+
:open="forceOpen || undefined"
|
|
5
|
+
data-testid="tooltip-wrapper"
|
|
6
|
+
>
|
|
7
|
+
<TooltipTrigger data-testid="tooltip-trigger">
|
|
8
|
+
<slot />
|
|
9
|
+
</TooltipTrigger>
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
<TooltipContent
|
|
12
|
+
:class="['unnnic-tooltip-label', `unnnic-tooltip-label-${side}`]"
|
|
13
|
+
:style="{ maxWidth: maxWidth }"
|
|
14
|
+
:side="side"
|
|
15
|
+
data-testid="tooltip-content"
|
|
16
|
+
>
|
|
17
|
+
<template v-if="enableHtml">
|
|
18
|
+
<!-- eslint-disable-next-line vue/no-v-html -->
|
|
19
|
+
<section
|
|
20
|
+
v-html="text"
|
|
21
|
+
data-testid="tooltip-html-content"
|
|
22
|
+
></section>
|
|
23
|
+
</template>
|
|
24
|
+
<template
|
|
25
|
+
v-for="(line, index) in text.split('\n')"
|
|
26
|
+
v-else
|
|
27
|
+
:key="index"
|
|
17
28
|
>
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
></section>
|
|
24
|
-
</template>
|
|
25
|
-
<template
|
|
26
|
-
v-for="(line, index) in text.split('\n')"
|
|
27
|
-
v-else
|
|
28
|
-
:key="index"
|
|
29
|
-
>
|
|
30
|
-
{{ line }}
|
|
31
|
-
<br />
|
|
32
|
-
</template>
|
|
33
|
-
</TooltipContent>
|
|
34
|
-
</Tooltip>
|
|
35
|
-
</TooltipProvider>
|
|
29
|
+
{{ line }}
|
|
30
|
+
<br />
|
|
31
|
+
</template>
|
|
32
|
+
</TooltipContent>
|
|
33
|
+
</Tooltip>
|
|
36
34
|
</template>
|
|
37
35
|
|
|
38
36
|
<script>
|
|
39
|
-
import { Tooltip,
|
|
40
|
-
import TooltipContent from '../ui/tooltip/TooltipContent.vue';
|
|
41
|
-
import TooltipTrigger from '../ui/tooltip/TooltipTrigger.vue';
|
|
37
|
+
import { Tooltip, TooltipContent, TooltipTrigger } from '../ui/tooltip';
|
|
42
38
|
|
|
43
39
|
export default {
|
|
44
40
|
name: 'UnnnicTooltip',
|
|
45
41
|
components: {
|
|
46
42
|
Tooltip,
|
|
47
|
-
TooltipProvider,
|
|
48
43
|
TooltipTrigger,
|
|
49
44
|
TooltipContent,
|
|
50
45
|
},
|
|
@@ -236,12 +236,6 @@ describe('ToolTip', () => {
|
|
|
236
236
|
});
|
|
237
237
|
|
|
238
238
|
describe('Component Structure', () => {
|
|
239
|
-
it('should have TooltipProvider component', () => {
|
|
240
|
-
expect(wrapper.findComponent({ name: 'TooltipProvider' }).exists()).toBe(
|
|
241
|
-
true,
|
|
242
|
-
);
|
|
243
|
-
});
|
|
244
|
-
|
|
245
239
|
it('should have Tooltip component', () => {
|
|
246
240
|
expect(wrapper.findComponent({ name: 'Tooltip' }).exists()).toBe(true);
|
|
247
241
|
});
|
package/src/components/index.ts
CHANGED
|
@@ -93,6 +93,12 @@ import DataTable from './DataTable/index.vue';
|
|
|
93
93
|
import Chip from './Chip/Chip.vue';
|
|
94
94
|
import Toast from './Toast/Toast.vue';
|
|
95
95
|
import { toast } from './Toast/ToastManager';
|
|
96
|
+
import Popover from './ui/popover/Popover.vue';
|
|
97
|
+
import PopoverContent from './ui/popover/PopoverContent.vue';
|
|
98
|
+
import PopoverTrigger from './ui/popover/PopoverTrigger.vue';
|
|
99
|
+
import PopoverFooter from './ui/popover/PopoverFooter.vue';
|
|
100
|
+
import TemplatePreview from './TemplatePreview/TemplatePreview.vue';
|
|
101
|
+
import TemplatePreviewModal from './TemplatePreview/TemplatePreviewModal.vue';
|
|
96
102
|
import Tabs from './ui/tabs/Tabs.vue';
|
|
97
103
|
import TabsList from './ui/tabs/TabsList.vue';
|
|
98
104
|
import TabsTrigger from './ui/tabs/TabsTrigger.vue';
|
|
@@ -103,12 +109,6 @@ import {
|
|
|
103
109
|
SegmentedControlTrigger,
|
|
104
110
|
SegmentedControlContent,
|
|
105
111
|
} from './ui/segmented-control';
|
|
106
|
-
import Popover from './ui/popover/Popover.vue';
|
|
107
|
-
import PopoverContent from './ui/popover/PopoverContent.vue';
|
|
108
|
-
import PopoverTrigger from './ui/popover/PopoverTrigger.vue';
|
|
109
|
-
import PopoverFooter from './ui/popover/PopoverFooter.vue';
|
|
110
|
-
import TemplatePreview from './TemplatePreview/TemplatePreview.vue';
|
|
111
|
-
import TemplatePreviewModal from './TemplatePreview/TemplatePreviewModal.vue';
|
|
112
112
|
import PageHeader from './PageHeader/PageHeader.vue';
|
|
113
113
|
import Dialog from './ui/dialog/Dialog.vue';
|
|
114
114
|
import DialogContent from './ui/dialog/DialogContent.vue';
|
|
@@ -236,11 +236,11 @@ export const components: ComponentsMap = {
|
|
|
236
236
|
unnnicTabsList: TabsList,
|
|
237
237
|
unnnicTabsTrigger: TabsTrigger,
|
|
238
238
|
unnnicTabsContent: TabsContent,
|
|
239
|
-
unnnicPageHeader: PageHeader,
|
|
240
239
|
unnnicSegmentedControl: SegmentedControl,
|
|
241
240
|
unnnicSegmentedControlList: SegmentedControlList,
|
|
242
241
|
unnnicSegmentedControlTrigger: SegmentedControlTrigger,
|
|
243
242
|
unnnicSegmentedControlContent: SegmentedControlContent,
|
|
243
|
+
unnnicPageHeader: PageHeader,
|
|
244
244
|
unnnicDialog: Dialog,
|
|
245
245
|
unnnicDialogContent: DialogContent,
|
|
246
246
|
unnnicDialogFooter: DialogFooter,
|
|
@@ -353,6 +353,12 @@ export const unnnicSelectTime = SelectTime as VueComponent;
|
|
|
353
353
|
export const unnnicChip = Chip;
|
|
354
354
|
export const unnnicToast = Toast;
|
|
355
355
|
export const unnnicToastManager = toast;
|
|
356
|
+
export const unnnicPopover = Popover;
|
|
357
|
+
export const unnnicPopoverContent = PopoverContent;
|
|
358
|
+
export const unnnicPopoverTrigger = PopoverTrigger;
|
|
359
|
+
export const unnnicPopoverFooter = PopoverFooter;
|
|
360
|
+
export const unnnicTemplatePreview = TemplatePreview as VueComponent;
|
|
361
|
+
export const unnnicTemplatePreviewModal = TemplatePreviewModal as VueComponent;
|
|
356
362
|
export const unnnicTabs = Tabs;
|
|
357
363
|
export const unnnicTabsList = TabsList;
|
|
358
364
|
export const unnnicTabsTrigger = TabsTrigger;
|
|
@@ -361,12 +367,6 @@ export const unnnicSegmentedControl = SegmentedControl;
|
|
|
361
367
|
export const unnnicSegmentedControlList = SegmentedControlList;
|
|
362
368
|
export const unnnicSegmentedControlTrigger = SegmentedControlTrigger;
|
|
363
369
|
export const unnnicSegmentedControlContent = SegmentedControlContent;
|
|
364
|
-
export const unnnicPopover = Popover;
|
|
365
|
-
export const unnnicPopoverContent = PopoverContent;
|
|
366
|
-
export const unnnicPopoverTrigger = PopoverTrigger;
|
|
367
|
-
export const unnnicPopoverFooter = PopoverFooter;
|
|
368
|
-
export const unnnicTemplatePreview = TemplatePreview as VueComponent;
|
|
369
|
-
export const unnnicTemplatePreviewModal = TemplatePreviewModal as VueComponent;
|
|
370
370
|
export const unnnicPageHeader = PageHeader;
|
|
371
371
|
export const unnnicDialog = Dialog;
|
|
372
372
|
export const unnnicDialogContent = DialogContent;
|
|
@@ -479,6 +479,12 @@ export const UnnnicSelectTime = SelectTime as VueComponent;
|
|
|
479
479
|
export const UnnnicChip = Chip;
|
|
480
480
|
export const UnnnicToast = Toast;
|
|
481
481
|
export const UnnnicToastManager = toast;
|
|
482
|
+
export const UnnnicPopover = Popover;
|
|
483
|
+
export const UnnnicPopoverContent = PopoverContent;
|
|
484
|
+
export const UnnnicPopoverTrigger = PopoverTrigger;
|
|
485
|
+
export const UnnnicPopoverFooter = PopoverFooter;
|
|
486
|
+
export const UnnnicTemplatePreview = TemplatePreview as VueComponent;
|
|
487
|
+
export const UnnnicTemplatePreviewModal = TemplatePreviewModal as VueComponent;
|
|
482
488
|
export const UnnnicTabs = Tabs;
|
|
483
489
|
export const UnnnicTabsList = TabsList;
|
|
484
490
|
export const UnnnicTabsTrigger = TabsTrigger;
|
|
@@ -487,12 +493,6 @@ export const UnnnicSegmentedControl = SegmentedControl;
|
|
|
487
493
|
export const UnnnicSegmentedControlList = SegmentedControlList;
|
|
488
494
|
export const UnnnicSegmentedControlTrigger = SegmentedControlTrigger;
|
|
489
495
|
export const UnnnicSegmentedControlContent = SegmentedControlContent;
|
|
490
|
-
export const UnnnicPopover = Popover;
|
|
491
|
-
export const UnnnicPopoverContent = PopoverContent;
|
|
492
|
-
export const UnnnicPopoverTrigger = PopoverTrigger;
|
|
493
|
-
export const UnnnicPopoverFooter = PopoverFooter;
|
|
494
|
-
export const UnnnicTemplatePreview = TemplatePreview as VueComponent;
|
|
495
|
-
export const UnnnicTemplatePreviewModal = TemplatePreviewModal as VueComponent;
|
|
496
496
|
export const UnnnicPageHeader = PageHeader;
|
|
497
497
|
export const UnnnicDialog = Dialog;
|
|
498
498
|
export const UnnnicDialogContent = DialogContent;
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
useForwardPropsEmits,
|
|
11
11
|
} from 'reka-ui';
|
|
12
12
|
import { cn } from '@/lib/utils';
|
|
13
|
+
import { useLayerZIndex } from '@/lib/layer-manager';
|
|
13
14
|
|
|
14
15
|
defineOptions({
|
|
15
16
|
name: 'UnnnicDialogContent',
|
|
@@ -35,6 +36,9 @@ const delegatedProps = reactiveOmit(props, 'class', 'parentClass');
|
|
|
35
36
|
|
|
36
37
|
const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
|
37
38
|
|
|
39
|
+
const overlayZIndex = useLayerZIndex('modal', { offset: -2 });
|
|
40
|
+
const modalZIndex = useLayerZIndex('modal');
|
|
41
|
+
|
|
38
42
|
const contentClasses = computed(() =>
|
|
39
43
|
cn(
|
|
40
44
|
'unnnic-dialog-content',
|
|
@@ -58,12 +62,14 @@ const ConditionalWrapper: Component = (_, { slots }) => {
|
|
|
58
62
|
<DialogPortal>
|
|
59
63
|
<DialogOverlay
|
|
60
64
|
class="unnnic-dialog-overlay data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0"
|
|
65
|
+
:style="{ zIndex: overlayZIndex }"
|
|
61
66
|
/>
|
|
62
67
|
|
|
63
68
|
<ConditionalWrapper>
|
|
64
69
|
<DialogContent
|
|
65
70
|
v-bind="forwarded"
|
|
66
71
|
:class="contentClasses"
|
|
72
|
+
:style="{ zIndex: modalZIndex }"
|
|
67
73
|
>
|
|
68
74
|
<slot />
|
|
69
75
|
</DialogContent>
|
|
@@ -5,6 +5,7 @@ import { reactiveOmit } from '@vueuse/core';
|
|
|
5
5
|
import { useForwardPropsEmits } from 'reka-ui';
|
|
6
6
|
import { DrawerContent, DrawerPortal } from 'vaul-vue';
|
|
7
7
|
import { cn } from '@/lib/utils';
|
|
8
|
+
import { useLayerZIndex } from '@/lib/layer-manager';
|
|
8
9
|
import DrawerOverlay from './DrawerOverlay.vue';
|
|
9
10
|
|
|
10
11
|
defineOptions({
|
|
@@ -20,6 +21,7 @@ const props = withDefaults(
|
|
|
20
21
|
}
|
|
21
22
|
>(),
|
|
22
23
|
{
|
|
24
|
+
class: undefined,
|
|
23
25
|
size: 'medium',
|
|
24
26
|
showOverlay: true,
|
|
25
27
|
},
|
|
@@ -28,11 +30,16 @@ const emits = defineEmits<DialogContentEmits>();
|
|
|
28
30
|
|
|
29
31
|
const delegatedProps = reactiveOmit(props, 'class');
|
|
30
32
|
const forwardedProps = useForwardPropsEmits(delegatedProps, emits);
|
|
33
|
+
|
|
34
|
+
const layerZIndex = useLayerZIndex('drawer');
|
|
31
35
|
</script>
|
|
32
36
|
|
|
33
37
|
<template>
|
|
34
38
|
<DrawerPortal>
|
|
35
|
-
<DrawerOverlay
|
|
39
|
+
<DrawerOverlay
|
|
40
|
+
v-if="showOverlay"
|
|
41
|
+
:style="{ zIndex: layerZIndex - 2 }"
|
|
42
|
+
/>
|
|
36
43
|
<DrawerContent
|
|
37
44
|
v-bind="forwardedProps"
|
|
38
45
|
:class="
|
|
@@ -42,7 +49,10 @@ const forwardedProps = useForwardPropsEmits(delegatedProps, emits);
|
|
|
42
49
|
props.class,
|
|
43
50
|
)
|
|
44
51
|
"
|
|
45
|
-
:style="{
|
|
52
|
+
:style="{
|
|
53
|
+
'--initial-transform': 'calc(100% + 8px)',
|
|
54
|
+
zIndex: layerZIndex,
|
|
55
|
+
}"
|
|
46
56
|
>
|
|
47
57
|
<slot />
|
|
48
58
|
</DrawerContent>
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
'bg-popover text-popover-foreground outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
|
10
10
|
)
|
|
11
11
|
"
|
|
12
|
+
:style="{ zIndex: popoverZIndex }"
|
|
12
13
|
>
|
|
13
14
|
<section :class="`unnnic-popover__content ${props.class || ''}`">
|
|
14
15
|
<component
|
|
@@ -34,6 +35,7 @@ import { computed, useSlots } from 'vue';
|
|
|
34
35
|
import { reactiveOmit } from '@vueuse/core';
|
|
35
36
|
import { PopoverContent, PopoverPortal, useForwardPropsEmits } from 'reka-ui';
|
|
36
37
|
import { cn } from '@/lib/utils';
|
|
38
|
+
import { useLayerZIndex } from '@/lib/layer-manager';
|
|
37
39
|
|
|
38
40
|
defineOptions({
|
|
39
41
|
inheritAttrs: false,
|
|
@@ -61,6 +63,8 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
|
|
61
63
|
|
|
62
64
|
const slots = useSlots();
|
|
63
65
|
|
|
66
|
+
const popoverZIndex = useLayerZIndex('popover');
|
|
67
|
+
|
|
64
68
|
const getComponentName = (vnode: VNode): string | undefined => {
|
|
65
69
|
const componentType = vnode.type as { name?: string; __name?: string };
|
|
66
70
|
return componentType?.name || componentType?.__name;
|
|
@@ -14,10 +14,14 @@ const props = defineProps<PopoverTriggerProps>();
|
|
|
14
14
|
</PopoverTrigger>
|
|
15
15
|
</template>
|
|
16
16
|
|
|
17
|
-
<style scoped>
|
|
17
|
+
<style lang="scss" scoped>
|
|
18
18
|
.unnnic-popover-trigger {
|
|
19
19
|
border: none;
|
|
20
20
|
background: transparent;
|
|
21
21
|
padding: 0;
|
|
22
|
+
|
|
23
|
+
& > * {
|
|
24
|
+
width: 100%;
|
|
25
|
+
}
|
|
22
26
|
}
|
|
23
27
|
</style>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import type { TooltipRootEmits, TooltipRootProps } from 'reka-ui';
|
|
3
3
|
import { TooltipRoot, useForwardPropsEmits } from 'reka-ui';
|
|
4
|
+
import { TooltipProvider } from 'reka-ui';
|
|
4
5
|
|
|
5
6
|
const props = defineProps<TooltipRootProps>();
|
|
6
7
|
const emits = defineEmits<TooltipRootEmits>();
|
|
@@ -9,7 +10,12 @@ const forwarded = useForwardPropsEmits(props, emits);
|
|
|
9
10
|
</script>
|
|
10
11
|
|
|
11
12
|
<template>
|
|
12
|
-
<
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
<TooltipProvider
|
|
14
|
+
:delayDuration="100"
|
|
15
|
+
disableClosingTrigger
|
|
16
|
+
>
|
|
17
|
+
<TooltipRoot v-bind="forwarded">
|
|
18
|
+
<slot />
|
|
19
|
+
</TooltipRoot>
|
|
20
|
+
</TooltipProvider>
|
|
15
21
|
</template>
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
useForwardPropsEmits,
|
|
10
10
|
} from 'reka-ui';
|
|
11
11
|
import { cn } from '@/lib/utils';
|
|
12
|
+
import { useLayerZIndex } from '@/lib/layer-manager';
|
|
12
13
|
|
|
13
14
|
defineOptions({
|
|
14
15
|
inheritAttrs: false,
|
|
@@ -26,6 +27,7 @@ const emits = defineEmits<TooltipContentEmits>();
|
|
|
26
27
|
const delegatedProps = reactiveOmit(props, 'class');
|
|
27
28
|
|
|
28
29
|
const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
|
30
|
+
const tooltipZIndex = useLayerZIndex('tooltip');
|
|
29
31
|
</script>
|
|
30
32
|
|
|
31
33
|
<template>
|
|
@@ -39,6 +41,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
|
|
39
41
|
props.class,
|
|
40
42
|
)
|
|
41
43
|
"
|
|
44
|
+
:style="{ zIndex: tooltipZIndex }"
|
|
42
45
|
>
|
|
43
46
|
<slot />
|
|
44
47
|
|
|
@@ -51,8 +54,6 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
|
|
51
54
|
@use '@/assets/scss/unnnic' as *;
|
|
52
55
|
|
|
53
56
|
.tooltip__content {
|
|
54
|
-
z-index: 10001;
|
|
55
|
-
|
|
56
57
|
background-color: $unnnic-color-gray-900;
|
|
57
58
|
color: $unnnic-color-white;
|
|
58
59
|
border-radius: $unnnic-radius-1;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { onBeforeUnmount, onMounted, ref, type Ref } from 'vue';
|
|
2
|
+
|
|
3
|
+
export const layerScale = {
|
|
4
|
+
hide: -1,
|
|
5
|
+
base: 0,
|
|
6
|
+
drawer: 1000,
|
|
7
|
+
modal: 1100,
|
|
8
|
+
popover: 1200,
|
|
9
|
+
tooltip: 1300,
|
|
10
|
+
toast: 1400,
|
|
11
|
+
} as const;
|
|
12
|
+
|
|
13
|
+
export type LayerToken = keyof typeof layerScale;
|
|
14
|
+
|
|
15
|
+
const DEFAULT_STEP = 5;
|
|
16
|
+
|
|
17
|
+
const counters: Record<LayerToken, number> = {
|
|
18
|
+
hide: 0,
|
|
19
|
+
base: 0,
|
|
20
|
+
drawer: 0,
|
|
21
|
+
modal: 0,
|
|
22
|
+
popover: 0,
|
|
23
|
+
tooltip: 0,
|
|
24
|
+
toast: 0,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
interface Allocation {
|
|
28
|
+
id: symbol;
|
|
29
|
+
type: LayerToken;
|
|
30
|
+
value: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const allocations = new Map<symbol, Allocation>();
|
|
34
|
+
|
|
35
|
+
function acquire(type: LayerToken): Allocation {
|
|
36
|
+
const id = Symbol('layer');
|
|
37
|
+
counters[type] = (counters[type] ?? 0) + 1;
|
|
38
|
+
const value = layerScale[type] + counters[type] * DEFAULT_STEP;
|
|
39
|
+
const allocation: Allocation = { id, type, value };
|
|
40
|
+
allocations.set(id, allocation);
|
|
41
|
+
return allocation;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function release(id: symbol) {
|
|
45
|
+
const allocation = allocations.get(id);
|
|
46
|
+
if (!allocation) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
allocations.delete(id);
|
|
51
|
+
const current = Math.max((counters[allocation.type] ?? 1) - 1, 0);
|
|
52
|
+
counters[allocation.type] = current;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface LayerZIndexOptions {
|
|
56
|
+
offset?: number;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function useLayerZIndex(
|
|
60
|
+
type: LayerToken = 'base',
|
|
61
|
+
options?: LayerZIndexOptions,
|
|
62
|
+
): Ref<number> {
|
|
63
|
+
const initialValue = layerScale[type] + (options?.offset ?? 0);
|
|
64
|
+
const zIndex = ref(initialValue);
|
|
65
|
+
|
|
66
|
+
let allocationId: symbol | null = null;
|
|
67
|
+
|
|
68
|
+
const allocate = () => {
|
|
69
|
+
const allocation = acquire(type);
|
|
70
|
+
allocationId = allocation.id;
|
|
71
|
+
zIndex.value = allocation.value + (options?.offset ?? 0);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
onMounted(allocate);
|
|
75
|
+
|
|
76
|
+
onBeforeUnmount(() => {
|
|
77
|
+
if (allocationId) {
|
|
78
|
+
release(allocationId);
|
|
79
|
+
allocationId = null;
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
return zIndex;
|
|
84
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Meta } from '@storybook/blocks';
|
|
2
|
+
|
|
3
|
+
<Meta title="Utilities/Layer Manager/Overview" />
|
|
4
|
+
|
|
5
|
+
# Layer Manager Overview
|
|
6
|
+
|
|
7
|
+
The layer manager exists to keep every teleported component (dialogs, drawers, popovers, tooltips, toasts, etc.) in a predictable stacking order without sprinkling arbitrary `z-index: 9999` rules across the codebase. Defining semantic bands (drawer, modal, popover, tooltip, toast) and allocating values automatically whenever a component mounts. [Reference](https://v1.chakra-ui.com/docs/components/recipes/z-index)
|
|
8
|
+
|
|
9
|
+
## Why avoid manual z-index values?
|
|
10
|
+
|
|
11
|
+
- **Unbounded numbers** – once one component uses `z-index: 9999`, the next overlay needs more. This escalates quickly and still breaks when stacking contexts change.
|
|
12
|
+
- **Stacking contexts** – `position`, `transform`, `opacity`, `filter`, and even flex or grid children can create new contexts that ignore global z-index rules. Portaled content plus a manager side-steps this entirely.
|
|
13
|
+
- **Shared ownership** – dialogs, drawers, dropdowns, and popovers often live in different packages. A single allocator means each feature does not need to know what values others are using.
|
|
14
|
+
|
|
15
|
+
## How it works here
|
|
16
|
+
|
|
17
|
+
1. **Tokens, not numbers** – components request a token such as `modal`, `popover`, or `tooltip`. The manager maps those tokens to a base band (e.g., modals start at 1200, popovers at 1400).
|
|
18
|
+
2. **Auto-increment** – every time a component mounts, it receives the next value in its band so nested dialogs or infinite toasts still stack correctly.
|
|
19
|
+
3. **Scoped offsets** – overlays that belong to the same surface (e.g., `DialogOverlay` vs `DialogContent`) simply call `useLayerZIndex` with a small negative offset so the overlay sits just beneath the content that opened it.
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
const modalZ = useLayerZIndex('modal');
|
|
23
|
+
const overlayZ = useLayerZIndex('modal', { offset: -2 });
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Benefits
|
|
27
|
+
|
|
28
|
+
- **Deterministic ordering** – open a drawer, then a popover, then a dialog, then a tooltip and the visual order will always follow the semantic bands.
|
|
29
|
+
- **Safer refactors** – tokens can be remapped (e.g., raise the entire `tooltip` band) without touching every component.
|
|
30
|
+
|
|
31
|
+
## When to override
|
|
32
|
+
|
|
33
|
+
In rare cases you might still need a custom `z-index`. Prefer to:
|
|
34
|
+
|
|
35
|
+
1. Add a new token in the layer manager if the surface fits the existing pattern (e.g., `tour`).
|
|
36
|
+
2. Only apply inline overrides for truly one-off cases, and document why the global manager does not work there.
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
Use the `Layer Manager` stories in Storybook to verify real interactions (dialog + tooltip/popover, drawer + dialog, nested dialogs, dialog + toast) whenever you add a new teleported component.
|
|
40
|
+
|