mirror of
https://github.com/nextui-org/nextui.git
synced 2025-12-08 19:26:11 +00:00
fix(accordion): allow cursor navigation within text (#3419)
* fix(accordion): allow cursor navigation within text * fix: wrong issue number
This commit is contained in:
parent
ec7c417387
commit
106752aaef
5
.changeset/funny-fishes-try.md
Normal file
5
.changeset/funny-fishes-try.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"@nextui-org/accordion": patch
|
||||
---
|
||||
|
||||
Fixed cursor navigation within text (#2152, #3364)
|
||||
@ -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";
|
||||
|
||||
@ -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();
|
||||
});
|
||||
@ -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");
|
||||
@ -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();
|
||||
});
|
||||
@ -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();
|
||||
});
|
||||
@ -227,7 +234,7 @@ describe("Accordion", () => {
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await userEvent.keyboard("[Tab]");
|
||||
await user.keyboard("[Tab]");
|
||||
});
|
||||
expect(secondButton).toHaveFocus();
|
||||
});
|
||||
@ -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");
|
||||
@ -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");
|
||||
});
|
||||
});
|
||||
|
||||
@ -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>
|
||||
@ -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>
|
||||
|
||||
@ -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";
|
||||
@ -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>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user