glin / reactable

Interactive data tables for R
https://glin.github.io/reactable
Other
613 stars 79 forks source link

Support for virtualized tables #203

Open hafen opened 2 years ago

hafen commented 2 years ago

Thanks for this awesome package.

As an alternative to pagination, it would be nice to support the ability to scroll the whole table with a sticky header and virtualized rows.

glin commented 2 years ago

Hi, I agree, and virtualized tables have been somewhere on my own wishlist for a while. I've seen that example in the React Table docs, but just haven't had time to explore it more.

Although the example looks pretty simple in those docs, there will probably be a significant amount of extra work to make the virtual scrolling properly accessible. From quick testing, keyboard navigation doesn't work at all - up/down arrow keys get stuck, page up/down doesn't work, and the home/end keys don't work reliably. react-window doesn't provide keyboard navigation out of the box, and it looks like you're supposed to implement it yourself (https://github.com/bvaughn/react-window/issues/46).

We'll also have to add the aria-rowindex attribute to rows and the aria-rowcount attribute to the table, to indicate the off-screen row indices and row count to screen readers. I would want to test these attributes across different browser/screen reader combinations to ensure they're widely supported, as I haven't come across many resources on the supportability of these ARIA attributes.

Besides that, there may be other accessibility issues to consider, like described at https://github.com/WICG/virtual-scroller.

So I think this is worth researching in the near/mid-term, but implementing it properly could be challenging.

bbt-dev commented 2 years ago

Thanks a lot for the development of the reactable package!

I don't know exactly whether the following items related to the virtualized tables, but it seems very similar.

I would like to suggest to provide a functionality by which a table produced by the reactable will adjust to the iframe height, keeping in mind that the iframe could be changed dinamically from the parent page by JS. This is actual because in most cases the tables produced by reactable are embedded as iframes (to avoid any conflicts in JS with the parent page environment). Now it is possible to set up the height of the table produced by reactable in px, and then embed it in an iframe of the same height. But there is an obstacle in this mechanism related to a fixed height of a reactable table, as explained below.

Sometimes (actually rather often for summary tables) it is better to use reactable table without pagination - and reactable allows to do this. This full-length tables has a fixed height. Initially we show this full-length table in the iframe. But then for a user it could be convenient to expand the iframe by clicking on the href linked to a JS function making iframe_obj.height = "1000"; (or something like iframe_obj.height = iframe_obj.contentWindow.document.body.scrollHeight;) and to see all the table. However, the aforementioned JS will increase the height of iframe, but the height of the reactable table will remain the same. For example, if initially both reactable table and iframe had height 300px, even if we increase the iframe height to 1000px, the height of the reactable table will remain 300 px and it will float at the top of increased iframe. It would be very nice to have a setting during the production in R that allows to make the reactable table that will adjust its height after increasing the iframe height - in that case a user could expand or contract the iframe as required, and always see the reactable table inside the whole iframe.

To provide a reproducible example, this is the content of the parent html:

<html>

<script type="application/javascript">

function resize_iframe_height( iframe_id ) {
    var iframe_obj = document.getElementById( iframe_id );
    iframe_obj.height = "1000";//iframe_obj.contentWindow.document.body.scrollHeight;
}

</script>

  <a href="#" onclick="resize_iframe_height('reactable_produced_content');return false;" title="Click to Expand iframe">
    Expand iframe
  </a>
  <iframe src="html_produced_by_reactable.html" width = 100% height = 300px id = "reactable_produced_content"></iframe>
</html>

I am not very strong in JS, but performed some search, and it seems that React could allow this dinamic resizing::