3

We've implemented React-Vitualized using single column Grid with rows that are enabled for keyboard event (onKeyUp/onKeyDown/onKeyPress). We are using Arrow-Key-Stepper to enable ArrowUp/ArrowDown scrolling of the rows.

All works quite well even with PgUp/PgDn, Home/End, Space and Shift-Space. However, when we add either tabIndex and/or contenteditable attributes to the rows (required for keyboard events), scrolling freezes when the focused rows scrolls out-of-view and removed from the DOM. We can regain control by using Tab key and/or the mouse.

QUESTION: Why is tabIndex/contenteditable attributes causing scrolling failure?

I am not allowed to reproduce the code publicly. Not asking for solution nor code but more an opinion from a more experienced source. This is the last issue for our implementation of this widget library, which has been very good thus far.

Appreciate any suggest/opinion.

1 Answers1

1

However, when we add either tabIndex and/or contenteditable attributes to the rows (required for keyboard events), scrolling freezes when the focused rows scrolls out-of-view and removed from the DOM.

I'm curious why the rows themselves need this attribute? The outer container rendered by ArrowKeyStepper has a tab-index, in order to be focusable. This is how ArrowKeyStepper listens to keyboard events.

If the row is focused, then when it goes out of the viewport, ArrowKeyStepper is left listening to ... nothing. The way to fix this is to use a class component to render your cell and conditionally self-focusing:

class Cell extends Component {
  componentDidMount = () => this._maybeFocus();
  componentDidUpdate = () => this._maybeFocus();

  render() {
    const {
      columnIndex,
      rowIndex,
      scrollToColumn,
      scrollToRow,
      style,
    } = this.props;

    return (
      <div
        style={style}
        ref={this._setRef}
        tabIndex={1}
      >
        {/* Your content here... */}
      </div>
    );
  };

  _maybeFocus = () => {
    const {
      columnIndex,
      rowIndex,
      scrollToColumn,
      scrollToRow,
    } = this.props;

    if (
      columnIndex === scrollToColumn &&
      rowIndex === scrollToRow
    ) {
      this._ref.focus();
    }
  }

  _setRef = ref => {
    this._ref = ref;
  };
}
bvaughn
  • 13,300
  • 45
  • 46
  • Thanks for quick response. Our use case requires the ability for users to select a row/multiple rows (using Tab/Arrows/Mouse/Tap) and when hitting 'Enter' triggers submit of the selected content. We also do use standard submit button outside the list, but keyboard only functionality is really important for the client. – Richard O'Brien Nov 20 '17 at 18:53