Skip to content

Commit f17a36f

Browse files
committed
docs(ComponentThemeVisualizer): add motion icon and tooltip
1 parent a48c264 commit f17a36f

2 files changed

Lines changed: 159 additions & 8 deletions

File tree

docs/app/components/content/ComponentThemeVisualizer.vue

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -154,14 +154,18 @@ watch(open, (isOpen) => {
154154
:ui="{ content: 'w-64 max-h-72 overflow-y-auto' }"
155155
:dismissible="false"
156156
>
157-
<UButton
158-
:icon="open ? 'i-lucide-x' : 'i-lucide-scan-eye'"
159-
color="neutral"
160-
variant="outline"
161-
size="sm"
162-
class="absolute -top-[11px] -right-[11px] z-1 rounded-full lg:opacity-0 lg:group-hover/component:opacity-100 ring-muted transition-opacity duration-200"
163-
:class="[open && 'lg:opacity-100 bg-elevated']"
164-
/>
157+
<UTooltip text="Inspect theme slots" :disabled="open" :content="{ side: 'right' }">
158+
<UButton
159+
color="neutral"
160+
variant="outline"
161+
size="sm"
162+
square
163+
class="absolute -top-[11px] -right-[11px] z-1 rounded-full lg:opacity-0 lg:group-hover/component:opacity-100 ring-muted transition-opacity duration-200"
164+
:class="[open && 'lg:opacity-100 bg-elevated']"
165+
>
166+
<ComponentThemeVisualizerIcon :open="open" />
167+
</UButton>
168+
</UTooltip>
165169

166170
<template #content>
167171
<div ref="popoverContentRef" class="px-2.5 py-1.5 text-xs font-semibold text-highlighted border-b border-default">
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
<script setup lang="ts">
2+
import { motion } from 'motion-v'
3+
4+
const props = withDefaults(defineProps<{
5+
size?: number
6+
open?: boolean
7+
}>(), {
8+
size: 16,
9+
open: false
10+
})
11+
12+
// X lines: rotate to form X when open, rotate back and scale down when closing
13+
const line1Variants = {
14+
open: {
15+
rotate: 45,
16+
scale: 1,
17+
opacity: 1,
18+
transition: { duration: 0.25, ease: 'easeOut' as const }
19+
},
20+
closed: {
21+
rotate: 0,
22+
scale: 0,
23+
opacity: 0,
24+
transition: { duration: 0.2, ease: 'easeIn' as const }
25+
}
26+
}
27+
28+
const line2Variants = {
29+
open: {
30+
rotate: -45,
31+
scale: 1,
32+
opacity: 1,
33+
transition: { duration: 0.25, ease: 'easeOut' as const }
34+
},
35+
closed: {
36+
rotate: 0,
37+
scale: 0,
38+
opacity: 0,
39+
transition: { duration: 0.2, ease: 'easeIn' as const }
40+
}
41+
}
42+
43+
// Eye: scale up when appearing, scale down when X appears
44+
const eyeVariants = {
45+
open: {
46+
scale: 0,
47+
opacity: 0,
48+
scaleY: 1,
49+
transition: { duration: 0.15, ease: 'easeIn' as const }
50+
},
51+
closed: {
52+
scale: 1,
53+
opacity: 1,
54+
scaleY: [1, 1, 0.1, 1, 1],
55+
transition: {
56+
scale: { duration: 0.25, delay: 0.1, ease: 'easeOut' as const },
57+
opacity: { duration: 0.2, delay: 0.1, ease: 'easeOut' as const },
58+
scaleY: {
59+
duration: 3,
60+
repeat: Infinity,
61+
ease: 'easeInOut' as const,
62+
times: [0, 0.45, 0.5, 0.55, 1],
63+
delay: 0.5
64+
}
65+
}
66+
}
67+
}
68+
69+
const pupilVariants = {
70+
open: {
71+
scale: 0,
72+
opacity: 0,
73+
transition: { duration: 0.15, ease: 'easeIn' as const }
74+
},
75+
closed: {
76+
opacity: [1, 1, 0, 1, 1],
77+
scale: [1, 1, 0, 1, 1],
78+
transition: {
79+
duration: 3,
80+
repeat: Infinity,
81+
ease: 'easeInOut' as const,
82+
times: [0, 0.45, 0.5, 0.55, 1],
83+
delay: 0.5
84+
}
85+
}
86+
}
87+
88+
const currentState = computed(() => props.open ? 'open' : 'closed')
89+
</script>
90+
91+
<template>
92+
<svg
93+
xmlns="http://www.w3.org/2000/svg"
94+
:width="size"
95+
:height="size"
96+
viewBox="0 0 24 24"
97+
fill="none"
98+
stroke="currentColor"
99+
stroke-width="2"
100+
stroke-linecap="round"
101+
stroke-linejoin="round"
102+
>
103+
<!-- X icon (two lines) -->
104+
<motion.line
105+
x1="4"
106+
y1="12"
107+
x2="20"
108+
y2="12"
109+
:variants="line1Variants"
110+
:animate="currentState"
111+
:style="{ transformOrigin: 'center' }"
112+
class="outline-none"
113+
/>
114+
<motion.line
115+
x1="4"
116+
y1="12"
117+
x2="20"
118+
y2="12"
119+
:variants="line2Variants"
120+
:animate="currentState"
121+
:style="{ transformOrigin: 'center' }"
122+
class="outline-none"
123+
/>
124+
125+
<!-- Eye shape (with blink) -->
126+
<motion.path
127+
d="M2.062 12.348a1 1 0 0 1 0-.696a10.75 10.75 0 0 1 19.876 0a1 1 0 0 1 0 .696a10.75 10.75 0 0 1-19.876 0"
128+
fill="none"
129+
:variants="eyeVariants"
130+
:animate="currentState"
131+
:style="{ transformOrigin: 'center' }"
132+
class="outline-none"
133+
/>
134+
135+
<!-- Pupil -->
136+
<motion.circle
137+
cx="12"
138+
cy="12"
139+
r="3"
140+
fill="none"
141+
:variants="pupilVariants"
142+
:animate="currentState"
143+
:style="{ transformOrigin: 'center' }"
144+
class="outline-none"
145+
/>
146+
</svg>
147+
</template>

0 commit comments

Comments
 (0)