Skip to content

Commit

Permalink
fix(accordion): allow cursor navigation within text (#3419)
Browse files Browse the repository at this point in the history
* fix(accordion): allow cursor navigation within text

* fix: wrong issue number
  • Loading branch information
ryo-manba authored Jul 6, 2024
1 parent ec7c417 commit 106752a
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 12 deletions.
5 changes: 5 additions & 0 deletions .changeset/funny-fishes-try.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@nextui-org/accordion": patch
---

Fixed cursor navigation within text (#2152, #3364)
69 changes: 59 additions & 10 deletions packages/components/accordion/__tests__/accordion.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import * as React from "react";
import {act, render} from "@testing-library/react";
import {focus} from "@nextui-org/test-utils";
import userEvent from "@testing-library/user-event";
import userEvent, {UserEvent} from "@testing-library/user-event";
import {Input} from "@nextui-org/input";

import {Accordion, AccordionItem} from "../src";

Expand All @@ -10,6 +11,12 @@ import {Accordion, AccordionItem} from "../src";
const spy = jest.spyOn(console, "error").mockImplementation(() => {});

describe("Accordion", () => {
let user: UserEvent;

beforeEach(() => {
user = userEvent.setup();
});

afterEach(() => {
jest.clearAllMocks();
});
Expand Down Expand Up @@ -115,7 +122,7 @@ describe("Accordion", () => {
expect(button).toHaveAttribute("aria-expanded", "false");

await act(async () => {
await userEvent.click(button);
await user.click(button);
});

expect(button).toHaveAttribute("aria-expanded", "true");
Expand Down Expand Up @@ -161,12 +168,12 @@ describe("Accordion", () => {
});

await act(async () => {
await userEvent.keyboard("[ArrowDown]");
await user.keyboard("[ArrowDown]");
});
expect(secondButton).toHaveFocus();

await act(async () => {
await userEvent.keyboard("[ArrowUp]");
await user.keyboard("[ArrowUp]");
});
expect(firstButton).toHaveFocus();
});
Expand Down Expand Up @@ -194,12 +201,12 @@ describe("Accordion", () => {
});

await act(async () => {
await userEvent.keyboard("[Home]");
await user.keyboard("[Home]");
});
expect(firstButton).toHaveFocus();

await act(async () => {
await userEvent.keyboard("[End]");
await user.keyboard("[End]");
});
expect(secondButton).toHaveFocus();
});
Expand Down Expand Up @@ -227,7 +234,7 @@ describe("Accordion", () => {
});

await act(async () => {
await userEvent.keyboard("[Tab]");
await user.keyboard("[Tab]");
});
expect(secondButton).toHaveFocus();
});
Expand Down Expand Up @@ -270,7 +277,7 @@ describe("Accordion", () => {
expect(button).toHaveAttribute("aria-expanded", "false");

await act(async () => {
await userEvent.click(button);
await user.click(button);
});

expect(button).toHaveAttribute("aria-expanded", "true");
Expand All @@ -294,17 +301,59 @@ describe("Accordion", () => {
expect(item1.querySelector("[role='region']")).toBeInTheDocument();

await act(async () => {
await userEvent.click(button);
await user.click(button);
});

const item2 = wrapper.getByTestId("item-2");
const button2 = item2.querySelector("button") as HTMLElement;

await act(async () => {
await userEvent.click(button2);
await user.click(button2);
});

expect(item1.querySelector("[role='region']")).toBeInTheDocument();
expect(item2.querySelector("[role='region']")).toBeInTheDocument();
});

it("should handle arrow key navigation within Input inside AccordionItem", async () => {
const wrapper = render(
<Accordion defaultExpandedKeys={["1"]}>
<AccordionItem key="1" title="Accordion Item 1">
<Input label="name" type="text" />
</AccordionItem>
<AccordionItem key="2" title="Accordion Item 2">
Accordion Item 2 description
</AccordionItem>
</Accordion>,
);

const input = wrapper.getByLabelText("name");

const firstButton = await wrapper.getByRole("button", {name: "Accordion Item 1"});

await act(() => {
focus(firstButton);
});
await act(async () => {
await user.keyboard("[Tab]");
});
expect(input).toHaveFocus();

await act(async () => {
await user.keyboard("aaa");
});
expect(input).toHaveValue("aaa");

await act(async () => {
await user.keyboard("[ArrowLeft]");
await user.keyboard("b");
});
expect(input).toHaveValue("aaba");

await act(async () => {
await user.keyboard("[ArrowRight]");
await user.keyboard("c");
});
expect(input).toHaveValue("aabac");
});
});
6 changes: 6 additions & 0 deletions packages/components/accordion/src/accordion-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ const AccordionItem = forwardRef<"button", AccordionItemProps>((props, ref) => {
initial="exit"
style={{willChange}}
variants={transitionVariants}
onKeyDown={(e) => {
e.stopPropagation();
}}
{...motionProps}
>
<div {...getContentProps()}>{children}</div>
Expand All @@ -85,6 +88,9 @@ const AccordionItem = forwardRef<"button", AccordionItemProps>((props, ref) => {
initial="exit"
style={{willChange}}
variants={transitionVariants}
onKeyDown={(e) => {
e.stopPropagation();
}}
{...motionProps}
>
<div {...getContentProps()}>{children}</div>
Expand Down
4 changes: 2 additions & 2 deletions packages/components/accordion/stories/accordion.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
InvalidCardIcon,
} from "@nextui-org/shared-icons";
import {Avatar} from "@nextui-org/avatar";
import {Input} from "@nextui-org/input";
import {Input, Textarea} from "@nextui-org/input";
import {Button} from "@nextui-org/button";

import {Accordion, AccordionProps, AccordionItem, AccordionItemProps} from "../src";
Expand Down Expand Up @@ -354,7 +354,7 @@ const WithFormTemplate = (args: AccordionProps) => {
}
/>
<Input isRequired label="Password" placeholder="Enter your password" type="password" />

<Textarea label="Message" placeholder="Enter your message" />
<div className="flex gap-2 justify-end">
<button className={button({color: "primary"})}>Login</button>
</div>
Expand Down

0 comments on commit 106752a

Please sign in to comment.