From 6a28925efce235b1e7ddf0566a7f8f52fe05b6f3 Mon Sep 17 00:00:00 2001 From: Mike Interlandi <43190101+Minterl@users.noreply.github.com> Date: Thu, 26 Jun 2025 14:12:51 -0400 Subject: [PATCH 1/6] add prop keepChildrenMounted to collapsible --- packages/react/collapsible/src/collapsible.tsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/react/collapsible/src/collapsible.tsx b/packages/react/collapsible/src/collapsible.tsx index 3e7f47b55..3452b14e6 100644 --- a/packages/react/collapsible/src/collapsible.tsx +++ b/packages/react/collapsible/src/collapsible.tsx @@ -21,6 +21,7 @@ const [createCollapsibleContext, createCollapsibleScope] = createContextScope(CO type CollapsibleContextValue = { contentId: string; + keepChildrenMounted?: boolean; disabled?: boolean; open: boolean; onOpenToggle(): void; @@ -33,6 +34,11 @@ type CollapsibleElement = React.ComponentRef; type PrimitiveDivProps = React.ComponentPropsWithoutRef; interface CollapsibleProps extends PrimitiveDivProps { defaultOpen?: boolean; + /** + * When set to true, children of content will remain mounted when content is + * collapsed. + */ + keepChildrenMounted?: boolean; open?: boolean; disabled?: boolean; onOpenChange?(open: boolean): void; @@ -44,6 +50,7 @@ const Collapsible = React.forwardRef( __scopeCollapsible, open: openProp, defaultOpen, + keepChildrenMounted, disabled, onOpenChange, ...collapsibleProps @@ -59,6 +66,7 @@ const Collapsible = React.forwardRef( return ( - {isOpen && children} + {(isOpen || context.keepChildrenMounted) && children} ); }); From 450123cf5d24af58ddbfa425bedb9f552d986695 Mon Sep 17 00:00:00 2001 From: Mike Interlandi <43190101+Minterl@users.noreply.github.com> Date: Thu, 26 Jun 2025 17:17:58 -0400 Subject: [PATCH 2/6] add prop keepChildrenMounted to accordion --- packages/react/accordion/src/accordion.tsx | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/packages/react/accordion/src/accordion.tsx b/packages/react/accordion/src/accordion.tsx index 4ec048265..d2e25fe88 100644 --- a/packages/react/accordion/src/accordion.tsx +++ b/packages/react/accordion/src/accordion.tsx @@ -196,6 +196,7 @@ type AccordionImplContextValue = { disabled?: boolean; direction: AccordionImplProps['dir']; orientation: AccordionImplProps['orientation']; + keepChildrenMounted?: boolean; }; const [AccordionImplProvider, useAccordionContext] = @@ -219,11 +220,23 @@ interface AccordionImplProps extends PrimitiveDivProps { * The language read direction. */ dir?: Direction; + /** + * When set to true, children of content will remain mounted when content is + * collapsed. + */ + keepChildrenMounted?: boolean; } const AccordionImpl = React.forwardRef( (props: ScopedProps, forwardedRef) => { - const { __scopeAccordion, disabled, dir, orientation = 'vertical', ...accordionProps } = props; + const { + __scopeAccordion, + disabled, + dir, + orientation = 'vertical', + keepChildrenMounted, + ...accordionProps + } = props; const accordionRef = React.useRef(null); const composedRefs = useComposedRefs(accordionRef, forwardedRef); const getItems = useCollection(__scopeAccordion); @@ -307,6 +320,7 @@ const AccordionImpl = React.forwardRef disabled={disabled} direction={dir} orientation={orientation} + keepChildrenMounted={keepChildrenMounted} > {...collapsibleScope} {...accordionItemProps} ref={forwardedRef} + keepChildrenMounted={accordionContext.keepChildrenMounted} disabled={disabled} open={open} onOpenChange={(open) => { From c55cb1f264ea0e35988ecbf85e28c6e80d1a22a4 Mon Sep 17 00:00:00 2001 From: Mike Interlandi <43190101+Minterl@users.noreply.github.com> Date: Thu, 26 Jun 2025 17:38:32 -0400 Subject: [PATCH 3/6] add accordion story for keepChildrenMounted --- apps/storybook/stories/accordion.stories.tsx | 88 ++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/apps/storybook/stories/accordion.stories.tsx b/apps/storybook/stories/accordion.stories.tsx index 6ebe7e99c..5e8ba742e 100644 --- a/apps/storybook/stories/accordion.stories.tsx +++ b/apps/storybook/stories/accordion.stories.tsx @@ -492,6 +492,94 @@ export const Horizontal = () => ( ); +export const KeepChildrenMounted = () => ( + <> +

Single/Uncontrolled

+ + + + One + + + Per erat orci nostra luctus sociosqu mus risus penatibus, duis elit vulputate viverra + integer ullamcorper congue curabitur sociis, nisi malesuada scelerisque quam suscipit + habitant sed. + + + + + Two + + + Cursus sed mattis commodo fermentum conubia ipsum pulvinar sagittis, diam eget bibendum + porta nascetur ac dictum, leo tellus dis integer platea ultrices mi. + + + + + Three (disabled) + + + Sociis hac sapien turpis conubia sagittis justo dui, inceptos penatibus feugiat himenaeos + euismod magna, nec tempor pulvinar eu etiam mattis. + + + + + Four + + + Odio placerat quisque sapien sagittis non sociis ligula penatibus + dignissim vitae, enim vulputate nullam semper potenti etiam volutpat libero. + + + + + +

Multiple/Uncontrolled

+ + + + One + + + Per erat orci nostra luctus sociosqu mus risus penatibus, duis elit vulputate viverra + integer ullamcorper congue curabitur sociis, nisi malesuada scelerisque quam suscipit + habitant sed. + + + + + Two + + + Cursus sed mattis commodo fermentum conubia ipsum pulvinar sagittis, diam eget bibendum + porta nascetur ac dictum, leo tellus dis integer platea ultrices mi. + + + + + Three (disabled) + + + Sociis hac sapien turpis conubia sagittis justo dui, inceptos penatibus feugiat himenaeos + euismod magna, nec tempor pulvinar eu etiam mattis. + + + + + Four + + + Odio placerat quisque sapien sagittis non sociis ligula penatibus + dignissim vitae, enim vulputate nullam semper potenti etiam volutpat libero. + + + + + +); + export const Chromatic = () => { const items = ['One', 'Two', 'Three', 'Four']; return ( From 872f763a6201bd076bf4cbbcc2d6d0ea79f34f9e Mon Sep 17 00:00:00 2001 From: Mike Interlandi <43190101+Minterl@users.noreply.github.com> Date: Thu, 26 Jun 2025 17:47:05 -0400 Subject: [PATCH 4/6] add collapsible story for keepChildrenMounted --- apps/storybook/stories/collapsible.stories.tsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/apps/storybook/stories/collapsible.stories.tsx b/apps/storybook/stories/collapsible.stories.tsx index 64cbcf89a..021fed629 100644 --- a/apps/storybook/stories/collapsible.stories.tsx +++ b/apps/storybook/stories/collapsible.stories.tsx @@ -58,6 +58,16 @@ export const AnimatedHorizontal = () => { ); }; +export const KeepChildrenMounted = () => ( + <> +

With keepChildrenMounted

+ + Trigger + Content 1 + + +); + export const Chromatic = () => ( <>

Uncontrolled

From 4f46c3a96674d2d786f0306797e36f323be3ac53 Mon Sep 17 00:00:00 2001 From: Mike Interlandi <43190101+Minterl@users.noreply.github.com> Date: Thu, 26 Jun 2025 17:57:47 -0400 Subject: [PATCH 5/6] add collapsible tests for keepChildrenMounted --- .../collapsible/src/collapsible.test.tsx | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/packages/react/collapsible/src/collapsible.test.tsx b/packages/react/collapsible/src/collapsible.test.tsx index e5e6c53ee..51f2295c3 100644 --- a/packages/react/collapsible/src/collapsible.test.tsx +++ b/packages/react/collapsible/src/collapsible.test.tsx @@ -108,3 +108,41 @@ describe('given an open controlled Collapsible', () => { }); }); }); + +describe('given a collapsible with keepChildrenMounted', () => { + let rendered: RenderResult; + let content: HTMLElement; + + afterEach(cleanup); + + beforeEach(() => { + rendered = render(); + content = rendered.getByText(CONTENT_TEXT); + }); + + describe('when clicking the trigger', () => { + beforeEach(() => { + const trigger = rendered.getByText(TRIGGER_TEXT); + fireEvent.click(trigger); + }); + + it('should show the content', () => { + expect(content).toBeVisible(); + }) + + describe('and clicking the trigger again', () => { + beforeEach(() => { + const trigger = rendered.getByText(TRIGGER_TEXT); + fireEvent.click(trigger); + }); + + it('should close the content', () => { + expect(content).not.toBeVisible(); + }); + + it('should keep the children mounted', () => { + expect(content).toBeInTheDocument(); + }); + }); + }); +}) From db766a7933d2fe32653f8f36e9bf9c70bf3b720d Mon Sep 17 00:00:00 2001 From: Mike Interlandi <43190101+Minterl@users.noreply.github.com> Date: Thu, 26 Jun 2025 18:19:44 -0400 Subject: [PATCH 6/6] changeset --- .changeset/tame-carpets-strive.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/tame-carpets-strive.md diff --git a/.changeset/tame-carpets-strive.md b/.changeset/tame-carpets-strive.md new file mode 100644 index 000000000..ef6eaef06 --- /dev/null +++ b/.changeset/tame-carpets-strive.md @@ -0,0 +1,6 @@ +--- +'@radix-ui/react-collapsible': minor +'@radix-ui/react-accordion': minor +--- + +add prop keepChildrenMounted