import React, { ReactNode, useEffect, useRef } from 'react'; import styled, { css } from 'styled-components'; import { MarginProps } from 'styled-system'; import { MaterialKeyboardArrowDown } from '@t3n/icons'; import Box from '../../Box'; import Heading from '../../Heading'; import Icon from '../../Icon'; export interface AccordionProps extends MarginProps { title: string; isOpen: boolean; onToggle: () => void; children?: ReactNode; tabbable?: boolean; } const StyledAccordionHeadBox = styled(Box)` display: flex; justify-content: space-between; align-items: center; cursor: pointer; h4 { font-size: 1.125rem; } `; const StyledIconBox = styled(Box)<{ collapsed: boolean }>` height: 2rem; width: 2rem; ${Icon} { transform: ${({ collapsed }) => collapsed ? 'rotate(0deg)' : 'rotate(180deg)'}; transition: transform 0.2s ease-in; } `; const StyledAccordionContent = styled(Box)<{ collapsed: boolean }>` overflow: hidden; transition: opacity 0.3s ease-in-out, height 0.3s ease-in-out; opacity: ${({ collapsed }) => (collapsed ? '0' : '1')}; position: relative; &:has(* > * > img) { ${({ collapsed }) => (collapsed ? 'transition-delay: 0.6s' : '')}; } & > * > * > * { position: relative; &:has(img) { transform: translateX(0); transition: transform 0.3s ease-in-out; &:nth-child(1) { transition-delay: 0.1s; } &:nth-child(2) { transition-delay: 0.3s; } ${({ collapsed }) => collapsed && css` transform: translateX(200%); &:nth-child(1) { transition-delay: 0.3s; } &:nth-child(2) { transition-delay: 0.1s; } `} } } `; const Accordion: React.FC = ({ children, title, isOpen, onToggle, tabbable, }) => { const collapsed = !isOpen; const contentRef = useRef(null); useEffect(() => { if (contentRef.current) { contentRef.current.style.height = collapsed ? '0' : `${contentRef.current.scrollHeight}px`; } }, [collapsed]); const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onToggle?.(); } }; return ( {title} {children} ); }; export default Accordion;