headplane/app/components/Tooltip.tsx

84 lines
1.8 KiB
TypeScript
Raw Normal View History

2025-02-01 15:28:04 -05:00
import React, { cloneElement, useRef } from 'react';
2024-05-21 17:21:14 -04:00
import {
2025-02-01 15:28:04 -05:00
AriaTooltipProps,
mergeProps,
useTooltip,
useTooltipTrigger,
} from 'react-aria';
import { TooltipTriggerState, useTooltipTriggerState } from 'react-stately';
2025-01-28 17:46:16 -05:00
import cn from '~/utils/cn';
2024-05-21 17:21:14 -04:00
2025-02-01 15:28:04 -05:00
export interface TooltipProps extends AriaTooltipProps {
children: [React.ReactElement, React.ReactElement<TooltipBodyProps>];
2024-05-21 17:21:14 -04:00
}
2025-02-01 15:28:04 -05:00
function Tooltip(props: TooltipProps) {
const state = useTooltipTriggerState({
...props,
delay: 0,
closeDelay: 0,
});
const ref = useRef<HTMLButtonElement | null>(null);
const { triggerProps, tooltipProps } = useTooltipTrigger(
{
...props,
delay: 0,
closeDelay: 0,
},
state,
ref,
);
const [component, body] = props.children;
return (
<span className="relative">
<button
ref={ref}
{...triggerProps}
className={cn(
'flex items-center justify-center',
2025-05-29 09:45:47 -04:00
'focus:outline-hidden focus:ring-3 rounded-xl',
)}
2025-02-01 15:28:04 -05:00
>
{component}
</button>
{state.isOpen &&
cloneElement(body, {
...tooltipProps,
state,
})}
</span>
);
2024-05-21 17:21:14 -04:00
}
2025-02-01 15:28:04 -05:00
interface TooltipBodyProps extends AriaTooltipProps {
children: React.ReactNode;
state?: TooltipTriggerState;
className?: string;
2024-05-21 17:21:14 -04:00
}
2025-02-01 15:28:04 -05:00
function Body({ state, className, ...props }: TooltipBodyProps) {
const { tooltipProps } = useTooltip(props, state);
2024-05-21 17:21:14 -04:00
return (
2025-02-01 15:28:04 -05:00
<span
{...mergeProps(props, tooltipProps)}
2024-12-31 10:30:14 +05:30
className={cn(
2025-02-01 15:28:04 -05:00
'absolute z-50 p-3 top-full mt-1',
2025-05-29 09:45:47 -04:00
'outline-hidden rounded-3xl text-sm w-48',
2025-02-01 15:28:04 -05:00
'bg-white dark:bg-headplane-950',
'text-black dark:text-white',
'shadow-lg dark:shadow-md rounded-xl',
'border border-headplane-100 dark:border-headplane-800',
2024-12-31 10:30:14 +05:30
className,
)}
2024-05-21 17:21:14 -04:00
>
2025-02-01 15:28:04 -05:00
{props.children}
</span>
2024-12-31 10:30:14 +05:30
);
2024-05-21 17:21:14 -04:00
}
2025-02-01 15:28:04 -05:00
export default Object.assign(Tooltip, {
Body,
});