Skip to content

Commit

Permalink
Feat: Add functionality to keep track of AccordionItem index
Browse files Browse the repository at this point in the history
  • Loading branch information
haribhandari07 committed Jan 17, 2024
1 parent 52075e2 commit 50c3a0b
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 6 deletions.
6 changes: 3 additions & 3 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ function App() {
return (
<>
<Accordion index={openAccordions} onChange={handleAccordionChange}>
<Accordion.Item index={0}>
<Accordion.Item>
<Accordion.Button>Button 1</Accordion.Button>
<Accordion.Panel>Panel 1</Accordion.Panel>
</Accordion.Item>
<Accordion.Item index={1}>
<Accordion.Item>
<Accordion.Button>Button 2</Accordion.Button>
<Accordion.Panel>Panel 2</Accordion.Panel>
</Accordion.Item>
<Accordion.Item index={2}>
<Accordion.Item>
<Accordion.Button>Button 3</Accordion.Button>
<Accordion.Panel>Panel 3</Accordion.Panel>
</Accordion.Item>
Expand Down
36 changes: 33 additions & 3 deletions src/components/Accordion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import {
ReactNode,
useCallback,
useContext,
useId,
useLayoutEffect,
useRef,
useState,
} from "react";
import { useControlledState } from "../utils/useControlledState.ts";

Expand Down Expand Up @@ -89,10 +93,30 @@ const Accordion = forwardRef(function (
[multiple, collapsible, onChange, controlledIndex]
);

const indexCounter = useRef(-1);
const descendantsMap = useRef<Record<string, number>>({});

// This useLayoutEffect cleanup is to cleanup the extra render in the strict mode
// Cleanup hack for now
useLayoutEffect(() => {
return () => {
indexCounter.current = -1;
descendantsMap.current = {};
};
}, []);

const getIndex = useCallback((id: string) => {
if (!descendantsMap.current[id]) {
descendantsMap.current[id] = ++indexCounter.current;
}
return descendantsMap.current[id];
}, []);

const context = {
openPanels: controlledIndex ? controlledIndex : openPanels,
onAccordionItemClick: readOnly ? noop : onAccordionItemClick,
readOnly,
getIndex,
};

return (
Expand All @@ -109,12 +133,18 @@ const AccordionItem = forwardRef(function (
children,
as: Comp = "div",
disabled = false,
index,
...props
}: AccordionItemProps,
forwardedRef
) {
const { openPanels } = useAccordionContext();
const { openPanels, getIndex } = useAccordionContext();

const itemId = useRef<string>(useId());
const [index, setIndex] = useState(-1);

useLayoutEffect(() => {
setIndex(getIndex(itemId.current));
}, [getIndex]);

const state =
(Array.isArray(openPanels)
Expand Down Expand Up @@ -239,7 +269,6 @@ interface AccordionItemProps {
as?: ElementType | ComponentType;
children: ReactNode;
disabled?: boolean;
index: number;
}

interface AccordionButtonProps {
Expand All @@ -258,6 +287,7 @@ interface InternalAccordionContextValue {
onAccordionItemClick(index: AccordionIndex): void;

readOnly: boolean;
getIndex: (id: string) => number;
}

interface InternalAccordionItemContextValue {
Expand Down

0 comments on commit 50c3a0b

Please sign in to comment.