Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(table): Add an isKeyboardNavigationDisabled prop to disable the navigation #3735

Open
wants to merge 5 commits into
base: canary
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fluffy-icons-refuse.md
Original file line number Diff line number Diff line change
@@ -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.
2 changes: 1 addition & 1 deletion apps/docs/content/docs/components/table.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand Down
39 changes: 38 additions & 1 deletion packages/components/table/__tests__/table.test.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import * as React from "react";
import {act, render} from "@testing-library/react";
import {act, fireEvent, render} from "@testing-library/react";
import 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"},
Expand Down Expand Up @@ -95,6 +96,42 @@ describe("Table", () => {
expect(wrapper.getAllByRole("gridcell")).toHaveLength(2);
});

it("should disable key navigations when isKeyboardNavigationDisabled is enabled", async () => {
const wrapper = render(
<Table isKeyboardNavigationDisabled={true} selectionMode="single">
<TableHeader>
<TableColumn>Foo</TableColumn>
<TableColumn>Bar</TableColumn>
<TableColumn>Baz</TableColumn>
</TableHeader>
<TableBody>
<TableRow>
<TableCell>Foo 1</TableCell>
<TableCell>Bar 1</TableCell>
<TableCell>Baz 1</TableCell>
</TableRow>
<TableRow>
<TableCell>Foo 2</TableCell>
<TableCell>Bar 2</TableCell>
<TableCell>Baz 2</TableCell>
</TableRow>
</TableBody>
</Table>,
);

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(
<Table aria-label="Dynamic Table">
Expand Down
10 changes: 10 additions & 0 deletions packages/components/table/src/use-table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ interface Props<T> 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.
*/
Expand Down Expand Up @@ -159,6 +164,7 @@ export function useTable<T extends object>(originalProps: UseTableProps<T>) {
layoutNode,
removeWrapper = false,
disableAnimation = globalContext?.disableAnimation ?? false,
isKeyboardNavigationDisabled = false,
selectionMode = "none",
topContentPlacement = "inside",
bottomContentPlacement = "inside",
Expand Down Expand Up @@ -186,6 +192,10 @@ export function useTable<T extends object>(originalProps: UseTableProps<T>) {
showSelectionCheckboxes,
});

if (isKeyboardNavigationDisabled && !state.isKeyboardNavigationDisabled) {
state.setKeyboardNavigationDisabled(true);
}

const {collection} = state;

const {gridProps} = useReactAriaTable<T>({...originalProps, layout: layoutNode}, state, domRef);
Expand Down