@@ -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