{"id":15649199,"url":"https://github.com/konsalex/table-nav","last_synced_at":"2025-04-14T03:14:37.720Z","repository":{"id":177603175,"uuid":"610854660","full_name":"konsalex/table-nav","owner":"konsalex","description":"Headless data grid (table) keyboard navigation library","archived":false,"fork":false,"pushed_at":"2023-07-27T14:10:00.000Z","size":40730,"stargazers_count":49,"open_issues_count":5,"forks_count":2,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-14T03:14:25.010Z","etag":null,"topics":["accessibility","javascript","keyboard","navigation","react","table"],"latest_commit_sha":null,"homepage":"https://konsalex.github.io/table-nav/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/konsalex.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-03-07T16:04:39.000Z","updated_at":"2025-04-03T15:31:03.000Z","dependencies_parsed_at":null,"dependency_job_id":"70e40aa9-b1b9-4db6-a411-f1ad139e457d","html_url":"https://github.com/konsalex/table-nav","commit_stats":null,"previous_names":["konsalex/table-nav"],"tags_count":20,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/konsalex%2Ftable-nav","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/konsalex%2Ftable-nav/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/konsalex%2Ftable-nav/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/konsalex%2Ftable-nav/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/konsalex","download_url":"https://codeload.github.com/konsalex/table-nav/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248813802,"owners_count":21165634,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["accessibility","javascript","keyboard","navigation","react","table"],"created_at":"2024-10-03T12:28:50.830Z","updated_at":"2025-04-14T03:14:37.691Z","avatar_url":"https://github.com/konsalex.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n    \u003cimg width=\"200\" src=\"https://github.com/konsalex/table-nav/raw/main/assets/logo.png\"/\u003e\n\u003c/p\u003e\n\n\u003ch2 align=\"center\" style=\"margin-top:-20px\"\u003etable-nav\u003c/h2\u003e\n\n**table-nav is a headless utility library, that enables accessible keyboard navigation of data grids (aka tables).**\n\nThe ARIA specs for data grid navigation can be found here:\n\n\u003ca href=\"https://www.w3.org/WAI/ARIA/apg/patterns/grid/\"\u003e\u003cimg src=\"https://github.com/konsalex/table-nav/raw/main/assets/w3c.png\" height=\"auto\" width=\"80\"\u003e\u003c/a\u003e\n\n\u003cimg src=\"https://github.com/konsalex/table-nav/raw/main/assets/demo.gif\" /\u003e\n\n**table-nav** consists of:\n* `core`: Contains all the logic of the library, which is framework-agnostic\n* `react`: Useful wrappers to work with React projects\n* `svelte` (soon): Useful wrappers to work with Svelte projects. [Example link](https://codesandbox.io/p/sandbox/interesting-cdn-7krjys?embed=1\u0026file=%2Fsrc%2FApp.svelte%3A140%2C20)\n\n\n### Installation\n\n```bash\nyarn add @table-nav/core @table-nav/react\n```\n\n### Usage\n\nTo use this library you can either use directly the `core` package or the `react` package.\n\n#### Core\n\nBelow is an example on how you can use the `core` package in a simple HTML table.\nThis package is framework-agnostic, and you can find an example integration with [Svelte here](https://codesandbox.io/p/sandbox/interesting-cdn-7krjys?embed=1\u0026file=%2Fsrc%2FApp.svelte%3A132%2C31-132%2C43).\n\n```js\n// DataGridNav is the main class of the library\nimport { DataGridNav } from \"@table-nav/core\";\n\n// Create a new instance of the class\nconst dataGridNav = new DataGridNav({\n  // Library is written in TS and all the options will be recommended inside your IDE\n  debug: true,\n});\n\n// Use the function provided by the library to handle the keydown/up events\ntable.addEventListener(\"keydown\", dataGridNav.tableKeyDown);\ntable.addEventListener(\"keyup\", dataGridNav.tableKeyUp); // This is neccessery to allow more than 1 key shortcuts\n```\n\n#### React\n\nFor projects using react, `@table-nav/react` provides a useful hook to work with.\n\n\n```jsx\n// Import hook from \"@table-nav/react\"\nimport { useTableNav } from '@table-nav/react';\n\n// Inside your HOC component\nconst { tableNav, listeners } = useTableNav();\n\n\u003cYourTable {...listeners} /\u003e\n```\n\n`useTableNav` returns an object with 2 properties:\n* `tableNav`: An instance of the `DataGridNav` class. Useful for programmatic navigation, and enabling/disabling the functionality for use-cases, like widget focus inside cell.\n* `listeners`: An object with the `onKeyDown` and `onKeyUp` listeners, that you can spread inside your table element.\n\nAll the examples inside [`packages/storybook`](https://github.com/konsalex/table-nav/tree/main/packages/storybook/stories) are with `@table-nav/react`, so feel free to take a look how they work.\n\n### Grid Navigation\n\n| Key                                                       | Description                                                                                                                                                                                                                           |\n|-----------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| \u003cimg width=\"200px\"  src=\"https://github.com/konsalex/table-nav/raw/main/assets/keys/ArrowRight.png\"/\u003e  | Moves focus one cell to the right. If focus is on the right-most cell in the row, focus does not move.                                                                                                                                |\n| \u003cimg width=\"200px\"  src=\"https://github.com/konsalex/table-nav/raw/main/assets/keys/ArrowLeft.png\"/\u003e   | Moves focus one cell to the left. If focus is on the left-most cell in the row, focus does not move.                                                                                                                                  |\n| \u003cimg width=\"200px\"  src=\"https://github.com/konsalex/table-nav/raw/main/assets/keys/ArrowUp.png\"/\u003e     | Moves focus one cell up. If focus is on the top cell in the column, focus does not move.                                                                                                                                              |\n| \u003cimg width=\"200px\"  src=\"https://github.com/konsalex/table-nav/raw/main/assets/keys/ArrowDown.png\"/\u003e   | Moves focus one cell down. If focus is on the bottom cell in the column, focus does not move.                                                                                                                                         |\n| \u003cimg width=\"200px\"  src=\"https://github.com/konsalex/table-nav/raw/main/assets/keys/PageDown.png\"/\u003e    | Moves focus down an author-determined number of rows, typically scrolling so the bottom row in the currently visible set of rows becomes one of the first visible rows. If focus is in the last row of the grid, focus does not move. |\n| \u003cimg width=\"200px\"  src=\"https://github.com/konsalex/table-nav/raw/main/assets/keys/PageUp.png\"/\u003e      | Moves focus up an author-determined number of rows, typically scrolling so the top row in the currently visible set of rows becomes one of the last visible rows. If focus is in the first row of the grid, focus does not move.      |\n| \u003cimg width=\"200px\"  src=\"https://github.com/konsalex/table-nav/raw/main/assets/keys/Home.png\"/\u003e        | Moves focus to the first cell in the row that contains focus.                                                                                                                                                                         |\n| \u003cimg width=\"200px\"   src=\"https://github.com/konsalex/table-nav/raw/main/assets/keys/End.png\"/\u003e        | Moves focus to the last cell in the row that contains focus.                                                                                                                                                                          |\n| \u003cimg width=\"200px\"  src=\"https://github.com/konsalex/table-nav/raw/main/assets/keys/ControlHome.png\"/\u003e | Moves focus to the first cell in the first row.                                                                                                                                                                                       |\n| \u003cimg width=\"200px\"   src=\"https://github.com/konsalex/table-nav/raw/main/assets/keys/ControlEnd.png\"/\u003e | Moves focus to the first cell in the last row.                                                                                                                                                                                        |\n| \u003cimg width=\"200px\"   src=\"https://github.com/konsalex/table-nav/raw/main/assets/keys/Enter.png\"/\u003e      | Disables grid navigation and focuses on the first focusable element in the cell. If there are no focusable elements in the cell.                                                                                                      |\n\n\n\n### Cell Navigation\n\n\u003e **Note**\n\u003e WTF (What the focus) is going on. There is no standardised way to know what is actually focusable in the web.\n\u003e To comply with this lib and work properly, you need to add a `tabindex` attribute explicitly to the elements you want to be focusable, inside a cell, except for `input` and `textarea` elements.\n\n| Key                                                          | Description                                                                                                                                                                                                                                                                                                                                  |\n|--------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| \u003cimg width=\"200px\"   src=\"https://github.com/konsalex/table-nav/raw/main/assets/keys/Escape.png\"/\u003e        | Restores grid navigation.                                                                                                                                                                                                                                                                                                                    |\n| \u003cimg width=\"200px\"  src=\"https://github.com/konsalex/table-nav/raw/main/assets/keys/ArrowRightDown.png\"/\u003e | If the cell contains multiple widgets, moves focus to the next widget inside the cell, optionally wrapping to the first widget if focus is on the last widget. Otherwise, passes the key event to the focused widget.\u003cbr/\u003e`Arrow Down` is disabled [issue](https://github.com/w3c/aria-practices/issues/2739#issuecomment-1613538972)        |\n| \u003cimg width=\"200px\"  src=\"https://github.com/konsalex/table-nav/raw/main/assets/keys/ArrowLeftUp.png\"/\u003e    | If the cell contains multiple widgets, moves focus to the previous widget inside the cell, optionally wrapping to the first widget if focus is on the last widget. Otherwise, passes the key event to the focused widget.     \u003cbr/\u003e`Arrow Up` is disabled [issue](https://github.com/w3c/aria-practices/issues/2739#issuecomment-1613538972) |\n\n\n\u003e The below keystrokes are supported natively by browsers, so they are not implement\n\n- `Tab`: moves focus to the next widget in the grid. Optionally, the focus movement may wrap inside a single cell or within the grid itself. (As described, there should be no trap focus inside a grid cell).\n- `Shift + Tab`: moves focus to the previous widget in the grid. Optionally, the focus movement may wrap inside a single cell or within the grid itself.\n\n---\n\n### Known issues 🐝\n\n1. Vertical navigation needs to be a bit smarter: [video](https://share.cleanshot.com/W7QBb0NV)\n2. WTF (what the focus) should happen in cell navigation, when you stumble an input? [Related issue](https://github.com/elastic/eui/issues/3334#issuecomment-616603058)\n\n\n### Contributions\n\nIf you want a feature that is not supported or found a bug that you want to fix, fork the repo, and then make a PR with your proposed changes. Still a small project so there are no strict guidelines.\n\n### Useful links 📚\n\n1. https://www.w3.org/WAI/ARIA/apg/patterns/grid/\n2. https://www.ag-grid.com/example/\n3. https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values\n4. https://github.com/ETSOO/Shared/blob/master/src/Keyboard.ts\n5. https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/no-noninteractive-element-interactions.md\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkonsalex%2Ftable-nav","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkonsalex%2Ftable-nav","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkonsalex%2Ftable-nav/lists"}