diff --git a/.changeset/fluffy-icons-refuse.md b/.changeset/fluffy-icons-refuse.md new file mode 100644 index 0000000000..bfde0510a8 --- /dev/null +++ b/.changeset/fluffy-icons-refuse.md @@ -0,0 +1,5 @@ +--- +"@nextui-org/table": patch +--- + +Currently, whenever any arrow-key keypress is triggered it navigates the focus to other cell/row. This creates an issue when the table cell contains a component which requires this keys for specific purpose (eg. if a table cell contains input component, it might need arrow keys for editing. But it is not possible because whenever the keypress triggers navigation). The PR adds an `isKeyboardNavigationDisabled` prop to disable the navigation. diff --git a/apps/docs/content/docs/components/table.mdx b/apps/docs/content/docs/components/table.mdx index 5415aa1e65..230aa89df5 100644 --- a/apps/docs/content/docs/components/table.mdx +++ b/apps/docs/content/docs/components/table.mdx @@ -457,7 +457,7 @@ You can customize the `Table` component by passing custom Tailwind CSS classes t | disableAnimation | `boolean` | Whether to disable the table and checkbox animations. | `false` | | checkboxesProps | [CheckboxProps](/docs/components/checkbox/#checkbox-props) | Props to be passed to the checkboxes. | - | | classNames | `Record<"base" | "table" | "thead" | "tbody" | "tfoot" | "emptyWrapper" | "loadingWrapper" | "wrapper" | "tr" | "th" | "td" | "sortIcon", string>` | Allows to set custom class names for the dropdown item slots. | - | - +| isKeyboardNavigationDisabled | `boolean` | Whether to disable keyboard navigations or not. | `false` | ### Table Events | Attribute | Type | Description | diff --git a/packages/components/table/__tests__/table.test.tsx b/packages/components/table/__tests__/table.test.tsx index 3e1cde7ab1..c58b0b3c82 100644 --- a/packages/components/table/__tests__/table.test.tsx +++ b/packages/components/table/__tests__/table.test.tsx @@ -1,8 +1,10 @@ import * as React from "react"; -import {act, render} from "@testing-library/react"; +import {act, render, fireEvent} from "@testing-library/react"; import userEvent, {UserEvent} from "@testing-library/user-event"; + import {Table, TableHeader, TableCell, TableColumn, TableBody, TableRow} from "../src"; +import {keyCodes} from "../../../utilities/test-utils/src"; const columns = [ {name: "Foo", key: "foo"}, @@ -101,6 +103,42 @@ describe("Table", () => { expect(wrapper.getAllByRole("gridcell")).toHaveLength(2); }); + it("should disable key navigations when isKeyboardNavigationDisabled is enabled", async () => { + const wrapper = render( + + + Foo + Bar + Baz + + + + Foo 1 + Bar 1 + Baz 1 + + + Foo 2 + Bar 2 + Baz 2 + + +
, + ); + + const row1 = wrapper.getAllByRole("row")[1]; + + // selecting the row1 + await act(async () => { + await userEvent.click(row1); + }); + expect(row1).toHaveFocus(); + + // triggering the arrow down on row1 should not shift the focus to row2 + fireEvent.keyDown(row1, {key: "ArrowDown", keyCode: keyCodes.ArrowDown}); + expect(row1).toHaveFocus(); + }); + it("should render dynamic table", () => { const wrapper = render( diff --git a/packages/components/table/src/use-table.ts b/packages/components/table/src/use-table.ts index b6aa81ed2b..00a5847cf9 100644 --- a/packages/components/table/src/use-table.ts +++ b/packages/components/table/src/use-table.ts @@ -90,6 +90,11 @@ interface Props extends HTMLNextUIProps<"table"> { * @default false */ disableAnimation?: boolean; + /** + * Whether to disable the keyboard navigation functionality. + * @default false + */ + isKeyboardNavigationDisabled?: boolean; /** * Props to be passed to the checkboxes. */ @@ -158,6 +163,7 @@ export function useTable(originalProps: UseTableProps) { classNames, removeWrapper = false, disableAnimation = globalContext?.disableAnimation ?? false, + isKeyboardNavigationDisabled = false, selectionMode = "none", topContentPlacement = "inside", bottomContentPlacement = "inside", @@ -185,6 +191,10 @@ export function useTable(originalProps: UseTableProps) { showSelectionCheckboxes, }); + if (isKeyboardNavigationDisabled && !state.isKeyboardNavigationDisabled) { + state.setKeyboardNavigationDisabled(true); + } + const {collection} = state; // Exclude the layout prop because it has a name conflict and is deprecated in useTable.