Environment information
Rule name
lint/a11y/noNoninteractiveTabindex
Playground link
https://biomejs.dev/playground/?code=ZQB4AHAAbwByAHQAIABmAHUAbgBjAHQAaQBvAG4AIABUAHIAZQBlAEcAcgBpAGQAKAApACAAewAKACAAIAByAGUAdAB1AHIAbgAgACgACgAgACAAIAAgADwAZABpAHYAIAByAG8AbABlAD0AIgB0AHIAZQBlAGcAcgBpAGQAIgAgAGEAcgBpAGEALQBhAGMAdABpAHYAZQBkAGUAcwBjAGUAbgBkAGUAbgB0AD0AIgBjAGUAbABsAC0AMQAtADIAIgA%2BAAoAIAAgACAAIAAgACAAPABkAGkAdgAgAHIAbwBsAGUAPQAiAGMAbwBsAHUAbQBuAGcAcgBvAHUAcAAiAD4ACgAgACAAIAAgACAAIAAgACAAPABkAGkAdgAgAHIAbwBsAGUAPQAiAHIAbwB3ACIAPgAKACAAIAAgACAAIAAgACAAIAAgACAAPABkAGkAdgAgAGkAZAA9ACIAYwBvAGwALQAxACIAIAByAG8AbABlAD0AIgBjAG8AbAB1AG0AbgBoAGUAYQBkAGUAcgAiACAAdABhAGIASQBuAGQAZQB4AD0AewAwAH0APgBDAG8AbAB1AG0AbgAgADEAPAAvAGQAaQB2AD4ACgAgACAAIAAgACAAIAAgACAAIAAgADwAZABpAHYAIABpAGQAPQAiAGMAbwBsAC0AMgAiACAAcgBvAGwAZQA9ACIAYwBvAGwAdQBtAG4AaABlAGEAZABlAHIAIgAgAHQAYQBiAEkAbgBkAGUAeAA9AHsAMAB9AD4AQwBvAGwAdQBtAG4AIAAyADwALwBkAGkAdgA%2BAAoAIAAgACAAIAAgACAAIAAgACAAIAA8AGQAaQB2ACAAaQBkAD0AIgBjAG8AbAAtADMAIgAgAHIAbwBsAGUAPQAiAGMAbwBsAHUAbQBuAGgAZQBhAGQAZQByACIAIAB0AGEAYgBJAG4AZABlAHgAPQB7ADAAfQA%2BAEMAbwBsAHUAbQBuACAAMwA8AC8AZABpAHYAPgAKACAAIAAgACAAIAAgACAAIAA8AC8AZABpAHYAPgAKACAAIAAgACAAIAAgADwALwBkAGkAdgA%2BAAoAIAAgACAAIAAgACAAPABkAGkAdgAgAHIAbwBsAGUAPQAiAHIAbwB3AGcAcgBvAHUAcAAiACAAdABhAGIASQBuAGQAZQB4AD0AIgAwACIAIABhAHIAaQBhAC0AZQB4AHAAYQBuAGQAZQBkAD0AIgBmAGEAbABzAGUAIgA%2BAAoAIAAgACAAIAAgACAAIAAgADwAZABpAHYAIAByAG8AbABlAD0AIgByAG8AdwAiAD4ACgAgACAAIAAgACAAIAAgACAAIAAgADwAZABpAHYAIABpAGQAPQAiAGMAZQBsAGwALQAxAC0AMQAiACAAcgBvAGwAZQA9ACIAZwByAGkAZABjAGUAbABsACIAIAB0AGEAYgBJAG4AZABlAHgAPQB7ADAAfQA%2BAEEAPAAvAGQAaQB2AD4ACgAgACAAIAAgACAAIAAgACAAIAAgADwAZABpAHYAIABpAGQAPQAiAGMAZQBsAGwALQAxAC0AMgAiACAAcgBvAGwAZQA9ACIAZwByAGkAZABjAGUAbABsACIAIAB0AGEAYgBJAG4AZABlAHgAPQB7ADAAfQA%2BAEIAPAAvAGQAaQB2AD4ACgAgACAAIAAgACAAIAAgACAAIAAgADwAZABpAHYAIABpAGQAPQAiAGMAZQBsAGwALQAxAC0AMwAiACAAcgBvAGwAZQA9ACIAZwByAGkAZABjAGUAbABsACIAIAB0AGEAYgBJAG4AZABlAHgAPQB7ADAAfQA%2BAEMAPAAvAGQAaQB2AD4ACgAgACAAIAAgACAAIAAgACAAPAAvAGQAaQB2AD4ACgAgACAAIAAgACAAIAA8AC8AZABpAHYAPgAKACAAIAAgACAAPAAvAGQAaQB2AD4ACgAgACAAKQA7AAoAfQA%3D
Expected result
Both treegrid and grid are described to work like spreadsheets on the web, where data can be edited and individual cells can be focused within and navigated using arrow keys.
Treegrid takes it one step further and allows expanding/collapsing of rows and columns like a tree.
So when trying to implement focus behavior, this throws an error when it shouldn’t:
// The HTML element div is non-interactive. Do not use tabIndex. (❌ Incorrect)
<div role="gridcell" tabIndex={0}>
~~~~~~~~~~~~
This conflicts with the recommended behavior of treegrid children:
Right Arrow
If focus is on a collapsed row, expand the row. …
In other words, a gridcell MUST be focusable when inside a treegrid if it’s expandable (via tabIndex), and also MUST be able to receive other keyboard commands.
lint/a11y/noNoninteractiveTabindex is correct in other instances, so it seems this is only a problem with grid and treegrid children.
Other notes
- The
useSemanticElements rule does apply to this example but is irrelevant; noNoninteractiveTabindex still raises the same errors
- Worth noting that, yes, by default many gridcells (and related roles) aren’t interactive, this issue is in certain scenarios they ARE REQUIRED to be
- The “roving tabindex” approach is optional here (where only the focusable element receives
tabIndex={0} and everything else gets tabIndex={-1}), but also doesn’t affect the outcome
Code of Conduct
Environment information
Rule name
lint/a11y/noNoninteractiveTabindex
Playground link
https://biomejs.dev/playground/?code=ZQB4AHAAbwByAHQAIABmAHUAbgBjAHQAaQBvAG4AIABUAHIAZQBlAEcAcgBpAGQAKAApACAAewAKACAAIAByAGUAdAB1AHIAbgAgACgACgAgACAAIAAgADwAZABpAHYAIAByAG8AbABlAD0AIgB0AHIAZQBlAGcAcgBpAGQAIgAgAGEAcgBpAGEALQBhAGMAdABpAHYAZQBkAGUAcwBjAGUAbgBkAGUAbgB0AD0AIgBjAGUAbABsAC0AMQAtADIAIgA%2BAAoAIAAgACAAIAAgACAAPABkAGkAdgAgAHIAbwBsAGUAPQAiAGMAbwBsAHUAbQBuAGcAcgBvAHUAcAAiAD4ACgAgACAAIAAgACAAIAAgACAAPABkAGkAdgAgAHIAbwBsAGUAPQAiAHIAbwB3ACIAPgAKACAAIAAgACAAIAAgACAAIAAgACAAPABkAGkAdgAgAGkAZAA9ACIAYwBvAGwALQAxACIAIAByAG8AbABlAD0AIgBjAG8AbAB1AG0AbgBoAGUAYQBkAGUAcgAiACAAdABhAGIASQBuAGQAZQB4AD0AewAwAH0APgBDAG8AbAB1AG0AbgAgADEAPAAvAGQAaQB2AD4ACgAgACAAIAAgACAAIAAgACAAIAAgADwAZABpAHYAIABpAGQAPQAiAGMAbwBsAC0AMgAiACAAcgBvAGwAZQA9ACIAYwBvAGwAdQBtAG4AaABlAGEAZABlAHIAIgAgAHQAYQBiAEkAbgBkAGUAeAA9AHsAMAB9AD4AQwBvAGwAdQBtAG4AIAAyADwALwBkAGkAdgA%2BAAoAIAAgACAAIAAgACAAIAAgACAAIAA8AGQAaQB2ACAAaQBkAD0AIgBjAG8AbAAtADMAIgAgAHIAbwBsAGUAPQAiAGMAbwBsAHUAbQBuAGgAZQBhAGQAZQByACIAIAB0AGEAYgBJAG4AZABlAHgAPQB7ADAAfQA%2BAEMAbwBsAHUAbQBuACAAMwA8AC8AZABpAHYAPgAKACAAIAAgACAAIAAgACAAIAA8AC8AZABpAHYAPgAKACAAIAAgACAAIAAgADwALwBkAGkAdgA%2BAAoAIAAgACAAIAAgACAAPABkAGkAdgAgAHIAbwBsAGUAPQAiAHIAbwB3AGcAcgBvAHUAcAAiACAAdABhAGIASQBuAGQAZQB4AD0AIgAwACIAIABhAHIAaQBhAC0AZQB4AHAAYQBuAGQAZQBkAD0AIgBmAGEAbABzAGUAIgA%2BAAoAIAAgACAAIAAgACAAIAAgADwAZABpAHYAIAByAG8AbABlAD0AIgByAG8AdwAiAD4ACgAgACAAIAAgACAAIAAgACAAIAAgADwAZABpAHYAIABpAGQAPQAiAGMAZQBsAGwALQAxAC0AMQAiACAAcgBvAGwAZQA9ACIAZwByAGkAZABjAGUAbABsACIAIAB0AGEAYgBJAG4AZABlAHgAPQB7ADAAfQA%2BAEEAPAAvAGQAaQB2AD4ACgAgACAAIAAgACAAIAAgACAAIAAgADwAZABpAHYAIABpAGQAPQAiAGMAZQBsAGwALQAxAC0AMgAiACAAcgBvAGwAZQA9ACIAZwByAGkAZABjAGUAbABsACIAIAB0AGEAYgBJAG4AZABlAHgAPQB7ADAAfQA%2BAEIAPAAvAGQAaQB2AD4ACgAgACAAIAAgACAAIAAgACAAIAAgADwAZABpAHYAIABpAGQAPQAiAGMAZQBsAGwALQAxAC0AMwAiACAAcgBvAGwAZQA9ACIAZwByAGkAZABjAGUAbABsACIAIAB0AGEAYgBJAG4AZABlAHgAPQB7ADAAfQA%2BAEMAPAAvAGQAaQB2AD4ACgAgACAAIAAgACAAIAAgACAAPAAvAGQAaQB2AD4ACgAgACAAIAAgACAAIAA8AC8AZABpAHYAPgAKACAAIAAgACAAPAAvAGQAaQB2AD4ACgAgACAAKQA7AAoAfQA%3D
Expected result
Both treegrid and grid are described to work like spreadsheets on the web, where data can be edited and individual cells can be focused within and navigated using arrow keys.
Treegrid takes it one step further and allows expanding/collapsing of rows and columns like a tree.
So when trying to implement focus behavior, this throws an error when it shouldn’t:
This conflicts with the recommended behavior of treegrid children:
In other words, a gridcell MUST be focusable when inside a treegrid if it’s expandable (via
tabIndex), and also MUST be able to receive other keyboard commands.lint/a11y/noNoninteractiveTabindexis correct in other instances, so it seems this is only a problem with grid and treegrid children.Other notes
useSemanticElementsrule does apply to this example but is irrelevant; noNoninteractiveTabindex still raises the same errorstabIndex={0}and everything else getstabIndex={-1}), but also doesn’t affect the outcomeCode of Conduct