import { useCallback, type ForwardRefRenderFunction, type HTMLAttributes, type ReactNode, forwardRef, useId, useState, } from 'react'; import { Button, Icon } from '../../atoms'; import styles from './collapsible.module.scss'; export type CollapsibleProps = Omit< HTMLAttributes, 'children' > & { /** * The collapsible body. */ children: ReactNode; /** * Should we disable padding around body? * * @default false */ disablePadding?: boolean; /** * Should the body be bordered? * * @default false */ hasBorders?: boolean; /** * The collapsible heading. */ heading: ReactNode; /** * Should the component be collapsed or expanded by default? * * @default false */ isCollapsed?: boolean; }; const CollapsibleWithRef: ForwardRefRenderFunction< HTMLDivElement, CollapsibleProps > = ( { children, className = '', disablePadding = false, hasBorders = false, heading, isCollapsed = false, ...props }, ref ) => { const bodyId = useId(); const [isExpanded, setIsExpanded] = useState(!isCollapsed); const bodyClassNames = [ styles.body, hasBorders ? styles['body--has-borders'] : '', styles[disablePadding ? 'body--no-padding' : 'body--has-padding'], ]; const wrapperClassNames = [ styles.wrapper, styles[isExpanded ? 'wrapper--expanded' : 'wrapper--collapsed'], className, ]; const handleState = useCallback(() => { setIsExpanded((prevState) => !prevState); }, []); return (
{children}
); }; /** * Collapsible component. * * Render a heading associated to a collapsible body. */ export const Collapsible = forwardRef(CollapsibleWithRef);