File size: 1,272 Bytes
3201ca6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import type { ReactNode } from "react";
import { AnimatePresence, motion, useReducedMotion } from "framer-motion";
import { cn } from "#/utils/utils";

const ACCORDION_TRANSITION = {
  duration: 0.2,
  ease: "easeInOut" as const,
};

interface AccordionPanelProps {
  open: boolean;
  children: ReactNode;
  testId?: string;
  className?: string;
}

/**
 * Height/opacity expand-collapse wrapper for Diffs / Commits accordion rows.
 * Honors prefers-reduced-motion by skipping animation.
 */
export function AccordionPanel({
  open,
  children,
  testId,
  className,
}: AccordionPanelProps) {
  const reduceMotion = useReducedMotion();

  if (reduceMotion) {
    return open ? (
      <div data-testid={testId} className={className}>
        {children}
      </div>
    ) : null;
  }

  return (
    <AnimatePresence initial={false}>
      {open ? (
        <motion.div
          key="accordion-panel"
          data-testid={testId}
          initial={{ height: 0, opacity: 0 }}
          animate={{ height: "auto", opacity: 1 }}
          exit={{ height: 0, opacity: 0 }}
          transition={ACCORDION_TRANSITION}
          className={cn("overflow-hidden", className)}
        >
          {children}
        </motion.div>
      ) : null}
    </AnimatePresence>
  );
}