Files
supabase/apps/docs/features/ui/InfoTooltip.tsx
T
Ivan Vasilov 56de26fe22 chore: Migrate the monorepo to use Tailwind v4 (#45318)
This PR migrates the whole monorepo to use Tailwind v4:
- Removed `@tailwindcss/container-queries` plugin since it's included by
default in v4,
- Bump all instances of Tailwind to v4. Made minimal changes to the
shared config to remove non-supported features (`alpha` mentions),
- Migrate all apps to be compatible with v4 configs,
- Fix the `typography.css` import in 3 apps,
- Add missing rules which were included by default in v3,
- Run `pnpm dlx @tailwindcss/upgrade` on all apps, which renames a lot
of classes
- Rename all misnamed classes according to
https://tailwindcss.com/docs/upgrade-guide#renamed-utilities in all
apps.

---------

Co-authored-by: Jordi Enric <jordi.err@gmail.com>
2026-04-30 10:53:24 +00:00

128 lines
3.7 KiB
TypeScript

'use client'
import React, {
type PropsWithChildren,
useCallback,
useEffect,
useId,
useRef,
useState,
} from 'react'
import { InfoIcon, XIcon } from 'lucide-react'
import { ErrorBoundary } from 'react-error-boundary'
import { useBreakpoint } from 'common'
import {
Button,
cn,
CommandEmpty_Shadcn_,
Sheet,
SheetContent,
SheetHeader,
Tooltip,
TooltipContent,
TooltipTrigger,
} from 'ui'
interface PopUpProps extends PropsWithChildren {
tooltipContent: React.ReactNode
className?: string
contentContainerClassName?: string
}
const buttonClassName = cn(
'relative px-1 py-0 -my-px',
'rounded-sm bg-surface-200 border border-dashed',
'transition-colors hover:border-strong group/inline-popup'
)
const InfoTooltip = ({
children,
className,
tooltipContent,
contentContainerClassName,
}: PopUpProps) => {
const id = useId().replaceAll(':', '')
const timeout = useRef<ReturnType<typeof setTimeout> | null>(null)
const [mobileSheetOpen, setMobileSheetOpen] = useState(false)
const [tooltipOpen, _setTooltipOpen] = useState(false)
const isMobile = useBreakpoint('md')
const setTooltipOpen = useCallback(
(open: boolean) => {
_setTooltipOpen(open)
setMobileSheetOpen(true)
timeout.current = setTimeout(() => {
if (isMobile) return
const targetElem: HTMLElement | null = document.querySelector(`#tooltip-content-${id}`)
targetElem?.focus()
})
},
[_setTooltipOpen, id, isMobile]
)
useEffect(() => {
return () => {
if (timeout.current) {
clearTimeout(timeout.current)
}
}
}, [])
return (
<>
<Tooltip open={tooltipOpen} onOpenChange={(open) => !isMobile && setTooltipOpen(open)}>
<TooltipTrigger asChild>
<span
role="button"
tabIndex={0}
onClick={() => setMobileSheetOpen(true)}
className={cn(buttonClassName, className)}
>
{children}
<InfoIcon
aria-hidden={true}
className="absolute p-px bg-background rounded-full -left-1.5 -top-1.5 w-3 h-3 text-foreground-lighter group-hover/inline-popup:text-foreground-light transition-colors"
/>
</span>
</TooltipTrigger>
<TooltipContent id={`tooltip-content-${id}`} className={contentContainerClassName}>
{tooltipContent}
</TooltipContent>
</Tooltip>
{isMobile && (
<Sheet open={mobileSheetOpen} onOpenChange={setMobileSheetOpen}>
<SheetContent
id={`mobile-sheet-content-${id}`}
showClose={false}
size="full"
side="bottom"
className={cn(
'md:hidden',
'text-foreground-lighter',
'rounded-t-lg overflow-hidden overflow-y-scroll',
'w-full h-fit min-h-[200px] py-2 px-4'
)}
>
<ErrorBoundary FallbackComponent={() => <CommandEmpty_Shadcn_ />}>
<SheetHeader className="flex items-center justify-between gap-2 px-0 py-2 mb-2 max-w-full">
<div className="flex items-center gap-2 max-w-[90%]">
<InfoIcon className="p-px min-w-4 min-h-4 text-foreground-lighter" />
<p className="italic text-foreground-light truncate">{children}</p>
</div>
<Button type="text" onClick={() => setMobileSheetOpen(false)} className="px-1">
<XIcon className="w-4 h-4 text-foreground-lighter" />
</Button>
</SheetHeader>
{tooltipContent}
</ErrorBoundary>
</SheetContent>
</Sheet>
)}
</>
)
}
export default InfoTooltip