91 lines
2.7 KiB
TypeScript
91 lines
2.7 KiB
TypeScript
import React from 'react'
|
|
import { styled, keyframes } from '../stitches.config'
|
|
import * as TooltipPrimitive from '@radix-ui/react-tooltip'
|
|
|
|
const slideUpAndFade = keyframes({
|
|
'0%': { opacity: 0, transform: 'translateY(2px)' },
|
|
'100%': { opacity: 1, transform: 'translateY(0)' }
|
|
})
|
|
|
|
const slideRightAndFade = keyframes({
|
|
'0%': { opacity: 0, transform: 'translateX(-2px)' },
|
|
'100%': { opacity: 1, transform: 'translateX(0)' }
|
|
})
|
|
|
|
const slideDownAndFade = keyframes({
|
|
'0%': { opacity: 0, transform: 'translateY(-2px)' },
|
|
'100%': { opacity: 1, transform: 'translateY(0)' }
|
|
})
|
|
|
|
const slideLeftAndFade = keyframes({
|
|
'0%': { opacity: 0, transform: 'translateX(2px)' },
|
|
'100%': { opacity: 1, transform: 'translateX(0)' }
|
|
})
|
|
|
|
const StyledContent = styled(TooltipPrimitive.Content, {
|
|
borderRadius: 4,
|
|
padding: '$2 $3',
|
|
fontSize: 12,
|
|
lineHeight: 1,
|
|
color: '$text',
|
|
backgroundColor: '$background',
|
|
boxShadow: 'hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px',
|
|
'@media (prefers-reduced-motion: no-preference)': {
|
|
animationDuration: '400ms',
|
|
animationTimingFunction: 'cubic-bezier(0.16, 1, 0.3, 1)',
|
|
animationFillMode: 'forwards',
|
|
willChange: 'transform, opacity',
|
|
'&[data-state="delayed-open"]': {
|
|
'&[data-side="top"]': { animationName: slideDownAndFade },
|
|
'&[data-side="right"]': { animationName: slideLeftAndFade },
|
|
'&[data-side="bottom"]': { animationName: slideUpAndFade },
|
|
'&[data-side="left"]': { animationName: slideRightAndFade }
|
|
}
|
|
},
|
|
'.dark &': {
|
|
boxShadow:
|
|
'0px 0px 10px 2px rgba(0,0,0,.45), hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px'
|
|
},
|
|
'.light &': {
|
|
boxShadow:
|
|
'0px 0px 10px 2px rgba(0,0,0,.25), hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px'
|
|
}
|
|
})
|
|
|
|
const StyledArrow = styled(TooltipPrimitive.Arrow, {
|
|
fill: '$background'
|
|
})
|
|
|
|
interface ITooltip {
|
|
content: string
|
|
open?: boolean
|
|
defaultOpen?: boolean
|
|
onOpenChange?: (open: boolean) => void
|
|
}
|
|
|
|
const Tooltip: React.FC<React.ComponentProps<typeof StyledContent> & ITooltip> = ({
|
|
children,
|
|
content,
|
|
open,
|
|
defaultOpen = false,
|
|
onOpenChange,
|
|
...rest
|
|
}) => {
|
|
return (
|
|
<TooltipPrimitive.Root
|
|
open={open}
|
|
defaultOpen={defaultOpen}
|
|
onOpenChange={onOpenChange}
|
|
delayDuration={100}
|
|
>
|
|
<TooltipPrimitive.Trigger asChild>{children}</TooltipPrimitive.Trigger>
|
|
<StyledContent side="bottom" align="center" {...rest}>
|
|
<div dangerouslySetInnerHTML={{ __html: content }} />
|
|
<StyledArrow offset={5} width={11} height={5} />
|
|
</StyledContent>
|
|
</TooltipPrimitive.Root>
|
|
)
|
|
}
|
|
|
|
export default Tooltip
|