---
# System prepended metadata

title: Pivot Overflow
tags: [pitch]

---

---
robots: noindex, nofollow
tags: pitch
---
# Pivot Overflow

### Problem
When the tabs in a pivot control are too wide to fit onscreen, they are truncated with no affordance to allow the user to get to the rightmost tabs. This is [Issue 4066](https://github.com/microsoft/fluentui/issues/4066).

There are several potential solutions used by Tabs-type controls in other UI:
* *Carousel*: Add horizontal scrolling to the tabs
* *Wrap*: Put tabs on multiple rows so that all are visible
* *Overflow*: Show a menu to show the tabs that don't fit

This project will tackle implementing *Overflow*.

![](https://user-images.githubusercontent.com/20363037/61396560-d4bbcf80-a87c-11e9-86b2-87d7f7c8c30f.png)

### Appetite
2 weeks

### Solution

The implementation can be broken down into a few parts:

#### A. Determine which tabs to show in the overflow menu

The tabs in the menu will include any that would not be fully visible.

One option is to use **ResizeGroup**; however, David has concerns about its method for rendering offscreen to measure, which causes issues with element refs.

Another option is to write a hook to figure out which tabs are clipped. Here's an outline from David:
```typescript=
// use this to find the index of the child which is not fully visible in the container.
const useFindClippedChildIndex = (containerRef) => {
  const [clippedChildIndex, setClippedChildIndex] = React.useState(-1);
  React.useEffect(() => {
    // This will be called on every render, so maybe this should be debounced
    const boundingRect = containerRef.current.getBoundingClientRect();
    const childNodes = Array.from(containerRef.current.childNodes)
    for (const child of childNodes) {
      if (!rectContains(boundingRect, child.getBoundingClientRect()) {
        if (index !== clippedChildIndex) {
          setClippedChildIndex(index);
        }
        break;
      }
    }
  });
  return clippedChildIndex;
};
```
This could be optimized 
* iterate backwards
* break on first visible
* cache measures in a map
* debounce/throttle (`useAsync`?)

Sync with Miro to find concepts to pull from toolbar.

* ResizeObserver to detect when the pivot element resized (no IE11 support)
* Hook to resize useOverflow?
    * Eval when:
        * selected item changes
        * window size
        * resize observer
        * 
    * Re-eval when selected item changes
* OverflowMenu: Render PivotItem as a ContextualMenuItem

#### B. Render the overflow menu
It may be possible to render the overflow menu using an **OverflowSet**, depending on how feasible it is to refactor the tabs to use OverflowSet.

An alternative option is to simply add a button for the overflow, which shows a standard menu on click.

### Risks (Rabbit holes)
Deciding which of the above implementations (ResizeGroup/OverflowSet vs. custom implementations) to use could in itself take up extra time.

The nitty gritty details of measuring and picking which items go in the overflow menu could be somewhat complicated. For example, the active tab item always needs to be shown (even if it would normally be in the overflow), and that reduces the amount of available space to render the rest of the items.

### Out of scope (No-gos)
It may be nice to eventually implement the other scaling options for when the tabs don't fit (Carousel and Wrap), but that is out of scope for this project.