Skip to content

Instantly share code, notes, and snippets.

@troygibb
Last active March 31, 2021 02:47
Show Gist options
  • Save troygibb/9be30ae863ea5da4ebdbf58f1eda8f49 to your computer and use it in GitHub Desktop.
Save troygibb/9be30ae863ea5da4ebdbf58f1eda8f49 to your computer and use it in GitHub Desktop.
Description of how we created tabs with react-mosaic

Motivation

Our product, Webviz, often finds itself short of real estate when users attempt to use an increasing number of panels. We also run into performance constraints when rendering so many panels, so we decided to implement tabbed panels to reduce both the visual and compute headaches!

Check out our release PR here to see the feature!

Challenges

The tiling library we rely on, react-mosaic, does not support tabs out of the box, but it does allow nested layouts! So we created a special kind of tile that would render nested layouts, and wrote a tab-like interface on top of it.

Managing the internal state of this layout worked like any other react-mosaic layout. However, things got tricky when we needed to drag a panel from the Tab panel layout over to the main layout (or vice versa). Since react-mosaic relies on mosaicId in its drag handlers to render drop target spaces, these 2 layouts had completely different ids, making any dragging panels between them incompatible.

Furthermore, the information passed to drag handlers is limited - i.e. the handler only receives 2 pieces of information, path and position. path refers to the mosaic layout path to which we would like create the new tile, and position refers to where we would like to render that tile ("top", "bottom", "left", "right"). This info is sufficient for a single layout, but when you don't know which layout you happen to be dragging into or from, you need more information.

Implementation

The first tweak we made to our fork of react-mosaic was creating a mosaicId prop to pass down to a root MosaicDumbWindow component. This newly created MosaicDumbWindow was not wrapped in any kind of drop target logic. That handled the issue of react-mosaic not properly rendering drop target spaces.

To solve the problem of allowing drag handlers to know which layouts we were dragging from and into, we created a new prop, tabId, to pass into the drag handlers. From this prop, the drag handlers could infer whether the drag source was coming from a Tab panel layout, and/or being dragged into a Tab panel layout. For the full nitty-gritty details about this drag and drop logic, check out the links below.

@jtbandes
Copy link

Thanks for the writeup! FYI, I found some workarounds for these issues that allows us to stop using the forked repo: https://github.com/foxglove/studio/pull/410

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment