| 
									
										
										
										
											2025-04-24 15:17:35 -07:00
										 |  |  | // Copyright 2025 Signal Messenger, LLC
 | 
					
						
							|  |  |  | // SPDX-License-Identifier: AGPL-3.0-only
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-03 06:29:51 -07:00
										 |  |  | import React, { useRef, useState, type ReactNode } from 'react'; | 
					
						
							|  |  |  | import * as Tooltip from '@radix-ui/react-tooltip'; | 
					
						
							|  |  |  | import { useLayoutEffect } from '@react-aria/utils'; | 
					
						
							|  |  |  | import { strictAssert } from '../../../util/assert'; | 
					
						
							| 
									
										
										
										
											2025-04-24 15:17:35 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | export type FunTooltipProps = Readonly<{ | 
					
						
							| 
									
										
										
										
											2025-06-03 06:29:51 -07:00
										 |  |  |   open?: boolean; | 
					
						
							|  |  |  |   onOpenChange?: (open: boolean) => void; | 
					
						
							|  |  |  |   disableHoverableContent?: boolean; | 
					
						
							|  |  |  |   side?: Tooltip.TooltipContentProps['side']; | 
					
						
							|  |  |  |   align?: Tooltip.TooltipContentProps['align']; | 
					
						
							|  |  |  |   collisionBoundarySelector?: string; | 
					
						
							|  |  |  |   collisionPadding?: number; | 
					
						
							|  |  |  |   content: ReactNode; | 
					
						
							| 
									
										
										
										
											2025-04-24 15:17:35 -07:00
										 |  |  |   children: ReactNode; | 
					
						
							|  |  |  | }>; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export function FunTooltip(props: FunTooltipProps): JSX.Element { | 
					
						
							| 
									
										
										
										
											2025-06-03 06:29:51 -07:00
										 |  |  |   const ref = useRef<HTMLButtonElement>(null); | 
					
						
							|  |  |  |   const [collisionBoundary, setCollisionBoundary] = useState<Element | null>( | 
					
						
							|  |  |  |     null | 
					
						
							|  |  |  |   ); | 
					
						
							|  |  |  |   useLayoutEffect(() => { | 
					
						
							|  |  |  |     if (props.collisionBoundarySelector == null) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     strictAssert(ref.current, 'missing ref'); | 
					
						
							|  |  |  |     const trigger = ref.current; | 
					
						
							|  |  |  |     setCollisionBoundary(trigger.closest(props.collisionBoundarySelector)); | 
					
						
							|  |  |  |   }, [props.collisionBoundarySelector]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-24 15:17:35 -07:00
										 |  |  |   return ( | 
					
						
							| 
									
										
										
										
											2025-06-03 06:29:51 -07:00
										 |  |  |     <Tooltip.Root | 
					
						
							|  |  |  |       open={props.open} | 
					
						
							|  |  |  |       onOpenChange={props.onOpenChange} | 
					
						
							|  |  |  |       disableHoverableContent={props.disableHoverableContent} | 
					
						
							|  |  |  |     > | 
					
						
							|  |  |  |       <Tooltip.Trigger ref={ref} asChild> | 
					
						
							|  |  |  |         {props.children} | 
					
						
							|  |  |  |       </Tooltip.Trigger> | 
					
						
							|  |  |  |       <Tooltip.Portal> | 
					
						
							|  |  |  |         <Tooltip.Content | 
					
						
							|  |  |  |           side={props.side} | 
					
						
							|  |  |  |           align={props.align} | 
					
						
							|  |  |  |           className="FunTooltip" | 
					
						
							|  |  |  |           collisionBoundary={collisionBoundary} | 
					
						
							|  |  |  |           collisionPadding={props.collisionPadding} | 
					
						
							|  |  |  |         > | 
					
						
							|  |  |  |           <span className="FunTooltip__Text">{props.content}</span> | 
					
						
							|  |  |  |         </Tooltip.Content> | 
					
						
							|  |  |  |       </Tooltip.Portal> | 
					
						
							|  |  |  |     </Tooltip.Root> | 
					
						
							| 
									
										
										
										
											2025-04-24 15:17:35 -07:00
										 |  |  |   ); | 
					
						
							|  |  |  | } |