DataTable: Tab and Shift+Tab can't leave a focused table

Closed Beginner friendly
#3,788 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

A pull request for this has already been merged.

  • #3800 by @huacnlee — merged

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
91/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
rust
Domain
accessibility

Research direction

Start with the Tab key bindings and action_select_next_col in crates/component/src/table/data_table.rs, then check the table keyboard shortcut documentation in English and Chinese. Remove Tab and Shift+Tab bindings and document the arrow key behavior; done when focus can leave the table in both directions and the shortcuts match the behavior. Add a regression test in crates/kit/tests/integration.

Written by the indexing model from the issue text.

Description

Description

Once a DataTable has keyboard focus, Tab and Shift+Tab never move focus out of it. A keyboard-only user who tabs into a table can't reach anything after it, or get back to anything before it, without the mouse. This is a keyboard trap (WCAG 2.1.2).

The cause is that the table binds Tab and Shift+Tab to the same actions as → and ← (data_table.rs:28):

KeyBinding::new("tab", SelectNextColumn, Some(CONTEXT)),
KeyBinding::new("shift-tab", SelectPrevColumn, Some(CONTEXT)),

action_select_next_col always handles the action. In row mode it moves the column selection, wrapping with loop_selection, which is on by default. In cell mode it moves to the next cell in the row, wrapping to the row's first cell. So Root's own Tab binding never runs.

Environment

  • GPUI Component: 0.9.0 (also main at b6a815cb)
  • Platform: Windows 11. The headless test below shows it's not platform-specific.

Steps to Reproduce

In a headless test (crates/kit/tests/integration), with a tab stop before and after a DataTable:

window.focus(&before, cx);
window.press("tab", cx);       // the table gets focus, as expected
window.press("tab", cx);       // repeated
window.press("shift-tab", cx);
Key Table focused Next stop focused Selection
Tab (from the stop before) yes
Tab yes no Column(1)
Tab yes no Column(2)
Tab yes no Column(0)
Tab yes no Column(1)
Shift+Tab yes previous stop: no

In an app (a process table on Windows, checked with UI Automation): Tab from the filter box moves focus to the grid. After that, Tab, Shift+Tab and Escape all leave UI Automation's focus on the grid.

Expected

Tab and Shift+Tab move focus to the next or previous control, as for other components. The ARIA grid pattern treats a grid as one Tab stop, with the arrow keys moving inside it. The arrow keys already do everything Tab does here.

Actual

Focus stays in the table, and Tab only changes which column or cell is selected.

The docs also don't match. The Keyboard Shortcuts section doesn't list Tab for row mode, and for cell mode it says Tab moves "to next cell (right, then next row)". In fact it wraps to the first cell of the same row.

Suggested fix

Remove the two Tab bindings, so Tab reaches Root and moves focus, and drop Tab and Shift+Tab from the cell-mode shortcuts in the docs (English and Chinese). → and ← keep the column and cell movement. I can open a PR with a regression test if that sounds right. If you'd rather keep Tab moving between cells in cell mode, an alternative is to call cx.propagate() when the selection is at the last cell (or the first, for Shift+Tab) instead of wrapping.

Dominant language
Rust
Stars
18.9k
Forks
1.2k
Avg merge
1d 3h
Merged PRs (30d)
266

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from longbridge/gpui-kit

All issues in longbridge/gpui-kit

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.