Skip to content

Commit acf6842

Browse files
committed
feat(Tooltip!): replace floating-ui tooltip with radix-vue tooltip
1 parent cea8dae commit acf6842

File tree

8 files changed

+197
-65
lines changed

8 files changed

+197
-65
lines changed

packages/themes/src/morpheme/_tooltip.scss

+75-23
Original file line numberDiff line numberDiff line change
@@ -15,39 +15,91 @@
1515
--v-tooltip-white-color: var(--color-gray-700);
1616
--v-tooltip-white-border: 1px solid var(--color-gray-100);
1717
--v-tooltip-white-arrow-border-color: var(--color-gray-50);
18-
}
1918

20-
.v-popper {
21-
display: inline-block;
19+
// default: black
20+
--v-tooltip-bg-color: var(--v-tooltip-black-bg-color);
21+
--v-tooltip-color: var(--v-tooltip-black-color);
2222
}
2323

24-
.v-popper--theme-tooltip-black {
25-
.v-popper__inner {
26-
background: var(--v-tooltip-black-bg-color);
27-
color: var(--v-tooltip-black-color);
28-
padding: var(--v-tooltip-padding-y) var(--v-tooltip-padding-x);
24+
.v-tooltip {
25+
&-content {
2926
border-radius: var(--v-tooltip-border-radius);
27+
padding: var(--v-tooltip-padding-y) var(--v-tooltip-padding-x);
3028
font-size: var(--v-tooltip-font-size);
31-
max-width: var(--v-tooltip-max-width);
29+
line-height: 1;
30+
color: var(--v-tooltip-color);
31+
background-color: var(--v-tooltip-bg-color);
32+
box-shadow:
33+
hsl(206 22% 7% / 35%) 0px 10px 38px -10px,
34+
hsl(206 22% 7% / 20%) 0px 10px 20px -15px;
35+
user-select: none;
36+
animation-duration: 400ms;
37+
animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
38+
will-change: transform, opacity;
39+
40+
&[data-state="delayed-open"][data-side="top"] {
41+
animation-name: slideDownAndFade;
42+
}
43+
&[data-state="delayed-open"][data-side="right"] {
44+
animation-name: slideLeftAndFade;
45+
}
46+
&[data-state="delayed-open"][data-side="bottom"] {
47+
animation-name: slideUpAndFade;
48+
}
49+
&[data-state="delayed-open"][data-side="left"] {
50+
animation-name: slideRightAndFade;
51+
}
52+
}
53+
54+
&-arrow {
55+
fill: var(--v-tooltip-bg-color);
3256
}
3357

34-
.v-popper__arrow-outer {
35-
border-color: var(--color-gray-900);
58+
&-trigger {
59+
//
3660
}
3761
}
3862

39-
.v-popper--theme-tooltip-white {
40-
.v-popper__inner {
41-
background: var(--v-tooltip-white-bg-color);
42-
color: var(--v-tooltip-white-color);
43-
padding: var(--v-tooltip-padding-y) var(--v-tooltip-padding-x);
44-
border-radius: var(--v-tooltip-border-radius);
45-
font-size: var(--v-tooltip-font-size);
46-
border: var(--v-tooltip-white-border);
47-
max-width: var(--v-tooltip-max-width);
63+
@keyframes slideUpAndFade {
64+
from {
65+
opacity: 0;
66+
transform: translateY(2px);
4867
}
68+
to {
69+
opacity: 1;
70+
transform: translateY(0);
71+
}
72+
}
4973

50-
.v-popper__arrow-outer {
51-
border-color: var(--v-tooltip-white-arrow-border-color);
74+
@keyframes slideRightAndFade {
75+
from {
76+
opacity: 0;
77+
transform: translateX(-2px);
5278
}
53-
}
79+
to {
80+
opacity: 1;
81+
transform: translateX(0);
82+
}
83+
}
84+
85+
@keyframes slideDownAndFade {
86+
from {
87+
opacity: 0;
88+
transform: translateY(-2px);
89+
}
90+
to {
91+
opacity: 1;
92+
transform: translateY(0);
93+
}
94+
}
95+
96+
@keyframes slideLeftAndFade {
97+
from {
98+
opacity: 0;
99+
transform: translateX(2px);
100+
}
101+
to {
102+
opacity: 1;
103+
transform: translateX(0);
104+
}
105+
}

packages/ui/src/foundation/elevation/Elevation.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import tokens from '@morpheme/design-tokens/js/tailwind';
88
<template v-for="(shadow, name) in tokens.boxShadow" :key="name">
99
<div :style="{boxShadow: shadow}" class="rounded-xl p-6 border bg-white">
1010
<div class="mb-2 font-semibold">
11-
{{ name === 'DEFAULT' ? 'shadow' : `shadow-${name}` }}
11+
{{ (name as any) === 'DEFAULT' ? 'shadow' : `shadow-${name}` }}
1212
</div>
1313
<code class="text-mono text-xs">{{ shadow }}</code>
1414
</div>

packages/ui/src/foundation/rounded/Rounded.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {remToPx} from '../utils';
1313
class="p-6 border-2 text-center bg-white"
1414
>
1515
<div class="font-semibold mb-3">
16-
{{ name === 'DEFAULT' ? 'rounded' : `rounded-${name}` }}
16+
{{ (name as any) === 'DEFAULT' ? 'rounded' : `rounded-${name}` }}
1717
</div>
1818
<code>{{ rounded }} ({{ remToPx(rounded) }})</code>
1919
</div>

packages/ui/src/foundation/typography/Typography.vue

-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
<script setup lang="ts">
22
import tokens from '@morpheme/design-tokens/js/tailwind';
3-
import {remToPx} from '../utils';
43
</script>
54

65
<template>

packages/ui/src/tooltip/package.json

+2-3
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,8 @@
1515
"author": "Warsono <[email protected]>",
1616
"license": "MIT",
1717
"dependencies": {
18-
"floating-vue": "^2.0.0-beta.20",
19-
"vee-validate": "^4.11.3",
20-
"vue": "^3.3.4"
18+
"radix-vue": "^1.9.5",
19+
"vue": "^3.4.38"
2120
},
2221
"devDependencies": {
2322
"@headlessui/vue": "^1.7.13",

packages/ui/src/tooltip/src/VTooltip.stories.ts

+28-14
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,13 @@ import VBtn from '../../button/src';
33
import type { Meta, StoryFn } from '@storybook/vue3';
44

55
const placements = [
6-
'top',
7-
'top-start',
8-
'top-end',
9-
'bottom',
10-
'bottom-start',
11-
'bottom-end',
12-
'right',
13-
'right-start',
14-
'right-end',
15-
'left',
16-
'left-start',
17-
'left-end',
6+
'start',
7+
'center',
8+
'end'
189
];
1910

11+
const sides = ['top', 'right', 'bottom', 'left'];
12+
2013
export default {
2114
title: 'Components/Tooltip',
2215
component: VTooltip,
@@ -28,9 +21,9 @@ const Template: StoryFn = (args) => ({
2821
return { args, placements };
2922
},
3023
template: `
31-
<div class="grid grid-cols-6 items-center justify-center gap-4 h-screen">
24+
<div class="grid grid-cols-3 items-center justify-center gap-4 h-screen">
3225
<div class="w-full flex justify-center" v-for="place in placements" :key="place">
33-
<VTooltip v-bind='args' :placement="place">
26+
<VTooltip v-bind='args' :align="place">
3427
<template #activator>
3528
<v-btn>
3629
{{ place }}
@@ -62,6 +55,27 @@ Tooltip.parameters = {
6255
},
6356
};
6457

58+
export const Sides: StoryFn = (args) => ({
59+
components: { VTooltip, VBtn },
60+
setup() {
61+
return { args, sides };
62+
},
63+
template: `
64+
<div class="grid grid-cols-4 items-center justify-center gap-4 h-screen">
65+
<div class="w-full flex justify-center" v-for="side in sides" :key="side">
66+
<VTooltip v-bind='args' :side="side">
67+
<template #activator>
68+
<v-btn>
69+
{{ side }}
70+
</v-btn>
71+
</template>
72+
<span>Hello :)</span>
73+
</VTooltip>
74+
</div>
75+
</div>
76+
`,
77+
});
78+
6579
export const Colors: StoryFn = (args) => ({
6680
components: { VTooltip, VBtn },
6781
setup() {

packages/ui/src/tooltip/src/VTooltip.vue

+87-21
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
<script setup lang="ts">
2-
import {Tooltip} from 'floating-vue';
3-
import type {PropType} from 'vue';
2+
import type { PropType } from 'vue';
3+
import {
4+
type TooltipRootProps,
5+
type TooltipTriggerProps,
6+
type TooltipPortalProps,
7+
type TooltipContentProps,
8+
type TooltipArrowProps,
9+
TooltipArrow, TooltipContent, TooltipPortal, TooltipProvider, TooltipRoot, TooltipTrigger
10+
} from 'radix-vue'
411
512
export type VTooltipPlacement =
613
| 'auto'
@@ -20,6 +27,9 @@ export type VTooltipPlacement =
2027
| 'left-end';
2128
2229
defineProps({
30+
/**
31+
* @deprecated use `align` and/or `side` instead
32+
*/
2333
placement: {
2434
type: String as PropType<VTooltipPlacement>,
2535
default: 'bottom',
@@ -49,6 +59,54 @@ defineProps({
4959
type: String as PropType<'black' | 'white'>,
5060
default: 'black',
5161
},
62+
arrowWidth: {
63+
type: Number,
64+
default: 8,
65+
},
66+
contentSideOffset: {
67+
type: Number,
68+
default: 8,
69+
},
70+
hideContentWrapper: {
71+
type: Boolean,
72+
default: false,
73+
},
74+
delayDuration: {
75+
type: Number,
76+
default: 200,
77+
},
78+
hideArrow: {
79+
type: Boolean,
80+
default: false,
81+
},
82+
align: {
83+
type: String as PropType<'start' | 'center' | 'end'>,
84+
default: 'center',
85+
},
86+
side: {
87+
type: String as PropType<'top' | 'right' | 'bottom' | 'left'>,
88+
default: 'top',
89+
},
90+
rootProps: {
91+
type: Object as PropType<Partial<TooltipRootProps>>,
92+
default: () => ({}),
93+
},
94+
triggerProps: {
95+
type: Object as PropType<Partial<TooltipTriggerProps>>,
96+
default: () => ({}),
97+
},
98+
portalProps: {
99+
type: Object as PropType<Partial<TooltipPortalProps>>,
100+
default: () => ({}),
101+
},
102+
contentProps: {
103+
type: Object as PropType<Partial<TooltipContentProps>>,
104+
default: () => ({}),
105+
},
106+
arrowProps: {
107+
type: Object as PropType<Partial<TooltipArrowProps>>,
108+
default: () => ({}),
109+
},
52110
});
53111
54112
defineSlots<{
@@ -58,30 +116,38 @@ defineSlots<{
58116
</script>
59117

60118
<template>
61-
<!-- <Tooltip :placement="placement" :theme="`tooltip-${color}`">
62-
<slot name="activator" />
63-
<template #popper>
64-
<slot />
65-
</template>
66-
</Tooltip> -->
67119
<TooltipProvider>
68-
<TooltipRoot>
69-
<TooltipTrigger
70-
class="IconButton"
120+
<TooltipRoot
121+
class="v-tooltip"
122+
:class="[
123+
`v-tooltip--${color}`,
124+
`v-tooltip--${placement}`,
125+
tooltipClass,
126+
]"
127+
:delay-duration="delayDuration"
128+
v-bind="rootProps"
129+
>
130+
<TooltipTrigger
131+
class="v-tooltip-trigger"
132+
as-child
133+
v-bind="triggerProps"
71134
>
72-
<slot name="activator" />
135+
<slot name="activator" v-bind="{ activatorClass }" />
73136
</TooltipTrigger>
74-
<TooltipPortal>
75-
<TooltipContent
137+
<TooltipPortal v-bind="portalProps">
138+
<TooltipContent
76139
as-child
77-
class="TooltipContent"
78-
:side-offset="5"
140+
class="v-tooltip-content"
141+
:side-offset="contentSideOffset"
142+
:align="align"
143+
:side="side"
144+
v-bind="contentProps"
79145
>
80-
Add to library
81-
<TooltipArrow
82-
class="TooltipArrow"
83-
:width="8"
84-
/>
146+
<div v-if="!hideContentWrapper">
147+
<slot />
148+
</div>
149+
<slot v-else />
150+
<TooltipArrow v-if="!hideArrow" class="v-tooltip-arrow" :width="arrowWidth" v-bind="arrowProps" />
85151
</TooltipContent>
86152
</TooltipPortal>
87153
</TooltipRoot>

packages/ui/vite.config.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ export default defineConfig({
88
esbuild: {
99
exclude: [
1010
'./src/**/**.stories.ts',
11-
'./src/**/**.stories.tsx'
11+
'./src/**/**.stories.tsx',
12+
'./src/foundation',
13+
'./src/stories',
1214
],
1315
},
1416
build: {

0 commit comments

Comments
 (0)