Skip to content

Instantly share code, notes, and snippets.

@n1xx1
Created August 2, 2022 13:12
Show Gist options
  • Save n1xx1/e1fdb5f5d2bb6afae64944c2aeffe6cd to your computer and use it in GitHub Desktop.
Save n1xx1/e1fdb5f5d2bb6afae64944c2aeffe6cd to your computer and use it in GitHub Desktop.
import {
Accordion,
AccordionItem,
AccordionItemProps,
AccordionProps,
ComponentWithAs,
ExpandedIndex,
forwardRef,
SystemStyleObject,
} from "@chakra-ui/react";
import {
Children,
createContext,
ReactNode,
useContext,
useState,
} from "react";
export const CustomAccordion: ComponentWithAs<"div", AccordionProps> =
forwardRef(({ index, onChange, children, ...props }, ref) => {
const [indexState, setIndexState] = useState(index);
return (
<Accordion
ref={ref}
index={index}
onChange={(index) => {
onChange?.(index);
setIndexState(index);
}}
{...props}
>
{Children.map(children, (child, index) => (
<ProvideAccordionContext
key={index}
selfIndex={index}
index={indexState}
>
{child}
</ProvideAccordionContext>
))}
</Accordion>
);
});
export interface CustomAccordionItemProps
extends Omit<AccordionItemProps, "_expanded"> {
_expanded?: SystemStyleObject;
}
export const CustomAccordionItem: ComponentWithAs<
"div",
CustomAccordionItemProps
> = forwardRef(({ _expanded, sx, ...props }, ref) => {
const ctx = useContext(CustomAccordionContext);
let styles = sx;
if (ctx.expanded && _expanded) {
styles = { ...(styles ?? {}), ..._expanded };
}
return <AccordionItem ref={ref} sx={styles} {...props} />;
});
const CustomAccordionContext = createContext({
expanded: false,
});
interface ProvideAccordionContextProps {
children?: ReactNode;
index: ExpandedIndex;
selfIndex: number;
}
function ProvideAccordionContext({
children,
index,
selfIndex,
}: ProvideAccordionContextProps) {
const expanded = Array.isArray(index)
? index.includes(selfIndex)
: index === selfIndex;
return (
<CustomAccordionContext.Provider value={{ expanded }}>
{children}
</CustomAccordionContext.Provider>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment