11import { createSignal , JSX , Show } from "solid-js" ;
22import QuestionMarkIcon from "../icon/QuestionMarkIcon" ;
33
4+ export enum TooltipAlignment {
5+ Center = "center" ,
6+ Left = "left" ,
7+ Right = "right" ,
8+ }
9+
410interface TooltipProps {
511 text : string ;
612 children ?: JSX . Element ;
713}
814
915export default function QuestionTooltip ( props : TooltipProps ) {
1016 const [ isVisible , setIsVisible ] = createSignal ( false ) ;
11- const [ position , setPosition ] = createSignal < { x : number , align : 'center' | 'left' | 'right' } > ( { x : 0 , align : 'center' } ) ;
17+ const [ position , setPosition ] = createSignal < {
18+ x : number ;
19+ align : TooltipAlignment ;
20+ } > ( { x : 0 , align : TooltipAlignment . Center } ) ;
1221
1322 let containerRef : HTMLDivElement | undefined ;
1423
15- const handleMouseEnter = ( ) => {
16- if ( containerRef ) {
17- const rect = containerRef . getBoundingClientRect ( ) ;
18- const tooltipWidth = 256 ; // w-64 is 16rem = 256px
24+ const determineAlignment = ( rect : DOMRect ) : TooltipAlignment => {
25+ const tooltipWidth = 256 ; // w-64 is 16rem = 256px
1926
20- // Calculate potential left and right bounds if centered
21- const centerLeft = rect . left + ( rect . width / 2 ) - ( tooltipWidth / 2 ) ;
22- const centerRight = centerLeft + tooltipWidth ;
27+ // Calculate potential left and right bounds if centered
28+ const centerLeft = rect . left + rect . width / 2 - tooltipWidth / 2 ;
29+ const centerRight = centerLeft + tooltipWidth ;
2330
24- const viewportWidth = window . innerWidth ;
25- const padding = 16 ; // 16px safety padding from screen edges
31+ const viewportWidth = window . innerWidth ;
32+ const padding = 16 ; // 16px safety padding from screen edges
2633
27- if ( centerLeft < padding ) {
28- // Overflow on the left: align left edge of tooltip with container
29- setPosition ( { x : 0 , align : 'left' } ) ;
30- } else if ( centerRight > viewportWidth - padding ) {
31- // Overflow on the right: align right edge of tooltip with container
32- setPosition ( { x : 0 , align : 'right' } ) ;
33- } else {
34- // Safe to center perfectly
35- setPosition ( { x : 0 , align : 'center' } ) ;
36- }
34+ if ( centerLeft < padding ) {
35+ return TooltipAlignment . Left ;
36+ } else if ( centerRight > viewportWidth - padding ) {
37+ return TooltipAlignment . Right ;
38+ } else {
39+ return TooltipAlignment . Center ;
40+ }
41+ } ;
42+
43+ const handleMouseEnter = ( ) => {
44+ if ( containerRef ) {
45+ const rect = containerRef . getBoundingClientRect ( ) ;
46+ const align = determineAlignment ( rect ) ;
47+ setPosition ( { x : 0 , align } ) ;
3748 }
3849 setIsVisible ( true ) ;
3950 } ;
@@ -51,25 +62,34 @@ export default function QuestionTooltip(props: TooltipProps) {
5162 tabIndex = { 0 }
5263 aria-label = "More information"
5364 >
54- < Show when = { props . children } fallback = { < QuestionMarkIcon class = "size-5 text-gray-500 hover:text-gray-700 transition-colors" /> } >
65+ < Show
66+ when = { props . children }
67+ fallback = {
68+ < QuestionMarkIcon class = "size-5 text-gray-500 hover:text-gray-700 transition-colors" />
69+ }
70+ >
5571 { props . children }
5672 </ Show >
5773
5874 < Show when = { isVisible ( ) } >
5975 < div
6076 class = { `absolute z-50 w-64 p-3 mt-2 text-sm text-gray-800 bg-white border border-gray-200 rounded-lg shadow-lg top-full pointer-events-none fade-in ${
61- position ( ) . align === 'center' ? 'left-1/2 -translate-x-1/2' :
62- position ( ) . align === 'left' ? 'left-0' :
63- 'right-0'
77+ position ( ) . align === TooltipAlignment . Center
78+ ? "left-1/2 -translate-x-1/2"
79+ : position ( ) . align === TooltipAlignment . Left
80+ ? "left-0"
81+ : "right-0"
6482 } `}
6583 >
6684 { props . text }
6785 { /* Decorative arrow pointing up */ }
6886 < div
6987 class = { `absolute w-3 h-3 bg-white border-t border-l border-gray-200 rotate-45 -top-[7px] ${
70- position ( ) . align === 'center' ? 'left-1/2 -translate-x-1/2' :
71- position ( ) . align === 'left' ? 'left-3' :
72- 'right-3'
88+ position ( ) . align === TooltipAlignment . Center
89+ ? "left-1/2 -translate-x-1/2"
90+ : position ( ) . align === TooltipAlignment . Left
91+ ? "left-3"
92+ : "right-3"
7393 } `}
7494 />
7595 </ div >
0 commit comments