diff --git a/change/@fluentui-react-accordion-2072fdcd-6e91-497d-8a09-567c6d4e60a1.json b/change/@fluentui-react-accordion-2072fdcd-6e91-497d-8a09-567c6d4e60a1.json new file mode 100644 index 00000000000000..e9732301636c5a --- /dev/null +++ b/change/@fluentui-react-accordion-2072fdcd-6e91-497d-8a09-567c6d4e60a1.json @@ -0,0 +1,7 @@ +{ + "type": "minor", + "comment": "fix: added openItems to AccordionToggleData which respects multiple and collapsible props for controlled Accordion", + "packageName": "@fluentui/react-accordion", + "email": "kakrookaran@gmail.com", + "dependentChangeType": "patch" +} diff --git a/packages/react-components/react-accordion/etc/react-accordion.api.md b/packages/react-components/react-accordion/etc/react-accordion.api.md index 712c9f5a976966..9463312c6ac481 100644 --- a/packages/react-components/react-accordion/etc/react-accordion.api.md +++ b/packages/react-components/react-accordion/etc/react-accordion.api.md @@ -162,6 +162,7 @@ export type AccordionState = ComponentState & AccordionContextVa // @public (undocumented) export type AccordionToggleData = { value: AccordionItemValue; + openItems: AccordionItemValue[]; }; // @public (undocumented) diff --git a/packages/react-components/react-accordion/src/components/Accordion/Accordion.types.ts b/packages/react-components/react-accordion/src/components/Accordion/Accordion.types.ts index de93ff2ff53532..cd492b0c784570 100644 --- a/packages/react-components/react-accordion/src/components/Accordion/Accordion.types.ts +++ b/packages/react-components/react-accordion/src/components/Accordion/Accordion.types.ts @@ -31,6 +31,7 @@ export type AccordionSlots = { export type AccordionToggleData = { value: AccordionItemValue; + openItems: AccordionItemValue[]; }; export type AccordionProps = ComponentProps & { diff --git a/packages/react-components/react-accordion/src/components/Accordion/useAccordion.test.ts b/packages/react-components/react-accordion/src/components/Accordion/useAccordion.test.ts index e5ec379d29f852..7e6848d971de6c 100644 --- a/packages/react-components/react-accordion/src/components/Accordion/useAccordion.test.ts +++ b/packages/react-components/react-accordion/src/components/Accordion/useAccordion.test.ts @@ -10,7 +10,7 @@ describe('useAccordion_unstable', () => { expect(result.current.openItems.length).toEqual(1); expect(result.current.openItems.includes(0)).toBeTruthy(); - act(() => result.current.requestToggle(undefined!, { value: 1 })); + act(() => result.current.requestToggle(undefined!, { value: 1, openItems: [] })); expect(result.current.openItems.length).toEqual(1); expect(result.current.openItems.includes(1)).toBeTruthy(); @@ -20,9 +20,9 @@ describe('useAccordion_unstable', () => { it('should only have zero open items before having any items', () => { const { result } = renderHook(() => useAccordion_unstable({ multiple: true }, React.createRef())); expect(result.current.openItems.length).toEqual(0); - act(() => result.current.requestToggle(undefined!, { value: 0 })); + act(() => result.current.requestToggle(undefined!, { value: 0, openItems: [] })); expect(result.current.openItems.length).toEqual(1); - act(() => result.current.requestToggle(undefined!, { value: 0 })); + act(() => result.current.requestToggle(undefined!, { value: 0, openItems: [] })); expect(result.current.openItems.length).toEqual(1); }); it('should not have less than 1 open item', () => { @@ -32,16 +32,16 @@ describe('useAccordion_unstable', () => { expect(result.current.openItems.length).toEqual(1); - act(() => result.current.requestToggle(undefined!, { value: 0 })); + act(() => result.current.requestToggle(undefined!, { value: 0, openItems: [] })); expect(result.current.openItems.length).toEqual(1); expect(result.current.openItems.includes(0)).toBeTruthy(); }); it('should open multiple panels', () => { const { result } = renderHook(() => useAccordion_unstable({ multiple: true }, React.createRef())); expect(result.current.openItems.length).toEqual(0); - act(() => result.current.requestToggle(undefined!, { value: 0 })); + act(() => result.current.requestToggle(undefined!, { value: 0, openItems: [] })); expect(result.current.openItems.includes(0)).toBeTruthy(); - act(() => result.current.requestToggle(undefined!, { value: 1 })); + act(() => result.current.requestToggle(undefined!, { value: 1, openItems: [] })); expect(result.current.openItems.includes(1)).toBeTruthy(); expect(result.current.openItems.length).toEqual(2); }); @@ -50,18 +50,18 @@ describe('useAccordion_unstable', () => { it('should have zero panels opened', () => { const { result } = renderHook(() => useAccordion_unstable({ collapsible: true }, React.createRef())); expect(result.current.openItems.length).toEqual(0); - act(() => result.current.requestToggle(undefined!, { value: 0 })); + act(() => result.current.requestToggle(undefined!, { value: 0, openItems: [] })); expect(result.current.openItems.length).toEqual(1); - act(() => result.current.requestToggle(undefined!, { value: 0 })); + act(() => result.current.requestToggle(undefined!, { value: 0, openItems: [] })); expect(result.current.openItems.length).toEqual(0); }); it('should not open more than one panel', () => { const { result } = renderHook(() => useAccordion_unstable({ collapsible: true }, React.createRef())); expect(result.current.openItems.length).toEqual(0); - act(() => result.current.requestToggle(undefined!, { value: 0 })); + act(() => result.current.requestToggle(undefined!, { value: 0, openItems: [] })); expect(result.current.openItems.length).toEqual(1); expect(result.current.openItems.includes(0)).toBeTruthy(); - act(() => result.current.requestToggle(undefined!, { value: 1 })); + act(() => result.current.requestToggle(undefined!, { value: 1, openItems: [] })); expect(result.current.openItems.length).toEqual(1); expect(result.current.openItems.includes(1)).toBeTruthy(); expect(result.current.openItems.includes(0)).toBeFalsy(); diff --git a/packages/react-components/react-accordion/src/components/Accordion/useAccordion.ts b/packages/react-components/react-accordion/src/components/Accordion/useAccordion.ts index 0b06b206ac3dfa..e5e7b2b4f5e0e7 100644 --- a/packages/react-components/react-accordion/src/components/Accordion/useAccordion.ts +++ b/packages/react-components/react-accordion/src/components/Accordion/useAccordion.ts @@ -30,8 +30,9 @@ export const useAccordion_unstable = (props: AccordionProps, ref: React.Ref { - onToggle?.(event, data); - setOpenItems(previousOpenItems => updateOpenItems(data.value, previousOpenItems, multiple, collapsible)); + const currentOpenItems = updateOpenItems(data.value, openItems, multiple, collapsible); + onToggle?.(event, { value: data.value, openItems: currentOpenItems }); + setOpenItems(currentOpenItems); }); return { diff --git a/packages/react-components/react-accordion/src/components/AccordionItem/useAccordionItem.ts b/packages/react-components/react-accordion/src/components/AccordionItem/useAccordionItem.ts index bf1141e0df65bf..72f0dd0d40dd61 100644 --- a/packages/react-components/react-accordion/src/components/AccordionItem/useAccordionItem.ts +++ b/packages/react-components/react-accordion/src/components/AccordionItem/useAccordionItem.ts @@ -18,7 +18,7 @@ export const useAccordionItem_unstable = ( const requestToggle = useAccordionContext_unstable(ctx => ctx.requestToggle); const open = useAccordionContext_unstable(ctx => ctx.openItems.includes(value)); const onAccordionHeaderClick = React.useCallback( - (ev: AccordionToggleEvent) => requestToggle(ev, { value }), + (ev: AccordionToggleEvent) => requestToggle(ev, { value, openItems: [] }), [requestToggle, value], ); @@ -30,7 +30,7 @@ export const useAccordionItem_unstable = ( root: 'div', }, root: getNativeElementProps('div', { - ref: ref, + ref, ...props, }), };