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

0% Statements 0/90
0% Branches 0/1
0% Functions 0/1
0% Lines 0/90

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

     import { ComponentProps, ReactNode, useState } from "react"
    import { cn } from "@/lib/utils"

    interface CollapsibleProps extends Omit<ComponentProps<"div">, "children"> {
      open?: boolean
      onOpenChange?: (open: boolean) => void
      defaultOpen?: boolean
      children?: ReactNode | ((state: { open: boolean; onOpenChange: (open: boolean) => void }) => ReactNode)
    }

    function Collapsible({
      open,
      onOpenChange,
      defaultOpen = false,
      children,
      className,
      ...props
    }: CollapsibleProps) {
      const [isOpen, setIsOpen] = useState(defaultOpen)
      const actualOpen = open !== undefined ? open : isOpen

      const handleOpenChange = (newOpen: boolean) => {
        setIsOpen(newOpen)
        onOpenChange?.(newOpen)
      }

      return (
        <div
          data-slot="collapsible"
          data-state={actualOpen ? "open" : "closed"}
          className={cn("w-full", className)}
          {...props}
        >
          {typeof children === "function"
            ? children({ open: actualOpen, onOpenChange: handleOpenChange })
            : children}
        </div>
      )
    }

    function CollapsibleTrigger({
      onClick,
      children,
      className,
      ...props
    }: ComponentProps<"button"> & { children?: ReactNode }) {
      return (
        <button
          data-slot="collapsible-trigger"
          className={cn(
            "mat-mdc-button",
            "flex items-center justify-between w-full",
            "px-3 py-2 rounded-md",
            "hover:bg-gray-200 dark:hover:bg-gray-700",
            "focus-visible:ring-2 focus-visible:ring-offset-2",
            "transition-colors",
            className
          )}
          onClick={onClick}
          {...props}
        >
          {children}
        </button>
      )
    }

    function CollapsibleContent({
      className,
      children,
      ...props
    }: ComponentProps<"div">) {
      return (
        <div
          data-slot="collapsible-content"
          className={cn(
            "overflow-hidden transition-all duration-200",
            "data-[state=open]:animate-in data-[state=closed]:animate-out",
            "data-[state=closed]:collapse",
            className
          )}
          {...props}
        >
          <div className="px-3 py-2">
            {children}
          </div>
        </div>
      )
    }

    export { Collapsible, CollapsibleTrigger, CollapsibleContent }