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>
);
}
|