import {
ButtonHTMLAttributes,
DetailedHTMLProps,
Dispatch,
HTMLAttributes,
SetStateAction,
createContext,
useContext,
useId,
useState,
} from 'react'
interface IAccordion {
id: string
open: boolean
toggle: Dispatch>
}
const AccordionContext = createContext({
id: '',
open: false,
toggle: () => {},
})
interface AccordionProps
extends Omit<
DetailedHTMLProps, HTMLElement>,
'children'
> {
defaultOpen?: boolean
children: React.ReactNode | ((props: { open: boolean }) => React.ReactNode)
}
export const Accordion = ({
children,
defaultOpen = false,
...rest
}: AccordionProps) => {
const [open, toggle] = useState(defaultOpen)
const id = useId()
return (
{typeof children === 'function' ? children({ open }) : children}
)
}
interface HeaderProps
extends DetailedHTMLProps<
ButtonHTMLAttributes,
HTMLButtonElement
> {}
const Header = ({ children, className, ...rest }: HeaderProps) => {
const { id, open, toggle } = useContext(AccordionContext)
return (
)
}
interface BodyProps
extends DetailedHTMLProps, HTMLDivElement> {}
const Body = ({ children, className, ...rest }: BodyProps) => {
const { id, open } = useContext(AccordionContext)
return (
{children}
)
}
Accordion.Header = Header
Accordion.Body = Body
/**
* Usage
*
Header
Body
----------------------------
{({ open }) => (
<>
Header
Body
>
)}
*/