Skip to content

Commit 1703d5a

Browse files
committed
chore: fix tooltip
1 parent 0722567 commit 1703d5a

File tree

2 files changed

+118
-73
lines changed

2 files changed

+118
-73
lines changed

app/pricing/components/comparison-table.tsx

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,29 +16,27 @@ export function ComparisonTable({ show }: ComparisonTableProps) {
1616
}
1717

1818
return (
19-
<Tooltip.Provider>
19+
<Tooltip.Provider delayDuration={300} skipDelayDuration={300}>
2020
<motion.div
21-
className="w-full"
21+
className='w-full'
2222
initial={{ opacity: 0, y: 20 }}
2323
animate={{ opacity: 1, y: 0 }}
2424
exit={{ opacity: 0, y: 20 }}
2525
transition={{ duration: 0.3 }}
2626
>
2727
{/* Compare plans title */}
28-
<div className="text-center py-10 w-full max-w-screen-xl mx-auto px-4 sm:px-6 lg:px-8">
29-
<div className="w-full max-w-[1100px] mx-auto">
30-
<h2 className="font-inter font-medium text-[#101012] text-2xl">
31-
Compare plans
32-
</h2>
28+
<div className='mx-auto w-full max-w-screen-xl px-4 py-10 text-center sm:px-6 lg:px-8'>
29+
<div className='mx-auto w-full max-w-[1100px]'>
30+
<h2 className='font-inter text-2xl font-medium text-[#101012]'>Compare plans</h2>
3331
</div>
3432
</div>
35-
33+
3634
{/* Responsive Table Display */}
37-
<div className="hidden md:block">
35+
<div className='hidden md:block'>
3836
<DesktopComparisonTable />
3937
</div>
40-
41-
<div className="block md:hidden">
38+
39+
<div className='block md:hidden'>
4240
<MobileComparisonTable />
4341
</div>
4442
</motion.div>

app/pricing/components/mobile-comparison-table.tsx

Lines changed: 109 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ export function MobileComparisonTable() {
1212
const [selectedPlan, setSelectedPlan] = useState<ComparisonPlan>(comparisonPlans[0]);
1313
const [isUpgradeDialogOpen, setIsUpgradeDialogOpen] = useState(false);
1414
const [isContactDialogOpen, setIsContactDialogOpen] = useState(false);
15+
const [openTooltips, setOpenTooltips] = useState<Set<string>>(new Set());
1516

1617
const handlePlanChange = (planId: string) => {
17-
const plan = comparisonPlans.find(p => p.id === planId);
18+
const plan = comparisonPlans.find((p) => p.id === planId);
1819

1920
if (plan) {
2021
setSelectedPlan(plan);
@@ -29,47 +30,73 @@ export function MobileComparisonTable() {
2930
setIsContactDialogOpen(true);
3031
};
3132

33+
const handleTooltipToggle = (featureId: string) => {
34+
setOpenTooltips((prev) => {
35+
const newSet = new Set(prev);
36+
37+
if (newSet.has(featureId)) {
38+
newSet.delete(featureId);
39+
} else {
40+
newSet.add(featureId);
41+
}
42+
43+
return newSet;
44+
});
45+
};
46+
3247
return (
33-
<div className="w-full bg-white px-4 pt-6">
48+
<div className='w-full bg-white px-4 pt-6'>
3449
{/* Plan Selector */}
35-
<div className="mb-6">
50+
<div className='mb-6'>
3651
<Select.Root value={selectedPlan.id} onValueChange={handlePlanChange}>
37-
<Select.Trigger className="w-full flex items-center justify-between px-4 py-3 bg-white border border-gray-300 rounded-lg text-left focus:outline-none focus:ring-2 focus:ring-[#9327FF] focus:border-transparent">
52+
<Select.Trigger className='flex w-full items-center justify-between rounded-lg border border-gray-300 bg-white px-4 py-3 text-left focus:border-transparent focus:outline-none focus:ring-2 focus:ring-[#9327FF]'>
3853
<Select.Value>
39-
<span className="text-[#21232A] font-medium" style={{ fontFamily: '"SF Pro Text"' }}>
54+
<span className='font-medium text-[#21232A]' style={{ fontFamily: '"SF Pro Text"' }}>
4055
{selectedPlan.name} Plan
4156
</span>
4257
</Select.Value>
43-
<Select.Icon className="ml-2">
44-
<svg width="12" height="8" viewBox="0 0 12 8" fill="none">
45-
<path d="M1 1.5L6 6.5L11 1.5" stroke="#6B7280" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
58+
<Select.Icon className='ml-2'>
59+
<svg width='12' height='8' viewBox='0 0 12 8' fill='none'>
60+
<path
61+
d='M1 1.5L6 6.5L11 1.5'
62+
stroke='#6B7280'
63+
strokeWidth='1.5'
64+
strokeLinecap='round'
65+
strokeLinejoin='round'
66+
/>
4667
</svg>
4768
</Select.Icon>
4869
</Select.Trigger>
49-
70+
5071
<Select.Portal>
51-
<Select.Content className="bg-white border border-gray-200 rounded-lg shadow-lg z-50 min-w-[200px]">
52-
<Select.Viewport className="p-1">
72+
<Select.Content className='z-50 min-w-[200px] rounded-lg border border-gray-200 bg-white shadow-lg'>
73+
<Select.Viewport className='p-1'>
5374
{comparisonPlans.map((plan) => (
5475
<Select.Item
5576
key={plan.id}
5677
value={plan.id}
57-
className="flex items-center px-3 py-2 text-sm rounded-md cursor-pointer hover:bg-gray-50 focus:bg-[#9327FF] focus:text-white focus:outline-none data-[highlighted]:bg-[#9327FF] data-[highlighted]:text-white"
78+
className='flex cursor-pointer items-center rounded-md px-3 py-2 text-sm hover:bg-gray-50 focus:bg-[#9327FF] focus:text-white focus:outline-none data-[highlighted]:bg-[#9327FF] data-[highlighted]:text-white'
5879
>
5980
<Select.ItemText>
60-
<div className="flex flex-col">
61-
<span className="font-medium" style={{ fontFamily: '"SF Pro Text"' }}>
81+
<div className='flex flex-col'>
82+
<span className='font-medium' style={{ fontFamily: '"SF Pro Text"' }}>
6283
{plan.name}
6384
</span>
64-
<span className="text-xs opacity-70" style={{ fontFamily: '"SF Pro Text"' }}>
85+
<span className='text-xs opacity-70' style={{ fontFamily: '"SF Pro Text"' }}>
6586
{plan.price.amount}
6687
{plan.price.period && ` / ${plan.price.period}`}
6788
</span>
6889
</div>
6990
</Select.ItemText>
70-
<Select.ItemIndicator className="ml-auto">
71-
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
72-
<path d="M13.5 4.5L6 12L2.5 8.5" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
91+
<Select.ItemIndicator className='ml-auto'>
92+
<svg width='16' height='16' viewBox='0 0 16 16' fill='none'>
93+
<path
94+
d='M13.5 4.5L6 12L2.5 8.5'
95+
stroke='currentColor'
96+
strokeWidth='2'
97+
strokeLinecap='round'
98+
strokeLinejoin='round'
99+
/>
73100
</svg>
74101
</Select.ItemIndicator>
75102
</Select.Item>
@@ -81,93 +108,119 @@ export function MobileComparisonTable() {
81108
</div>
82109

83110
{/* Selected Plan Details */}
84-
<div className="mb-6 p-4 bg-gray-50 w-full rounded-lg">
85-
<div className="text-center w-full">
86-
<h3 className="text-[#21232A] font-bold text-xl leading-[24px] mb-2" style={{ fontFamily: '"SF Pro Text"' }}>
111+
<div className='mb-6 w-full rounded-lg bg-gray-50 p-4'>
112+
<div className='w-full text-center'>
113+
<h3 className='mb-2 text-xl font-bold leading-[24px] text-[#21232A]' style={{ fontFamily: '"SF Pro Text"' }}>
87114
{selectedPlan.name}
88115
</h3>
89-
90-
<div className="text-[#21232A] mb-2">
116+
117+
<div className='mb-2 text-[#21232A]'>
91118
{selectedPlan.price.period ? (
92119
<div>
93-
<span className="font-semibold text-2xl" style={{ fontFamily: '"SF Pro Text"' }}>
120+
<span className='text-2xl font-semibold' style={{ fontFamily: '"SF Pro Text"' }}>
94121
{selectedPlan.price.amount}
95122
</span>
96123
{selectedPlan.price.period && (
97-
<span className="font-normal text-base ml-1" style={{ fontFamily: '"SF Pro Text"' }}>
124+
<span className='ml-1 text-base font-normal' style={{ fontFamily: '"SF Pro Text"' }}>
98125
/ {selectedPlan.price.period}
99126
</span>
100127
)}
101128
</div>
102129
) : (
103-
<span className="font-normal text-2xl" style={{ fontFamily: '"SF Pro Text"' }}>
130+
<span className='text-2xl font-normal' style={{ fontFamily: '"SF Pro Text"' }}>
104131
{selectedPlan.price.amount}
105132
</span>
106133
)}
107134
</div>
108-
135+
109136
{selectedPlan.billingInfo && (
110-
<div className="text-[#6F748C] text-sm mb-4" style={{ fontFamily: '"SF Pro Text"' }}>
137+
<div className='mb-4 text-sm text-[#6F748C]' style={{ fontFamily: '"SF Pro Text"' }}>
111138
{selectedPlan.billingInfo}
112139
</div>
113140
)}
114-
141+
115142
{selectedPlan.id !== 'free' && (
116-
<button
117-
onClick={selectedPlan.cta.variant === 'upgrade' ? handleUpgradeClick : selectedPlan.cta.variant === 'contact' ? handleContactClick : undefined}
118-
className={`px-6 w-full py-3 rounded-lg font-medium transition-colors ${
119-
selectedPlan.cta.variant === 'contact'
120-
? 'border-2 border-[#9327FF] text-[#9327FF] hover:bg-[#9327FF] hover:text-white'
121-
: 'bg-[#9327FF] text-white hover:bg-[#7A1FD9]'
122-
}`}>
143+
<button
144+
onClick={
145+
selectedPlan.cta.variant === 'upgrade'
146+
? handleUpgradeClick
147+
: selectedPlan.cta.variant === 'contact'
148+
? handleContactClick
149+
: undefined
150+
}
151+
className={`w-full rounded-lg px-6 py-3 font-medium transition-colors ${
152+
selectedPlan.cta.variant === 'contact'
153+
? 'border-2 border-[#9327FF] text-[#9327FF] hover:bg-[#9327FF] hover:text-white'
154+
: 'bg-[#9327FF] text-white hover:bg-[#7A1FD9]'
155+
}`}
156+
>
123157
{selectedPlan.cta.text}
124158
</button>
125159
)}
126160
</div>
127161
</div>
128162

129163
{/* Features by Group */}
130-
<div className="space-y-6">
164+
<div className='space-y-6'>
131165
{comparisonFeatureGroups.map((group) => (
132-
<div key={group.id} className="bg-white border border-gray-200 rounded-lg overflow-hidden">
166+
<div key={group.id} className='overflow-hidden rounded-lg border border-gray-200 bg-white'>
133167
{/* Group Title */}
134-
<div className="bg-gray-50 px-4 py-3 border-b border-gray-200">
135-
<h4 className="text-[#21232A] font-medium text-lg leading-[24px]" style={{ fontFamily: '"SF Pro Text"' }}>
168+
<div className='border-b border-gray-200 bg-gray-50 px-4 py-3'>
169+
<h4 className='text-lg font-medium leading-[24px] text-[#21232A]' style={{ fontFamily: '"SF Pro Text"' }}>
136170
{group.title}
137171
</h4>
138172
</div>
139-
173+
140174
{/* Features */}
141-
<div className="divide-y divide-gray-100">
175+
<div className='divide-y divide-gray-100'>
142176
{group.features.map((feature) => (
143-
<div key={feature.id} className="px-4 py-3 flex items-center justify-between">
144-
<div className="flex items-center flex-1">
145-
<span className="text-[#21232A] font-normal text-sm leading-5" style={{ fontFamily: '"SF Pro Text"' }}>
177+
<div key={feature.id} className='flex items-center justify-between px-4 py-3'>
178+
<div className='flex flex-1 items-center'>
179+
<span
180+
className='text-sm font-normal leading-5 text-[#21232A]'
181+
style={{ fontFamily: '"SF Pro Text"' }}
182+
>
146183
{feature.name}
147184
</span>
148185
{feature.tooltip && (
149-
<Tooltip.Root>
186+
<Tooltip.Root
187+
open={openTooltips.has(feature.id)}
188+
onOpenChange={(open) => {
189+
if (!open) {
190+
setOpenTooltips((prev) => {
191+
const newSet = new Set(prev);
192+
193+
newSet.delete(feature.id);
194+
195+
return newSet;
196+
});
197+
}
198+
}}
199+
>
150200
<Tooltip.Trigger asChild>
151-
<div className="ml-2 flex-shrink-0 cursor-help">
201+
<div
202+
className='ml-2 flex-shrink-0 cursor-help'
203+
onClick={() => handleTooltipToggle(feature.id)}
204+
>
152205
<TooltipIcon />
153206
</div>
154207
</Tooltip.Trigger>
155208
<Tooltip.Portal>
156209
<Tooltip.Content
157-
className="bg-gray-900 max-w-xs whitespace-pre-wrap break-words text-white px-3 py-2 rounded-md text-sm z-50"
210+
className='z-50 max-w-xs whitespace-pre-wrap break-words rounded-md bg-gray-900 px-3 py-2 text-sm text-white'
158211
sideOffset={5}
159212
>
160213
{feature.tooltip}
161-
<Tooltip.Arrow className="fill-gray-900" />
214+
<Tooltip.Arrow className='fill-gray-900' />
162215
</Tooltip.Content>
163216
</Tooltip.Portal>
164217
</Tooltip.Root>
165218
)}
166219
</div>
167-
168-
<div className="ml-4 flex-shrink-0">
220+
221+
<div className='ml-4 flex-shrink-0'>
169222
{typeof feature.support[selectedPlan.id] === 'string' ? (
170-
<span className="text-[#21232A] font-medium text-sm" style={{ fontFamily: '"SF Pro Text"' }}>
223+
<span className='text-sm font-medium text-[#21232A]' style={{ fontFamily: '"SF Pro Text"' }}>
171224
{feature.support[selectedPlan.id]}
172225
</span>
173226
) : feature.support[selectedPlan.id] === true ? (
@@ -182,16 +235,10 @@ export function MobileComparisonTable() {
182235
</div>
183236
))}
184237
</div>
185-
186-
<UpgradeDialog
187-
isOpen={isUpgradeDialogOpen}
188-
onClose={() => setIsUpgradeDialogOpen(false)}
189-
/>
190-
191-
<ContactDialog
192-
open={isContactDialogOpen}
193-
onOpenChange={setIsContactDialogOpen}
194-
/>
238+
239+
<UpgradeDialog isOpen={isUpgradeDialogOpen} onClose={() => setIsUpgradeDialogOpen(false)} />
240+
241+
<ContactDialog open={isContactDialogOpen} onOpenChange={setIsContactDialogOpen} />
195242
</div>
196243
);
197244
}

0 commit comments

Comments
 (0)