DataTable: Tab and Shift+Tab can't leave a focused table
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
mainat 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
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from longbridge/gpui-kit
-
Difficulty 2/5 1-3 hours Newbie friendliness 77/100
longbridge/gpui-kit#3795 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 67/100
longbridge/gpui-kit#3735 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
longbridge/gpui-kit#3711 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 73/100
longbridge/gpui-kit#3630 ·
Maintainers usually reply within 1 day
-
input: allow Editor as the control of an InputGroupMay be free again A pull request for this issue was closed without being merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
longbridge/gpui-kit#3620 ·
Maintainers usually reply within 1 day
All issues in longbridge/gpui-kit
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
madesroches/fontaine#513 ·
Maintainers usually reply within 1 day
-
area:ui needs-triage
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
bherbruck/solvecraft#13497 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
needs-triage tooling
Difficulty 1/5 Under an hour Newbie friendliness 90/100
neilsh/stunt-reel#317 ·
Maintainers usually reply within 1 day
-
Add Noto Sans Thaana (Dhivehi) - missing face blocking Thaana support in PdfCraftPossibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
storytold/craft-fonts#65 ·
Maintainers usually reply within 2 days