From 606f75726c6b273ea25528ec3269fa6e82af3349 Mon Sep 17 00:00:00 2001 From: ryoon Date: Fri, 27 Sep 2024 01:53:59 +0900 Subject: [PATCH] fix(input): ensure clear button is not focusable when disabled (#3774) * fix(input): ensure clear button is not focusable when disabled * test(input): add test to ensure clear button is not focusable when disabled * chore: add changeset for clear button focus fix when input is disabled * fix(input): update clear button to use button element * test(input): add focus test when disabled and update tests for clear button using button element * test(input): replace querySelector with getByRole for clear button * fix(input): set tabIndex to -1 for clear button * test(input): ensure clear button is not focusable --- .changeset/two-waves-own.md | 5 +++++ .../components/input/__tests__/input.test.tsx | 22 ++++++++++++++++--- packages/components/input/src/input.tsx | 2 +- packages/components/input/src/use-input.ts | 5 +++-- 4 files changed, 28 insertions(+), 6 deletions(-) create mode 100644 .changeset/two-waves-own.md diff --git a/.changeset/two-waves-own.md b/.changeset/two-waves-own.md new file mode 100644 index 0000000000..8c534e7b7f --- /dev/null +++ b/.changeset/two-waves-own.md @@ -0,0 +1,5 @@ +--- +"@nextui-org/input": patch +--- + +clear button should not receive focus when input is disabled. diff --git a/packages/components/input/__tests__/input.test.tsx b/packages/components/input/__tests__/input.test.tsx index 23859a06d5..5f967d25fb 100644 --- a/packages/components/input/__tests__/input.test.tsx +++ b/packages/components/input/__tests__/input.test.tsx @@ -37,6 +37,22 @@ describe("Input", () => { expect(container.querySelector("input")).toHaveAttribute("disabled"); }); + it("should disable the clear button when isDisabled", () => { + const {getByRole} = render(); + + const clearButton = getByRole("button"); + + expect(clearButton).toBeDisabled(); + }); + + it("should not allow clear button to be focusable", () => { + const {getByRole} = render(); + + const clearButton = getByRole("button"); + + expect(clearButton).toHaveAttribute("tabIndex", "-1"); + }); + it("should have required attribute when isRequired with native validationBehavior", () => { const {container} = render(); @@ -141,7 +157,7 @@ describe("Input", () => { />, ); - const clearButton = getByRole("button"); + const clearButton = getByRole("button")!; expect(clearButton).not.toBeNull(); @@ -197,7 +213,7 @@ describe("Input", () => { />, ); - const clearButton = getByRole("button"); + const clearButton = getByRole("button")!; expect(clearButton).not.toBeNull(); @@ -256,7 +272,7 @@ describe("Input with React Hook Form", () => { input1 = document.querySelector("input[name=withDefaultValue]")!; input2 = document.querySelector("input[name=withoutDefaultValue]")!; input3 = document.querySelector("input[name=requiredField]")!; - submitButton = document.querySelector("button")!; + submitButton = document.querySelector('button[type="submit"]')!; }); it("should work with defaultValues", () => { diff --git a/packages/components/input/src/input.tsx b/packages/components/input/src/input.tsx index 9414472494..10c5ecf10e 100644 --- a/packages/components/input/src/input.tsx +++ b/packages/components/input/src/input.tsx @@ -36,7 +36,7 @@ const Input = forwardRef<"input", InputProps>((props, ref) => { const end = useMemo(() => { if (isClearable) { - return {endContent || }; + return ; } return endContent; diff --git a/packages/components/input/src/use-input.ts b/packages/components/input/src/use-input.ts index 256c75b8ec..26e0e15eff 100644 --- a/packages/components/input/src/use-input.ts +++ b/packages/components/input/src/use-input.ts @@ -510,8 +510,9 @@ export function useInput { return { ...props, - role: "button", - tabIndex: 0, + type: "button", + tabIndex: -1, + disabled: originalProps.isDisabled, "aria-label": "clear input", "data-slot": "clear-button", "data-focus-visible": dataAttr(isClearButtonFocusVisible),