# All files / src/components/ui tooltip.tsx

87.87% Statements 87/99
91.66% Branches 11/12
100% Functions 6/6
87.87% Lines 87/99

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    1001x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    14x
    14x
    14x
    1x
    25x
    25x
    25x
    25x
    25x
    25x
    25x
    25x
    1x
    25x
    25x
    25x
    25x
    25x
    9x
    9x
    9x
    9x
    25x
    25x
    2x
    2x
    2x
    2x
    2x
    25x
    25x
    25x
    25x
    25x
    25x
    25x
    25x

    1x
    39x
    39x
    39x
    39x
    39x
    39x
    39x
    39x
    39x
    14x
    39x
    39x
    39x
    9x
    9x
    9x
    9x
    9x
    9x
    9x
    9x
    9x
    9x
    9x
    9x
    9x
    9x
    9x
    9x
    9x
    9x
    9x
    9x
    9x
    1x
    1x
     "use client"

    import React, { ComponentProps, useState, useRef, useEffect } from "react"
    import { createPortal } from "react-dom"
    import { cn } from "@/lib/utils"

    interface TooltipContextValue {
      open: boolean
      setOpen: (open: boolean) => void
    }

    const TooltipContext = React.createContext<TooltipContextValue | null>(null)

    function TooltipProvider({ children }: { children: React.ReactNode; delayDuration?: number }) {
      return <>{children}</>
    }

    function Tooltip({ children }: { children: React.ReactNode }) {
      const [open, setOpen] = useState(false)
      return (
        <TooltipContext.Provider value={{ open, setOpen }}>
          {children}
        </TooltipContext.Provider>
      )
    }

    function TooltipTrigger({ children, asChild, ...props }: ComponentProps<"button"> & { asChild?: boolean }) {
      const context = React.useContext(TooltipContext)
      const timeoutRef = useRef<NodeJS.Timeout | null>(null)

      const handleMouseEnter = () => {
        timeoutRef.current = setTimeout(() => {
          context?.setOpen(true)
        }, 700)
      }

      const handleMouseLeave = () => {
        if (timeoutRef.current) {
          clearTimeout(timeoutRef.current)
        }
        context?.setOpen(false)
      }

      if (asChild && React.isValidElement(children)) {
        return React.cloneElement(children as React.ReactElement, {
          onMouseEnter: handleMouseEnter,
          onMouseLeave: handleMouseLeave,
          ...props,
        })
      }

      return (
        <button
          type="button"
          onMouseEnter={handleMouseEnter}
          onMouseLeave={handleMouseLeave}
          {...props}
        >
          {children}
        </button>
      )
    }

    function TooltipContent({
      className,
      children,
      ...props
    }: ComponentProps<"div"> & { sideOffset?: number }) {
      const context = React.useContext(TooltipContext)
      const [mounted, setMounted] = useState(false)

      useEffect(() => {
        setMounted(true)
      }, [])

      if (!context?.open || !mounted) return null

      return createPortal(
        <div className="cdk-overlay-container">
          <div className="cdk-overlay-pane">
            <div
              className={cn(
                "mat-mdc-tooltip mdc-tooltip mat-mdc-tooltip-show",
                className
              )}
              role="tooltip"
              {...props}
            >
              <div className="mdc-tooltip__surface mdc-tooltip__surface-animation">
                {children}
              </div>
            </div>
          </div>
        </div>,
        document.body
      )
    }

    export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }