All files / src/components/ui/pageGrid PageGrid.jsx

100% Statements 3/3
75% Branches 3/4
100% Functions 1/1
100% Lines 3/3

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    7x                                                       57x   57x                                        
import {AnimatePresence, motion} from "framer-motion";
 
const COLS = {
    1: "grid-cols-1",
    2: "grid-cols-1 md:grid-cols-2",
    3: "grid-cols-1 md:grid-cols-2 xl:grid-cols-3",
    4: "grid-cols-1 md:grid-cols-2 xl:grid-cols-4",
};
 
/**
 * PageGrid component for consistent grid layouts with page transitions.
 *
 * @component
 * @module components/ui/PageGrid
 *
 * @param {object} props - Component properties.
 * @param {React.ReactNode} props.children - Grid items (Cards) to render inside the layout.
 * @param {string | number} props.page - Unique page identifier for AnimatePresence key and smooth transitions.
 * @param {string} [props.className] - Additional CSS classes for the wrapper div.
 * @param {object} [props.rest] - Other props to spread on the wrapper div (e.g., data attributes).
 *
 * @returns {JSX.Element} Responsive 2-column grid with Framer Motion animations that fills viewport height uniformly.
 */
export function PageGrid({
                             children,
                             page,
                             columns = 2,
                             className = "",
                             ...rest
                         }) {
    const colClass = COLS[columns] ?? COLS[2];
 
    return (
        <div className={`flex flex-col ${className}`} {...rest}>
            <AnimatePresence mode="wait">
                <motion.div
                    key={`page-${page}`}
                    initial={{opacity: 0, scale: 0.96}}
                    animate={{opacity: 1, scale: 1}}
                    exit={{opacity: 0, scale: 0.96}}
                    transition={{duration: 0.3, ease: "easeOut"}}
                    layout
                    className={`grid ${colClass} gap-6 pt-4 items-start`}
                    role="grid"
                    aria-label={`Page ${page}`}
                >
                    {children}
                </motion.div>
            </AnimatePresence>
        </div>
    );
}