You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hi @fabianonunes! If you set the overacanCount prop, it will render that number of off-canvas buffer rows before and after the visible rows. This also has the effect of enabling tab scrolling. That should make your list fully tab navigable.
Hi, Jason!
I think it's not that simple, because when the DOM element is recycled for another item, the current focus is lost.
Consider a list with 10 visible items and overscanCount={10}. When the 18th item is focused, the next TAB could motivate a scroll, recycling all nodes and the old focus is lost.
@fabianonunes Yeah :( I had posted that and then started fiddling with the JSFiddle and realized the recycling kills it. I did manage to get it working, but it requires a little bit of effort! First, I added a focus listener to each row and persisted the currently focussed row id (just the index in this case) in the demo component's state. When rendering a given row (now a <Row> component), a focussed boolean can then be passed in as a prop that tells the row if it is currently the focussed item. If it is, after rendering it invokes .focus() on itself.
Second, in order to make shift+tab work, I added a componentDidUpdate() hook that just calls the DOM .scrollIntoViewIfNeeded() method on whichever row is focussed. This scrolls the off-canvas rendered "-1th" item into view where there browser does not (it is not outside the default bounds for the browser's own focus scrolling behavior).
@developit This solution won't work if (i) the component's root isn't a focusable element, (ii) we have two focusable elements by <Row/>.
We could save the document.activeElement reference before render and reinforce focus on componentDidUpdate. But in this case, we need keyed children (to avoid reuse).
For the first one, I think just adding tabIndex="0" to each row would make them focussable.
For keyed children though, that sortof defeats the optimization here. Your document.activeElement technique is definitely on the right track though....
Activity
developit commentedon Sep 8, 2016
Hi @fabianonunes! If you set the
overacanCountprop, it will render that number of off-canvas buffer rows before and after the visible rows. This also has the effect of enabling tab scrolling. That should make your list fully tab navigable.Let me know if that works for you!
fabianonunes commentedon Sep 9, 2016
Hi, Jason!
I think it's not that simple, because when the DOM element is recycled for another item, the current focus is lost.
Consider a list with 10 visible items and overscanCount={10}. When the 18th item is focused, the next TAB could motivate a scroll, recycling all nodes and the old focus is lost.
Same example, but with overscanCount={30}
https://jsfiddle.net/gnL63f5d/
developit commentedon Sep 9, 2016
@fabianonunes Yeah :( I had posted that and then started fiddling with the JSFiddle and realized the recycling kills it. I did manage to get it working, but it requires a little bit of effort! First, I added a focus listener to each row and persisted the currently focussed row
id(just the index in this case) in the demo component'sstate. When rendering a given row (now a<Row>component), afocussedboolean can then be passed in as a prop that tells the row if it is currently the focussed item. If it is, after rendering it invokes.focus()on itself.Second, in order to make shift+tab work, I added a
componentDidUpdate()hook that just calls the DOM.scrollIntoViewIfNeeded()method on whichever row is focussed. This scrolls the off-canvas rendered "-1th" item into view where there browser does not (it is not outside the default bounds for the browser's own focus scrolling behavior).Here's the working JSFiddle with the above two modifications in place:
https://jsfiddle.net/developit/83h1jb2u/5/
Sorry this is so convoluted! I'd love to see something cleaner.
fabianonunes commentedon Sep 9, 2016
@developit This solution won't work if (i) the component's root isn't a focusable element, (ii) we have two focusable elements by
<Row/>.We could save the
document.activeElementreference before render and reinforce focus oncomponentDidUpdate. But in this case, we need keyed children (to avoid reuse).Check here: https://jsfiddle.net/Lgd86uaw/2/
Diff: fabianonunes@aedbd1
developit commentedon Sep 9, 2016
For the first one, I think just adding
tabIndex="0"to each row would make them focussable.For keyed children though, that sortof defeats the optimization here. Your document.activeElement technique is definitely on the right track though....
fabianonunes commentedon Sep 9, 2016
Yes. Keyed elements has a impact on perfomance. It's not an alternative.
developit commentedon Sep 9, 2016
@fabianonunes Also I just realized - if the user scrolls the list using the mouse wheel / flick, hitting tab again uses the shifted viewport :(
I'm actually thinking overriding tab is the only way to go here.