diff --git a/packages/libs/react-ui/src/components/Accordion/Accordion.stories.tsx b/packages/libs/react-ui/src/components/Accordion/Accordion.stories.tsx index f086d19be86..469f976ac25 100644 --- a/packages/libs/react-ui/src/components/Accordion/Accordion.stories.tsx +++ b/packages/libs/react-ui/src/components/Accordion/Accordion.stories.tsx @@ -53,26 +53,24 @@ export const Dynamic: IStory = { }, render: ({ linked, sectionCount }) => { return ( - - - {sampleSections - .slice(0, sectionCount) - .map( - ( - { title, children, onOpen, onClose }: IAccordionSectionProps, - index, - ) => ( - - {children} - - ), - )} - + + {sampleSections + .slice(0, sectionCount) + .map( + ( + { title, children, onOpen, onClose }: IAccordionSectionProps, + index, + ) => ( + + {children} + + ), + )} ); }, diff --git a/packages/libs/react-ui/src/components/Accordion/Accordion.tsx b/packages/libs/react-ui/src/components/Accordion/Accordion.tsx index 85c6be056fd..f0174d7645f 100644 --- a/packages/libs/react-ui/src/components/Accordion/Accordion.tsx +++ b/packages/libs/react-ui/src/components/Accordion/Accordion.tsx @@ -1,12 +1,97 @@ -import { IAccordionSectionsProps } from '.'; +import { + accordionContentWrapperClass, + accordionSectionClass, + accordionTitleClass, + accordionTitleVariants, +} from './Accordion.css'; +import useLinked from './useLinked'; +import { IAccordionSectionProps } from '.'; +import classNames from 'classnames'; import type { FC, FunctionComponentElement } from 'react'; -import React from 'react'; +import React, { useCallback, useEffect } from 'react'; export interface IAccordionRootProps { - children?: FunctionComponentElement; + children?: FunctionComponentElement[]; + linked?: boolean; + openSection?: number; } -export const AccordionRoot: FC = ({ children }) => { - return
{children}
; +export const AccordionRoot: FC = ({ + children, + linked = false, + openSection, +}) => { + const { usingLinked, setUsingLinked, openSections, setOpenSections } = + useLinked(openSection); + + useEffect(() => { + setUsingLinked(linked); + if (linked && openSections.length > 1) { + const lastOpen = openSections.pop() || -1; + setOpenSections([lastOpen]); + } + }, [linked]); + + const handleToggleSection = useCallback( + ( + index: number, + { onOpen, onClose }: Pick, + ): void => { + const isOpen = openSections.includes(index); + if (isOpen) { + setOpenSections(openSections.filter((i) => i !== index)); + onClose?.(); + } else { + setOpenSections(usingLinked ? [index] : [...openSections, index]); + onOpen?.(); + } + }, + [openSections, usingLinked], + ); + + return ( +
+ {React.Children.map(children, (section, sectionIndex) => ( +
+
+ handleToggleSection(sectionIndex, { + onOpen: section?.props.onOpen, + onClose: section?.props.onClose, + }) + } + className={classNames( + accordionTitleClass, + accordionTitleVariants[ + openSections.includes(sectionIndex) ? 'opened' : 'closed' + ], + )} + > + {React.cloneElement( + section as React.ReactElement< + HTMLElement | IAccordionSectionProps, + | string + | React.JSXElementConstructor< + JSX.Element & IAccordionSectionProps + > + >, + { + isOpen: openSections.includes(sectionIndex), + }, + )} +
+ {openSections.includes(sectionIndex) && section && ( +
+ {section.props.children} +
+ )} +
+ ))} +
+ ); }; diff --git a/packages/libs/react-ui/src/components/Accordion/index.ts b/packages/libs/react-ui/src/components/Accordion/index.ts index 286187237cb..9b33c56d688 100644 --- a/packages/libs/react-ui/src/components/Accordion/index.ts +++ b/packages/libs/react-ui/src/components/Accordion/index.ts @@ -2,21 +2,17 @@ import type { IAccordionRootProps } from './Accordion'; import { AccordionRoot } from './Accordion'; import type { IAccordionSectionProps } from './AccordionSection'; import { AccordionSection } from './AccordionSection'; -import type { IAccordionSectionsProps } from './AccordionSections'; -import { AccordionSections } from './AccordionSections'; import type { FC } from 'react'; -export { IAccordionRootProps, IAccordionSectionProps, IAccordionSectionsProps }; +export { IAccordionRootProps, IAccordionSectionProps }; export interface IAccordionProps { Root: FC; - Sections: FC; Section: FC; } export const Accordion: IAccordionProps = { Root: AccordionRoot, - Sections: AccordionSections, Section: AccordionSection, };