fix(accordion): keepContentMounted with disableAnimation (#5172)

* fix(accordion): keepContentMounted with disableAnimation

* feat(accordion): add test cases

* fix(accordion): use waitFor
This commit is contained in:
աӄա 2025-04-19 23:24:17 +08:00 committed by GitHub
parent 500ed771e2
commit 531518f2ef
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 103 additions and 4 deletions

View File

@ -0,0 +1,5 @@
---
"@heroui/accordion": patch
---
fixed keepContentMounted with disableAnimation (#5157)

View File

@ -1,6 +1,6 @@
import "@testing-library/jest-dom";
import * as React from "react";
import {act, render} from "@testing-library/react";
import {act, render, waitFor} from "@testing-library/react";
import {focus, shouldIgnoreReactWarning, spy} from "@heroui/test-utils";
import userEvent, {UserEvent} from "@testing-library/user-event";
import {Input} from "@heroui/input";
@ -267,7 +267,7 @@ describe("Accordion", () => {
expect(button).toHaveAttribute("aria-expanded", "true");
});
it("should support keepContentMounted", async () => {
it("should support keepContentMounted={true}", async () => {
const wrapper = render(
<Accordion keepContentMounted>
<AccordionItem key="1" data-testid="item-1" title="Accordion Item 1">
@ -289,9 +289,99 @@ describe("Accordion", () => {
const button2 = item2.querySelector("button") as HTMLElement;
await user.click(button2);
await waitFor(() => {
expect(item1.querySelector("[role='region']")).toBeInTheDocument();
expect(item2.querySelector("[role='region']")).toBeInTheDocument();
});
});
it("should support keepContentMounted={false}", async () => {
const wrapper = render(
<Accordion keepContentMounted={false}>
<AccordionItem key="1" data-testid="item-1" title="Accordion Item 1">
Accordion Item 1 description
</AccordionItem>
<AccordionItem key="2" data-testid="item-2" title="Accordion Item 2">
Accordion Item 2 description
</AccordionItem>
</Accordion>,
);
const item1 = wrapper.getByTestId("item-1");
const button = item1.querySelector("button") as HTMLElement;
expect(item1.querySelector("[role='region']")).not.toBeInTheDocument();
await user.click(button);
const item2 = wrapper.getByTestId("item-2");
const button2 = item2.querySelector("button") as HTMLElement;
await user.click(button2);
await waitFor(() => {
expect(item1.querySelector("[role='region']")).not.toBeInTheDocument();
expect(item2.querySelector("[role='region']")).toBeInTheDocument();
});
});
it("should support keepContentMounted={true} & disableAnimation={true}", async () => {
const wrapper = render(
<Accordion disableAnimation keepContentMounted>
<AccordionItem key="1" data-testid="item-1" title="Accordion Item 1">
Accordion Item 1 description
</AccordionItem>
<AccordionItem key="2" data-testid="item-2" title="Accordion Item 2">
Accordion Item 2 description
</AccordionItem>
</Accordion>,
);
const item1 = wrapper.getByTestId("item-1");
const button = item1.querySelector("button") as HTMLElement;
expect(item1.querySelector("[role='region']")).toBeInTheDocument();
await user.click(button);
const item2 = wrapper.getByTestId("item-2");
const button2 = item2.querySelector("button") as HTMLElement;
await user.click(button2);
await waitFor(() => {
expect(item1.querySelector("[role='region']")).toBeInTheDocument();
expect(item2.querySelector("[role='region']")).toBeInTheDocument();
});
});
it("should support keepContentMounted={false} & disableAnimation={true}", async () => {
const wrapper = render(
<Accordion disableAnimation keepContentMounted={false}>
<AccordionItem key="1" data-testid="item-1" title="Accordion Item 1">
Accordion Item 1 description
</AccordionItem>
<AccordionItem key="2" data-testid="item-2" title="Accordion Item 2">
Accordion Item 2 description
</AccordionItem>
</Accordion>,
);
const item1 = wrapper.getByTestId("item-1");
const button = item1.querySelector("button") as HTMLElement;
expect(item1.querySelector("[role='region']")).not.toBeInTheDocument();
await user.click(button);
const item2 = wrapper.getByTestId("item-2");
const button2 = item2.querySelector("button") as HTMLElement;
await user.click(button2);
await waitFor(() => {
expect(item1.querySelector("[role='region']")).not.toBeInTheDocument();
expect(item2.querySelector("[role='region']")).toBeInTheDocument();
});
});
it("should handle arrow key navigation within Input inside AccordionItem", async () => {
const wrapper = render(

View File

@ -54,9 +54,13 @@ const AccordionItem = forwardRef<"button", AccordionItemProps>((props, ref) => {
const content = useMemo(() => {
if (disableAnimation) {
if (keepContentMounted) {
return <div {...getContentProps()}>{children}</div>;
}
return isOpen && <div {...getContentProps()}>{children}</div>;
}
const transitionVariants: Variants = {
exit: {...TRANSITION_VARIANTS.collapse.exit, overflowY: "hidden"},
enter: {...TRANSITION_VARIANTS.collapse.enter, overflowY: "unset"},