Implementation Story
The Notebook Toolbar
({{, }})

Noah Hardwicke (UX and UI teams)

Contents

Overview of the toolbar

Principal implementation challenges in WL

Review of some relevant front end constructs

Use this toolbox to solve the implementation challenges

Toolbar Overview

UX of the toolbar to be discussed in the UX talk

Implementation challenges: control overflow and popup alignment

Issue 1: Overflow

We want:

Discrete elision of a row of items

To know which items have been elided

To put these items into an overflow menu

Module[{construct,itemsList},

itemsList=Show[#,ImageSize->{Automatic,100},ImagePadding->{{5,5},{0,0}},BaselinePosition->Center]&/@{,,,,,,,};

construct[items_List, lineSpacing_?NumericQ]:=

Module[{widths,makeOvButton,overflowButtons,assembly,taggingRules},

(* Calculate the item widths *)
widths=Rasterize[#,"BoundingBox"][[1]]&/@items;

(* Function: create an overflow button given its index i, such that items i and greater are in its overflow menu, and item i-1 is attached to it. *)
makeOvButton=Function[i,
With[
(* Populate the overflow menu: *)
{contents=Table[
With[{str=ToString[j]},
Dynamic[CurrentValue[{TaggingRules,"Items",str}],DestroyAfterEvaluation->True]]:>Null(*Action*),
{j,i,Length[items]}],
(* Retrieve the item to attach: *)
attachedItem=With[{str=ToString[i-1]},
Dynamic[CurrentValue[{TaggingRules,"Items",str}],DestroyAfterEvaluation->True]]},

(* First overflow button does not need to attach an item: *)
If[i===1,#,
DynamicModule[{},#,
Initialization:>
AttachCell[EvaluationBox[],attachedItem,Left,Automatic,Right]]]&@
(* Last overflow button gets replaced with the last item: *)
If[i===Length[items],
Dynamic[CurrentValue[{TaggingRules,"Items",ToString[i]}],DestroyAfterEvaluation->True],
Pane[#,FrameMargins->{{5,5},{0,0}},BaselinePosition->Center]&@
ActionMenu[,contents,Appearance->"Frameless",BaselinePosition->Center]]]];

(* Overflow buttons are 100pts wide (and all items are >= 100pts). Find difference between item and overflow button widths, and a corresponding spacer to the right of the overflow button. *)
(* Also provide each overflow button with its position index for populating its overflow menu and knowing which item to attach. *)
overflowButtons=Flatten@MapIndexed[
Function[{width, i},
{makeOvButton[First[i]],Spacer[{width-110,0}]}],
widths];

(* Wrap the items in Row, and constrict the view to the first line only with Pane and opts *)
assembly=Pane[Row[overflowButtons],
{Automatic,100},
Alignment->Top,
ScrollPosition->Dynamic[{0,0},None],
BaseStyle->{
LinebreakAdjustments->{10,1,1,10,10},LineIndent->0,
LineSpacing->{lineSpacing,0}}];

(* Construct tagging rules to store the item boxes in the final cell *)
taggingRules=Association@MapIndexed[
Function[{item,i},ToString[First[i]]->item],
items];

(* Construct the final cell *)
Deploy@RawBoxes@Cell[
BoxData[ToBoxes[assembly]],
TaggingRules-><|"Items"->taggingRules|>]];

@construct[itemsList,1000]]

But there is no “OverflowBox” that does this!

What Tools do we Have?

Features and box generators that could be helpful:

Pane, PaneSelector

DynamicModule + Initialization, DynamicWrapper

CurrentValue, AbsoluteCurrentValue, MousePosition

Attached cells:

AttachCell[parent,cell,alignmentParent,offset,alignmentContent]

Examples:

AttachCell[EvaluationCell[],"WTC 2022",Left,0,Left,
RemovalConditions->{"OutsideMouseClick"}]

AttachCell[EvaluationNotebook[],"WTC 2022",Right,0,Right]

NotebookDelete[%]

Overflow: Suboptimal Solution

Use a DynamicWrapper to track the window width.

If we know the item widths, we can calculate which items to hide (using PaneSelectors).

Details and Implementation

Outline

Find the widths of each item

Either require explicit widths, or use:

Rasterize[item,"BoundingBox"]

Calculate which controls should be hidden for a given window width

Dynamically track the window width

DynamicWrapper[toolbar,w=AbsoluteCurrentValue[{WindowWidth,1}]]

Use PaneSelectors to switch elided items to zero-width spacers

PaneSelector[
{False->item,True->Spacer[0]},
Dynamic[w<479]]

Code

items={1,2,3,4,5,6,7,8};

Module[{widths,panes,overflowButton,offset=50},

(* Calculate the item widths *)
widths=Rasterize[#,"BoundingBox"][[1]]&/@items;


(* We'll use a Pane to constrain the items. Set its initial dims: *)
DynamicModule[{w = 800,h=100},

(* Use PaneSelectors to collapse each item when w is less than the corresponding running total width *)
panes=MapThread[

Function[{item,width},
PaneSelector[
{False->item,True->Spacer[0]},Dynamic[w<width],
ImageSize->Automatic]],

{items,Accumulate[widths]+offset}];


(* The overflow button compares w against the running total widths to determine which items to display *)
overflowButton=PaneSelector[

{True->Button[,,],
False->Spacer[0]},

With[{maxW=Total[widths]+offset},
Dynamic[w<maxW]],
ImageSize->Automatic];

(* Dynamically track the pane width *)
Framed@Pane[
Row[Append[panes,overflowButton]],
ImageSize->Dynamic[{w,h}],
AppearanceElements->"ResizeArea"]]]

Reason for Inefficiency

All these Dynamics fire when the Pane is resized:

ImageSize->Dynamic[{w,h}]

PaneSelector[
{False->item1,True->Spacer[0]},Dynamic[w<width1]]

PaneSelector[
{False->item2,True->Spacer[0]},Dynamic[w<width2]]

...

Optimization of the Dynamic calculations can only get us so far

We want to minimize the number of Dynamics used

Inefficiencies are created by instances of Dynamic, so minimize the number of Dynamics used.

Overflow: Solution Without Dynamics

Exploit boxes that don’t rely on Dynamics to achieve their effects

Item Elision by Linebreaking

Use Pane, Alignment and ScrollPosition to view only the first line of items

Use LinebreakingAdjustments to get the desired linebreaking

row=Highlighted@Pane[
Row[],{Automatic,Automatic(*50*)},
Alignment->Top,
ScrollPosition->Dynamic[{0,0},None],
BaseStyle->{
LinebreakAdjustments->{10,1,1,10,10},LineIndent->0}];

(Note that Dynamic[{0,0}, None] specifies no dynamic updating)

[row]

Overflow: Solution Without Dynamics

Instead of a row of items, let’s start with a row of overflow buttons:

Pane[Pane[#,{1050,Automatic},FrameMargins->{{6,0},{0,7}}],{Full,Automatic},ImageSizeAction->"ResizeToFit"]&@
Row[Table[Pane[Overlay[{Framed[Pane[,{100,100},Alignment->{Center,Center},ContentPadding->False],FrameMargins->None,
Background->],Row[{Spacer[5],i}]},Alignment->{Left,Top}],FrameMargins->{{8,8},{0,0}}],{i,5}]]

Overflow: Solution Without Dynamics

Now cover the overflow buttons with the row of items:

Pane[Pane[#,{1050,Automatic},FrameMargins->{{6,0},{0,7}}],{Full,Automatic},ImageSizeAction->"ResizeToFit"]&@
With[
{
d=150,
overflows=Row[Table[Pane[Overlay[{Framed[Pane[,{100,100},Alignment->{Center,Center},ContentPadding->False],FrameMargins->None,
Background->],Row[{Spacer[5],i}]},Alignment->{Left,Top}],FrameMargins->{{8,8},{0,0}}],{i,5}]],
items=Row[Table[Pane[Framed[Pane[i,{100,100},Alignment->{Center,Center},ContentPadding->False],FrameMargins->None,
Background->],FrameMargins->{{8,8},{0,0}}],{i,4}]]},

DynamicModule[{t=0},
Column[{
Overlay[
{
Pane[overflows,FrameMargins->{{0,0},{d,0}}],
Pane[items,FrameMargins->Dynamic[{{0,0},{0,d(1-Sin[π/2t])}}]]},
{1,2},
Alignment->{Top,Left},FrameMargins->None],
Trigger[Dynamic[t],{0,1},1.35,AppearanceElements->{"TriggerButton","ResetButton"}]},
Alignment->Right],Initialization:>(t=0)]]

Overflow: Solution Without Dynamics

Connect the (n^th) item to the (((n+1))^th) overflow button:

Pane[Pane[#,{1050,Automatic}],{Full,Automatic},ImageSizeAction->"ResizeToFit"]&@
With[
{
overflows=Table[Pane[Overlay[{Framed[Pane[,{100,100},Alignment->{Center,Center},ContentPadding->False],FrameMargins->None,
Background->],Row[{Spacer[5],i}]},Alignment->{Left,Top}],FrameMargins->{{8,8},{0,0}}],{i,5}],
items=Table[Pane[Framed[Pane[i,{100,100},Alignment->{Center,Center},ContentPadding->False],FrameMargins->None,
Background->],FrameMargins->{{8,8},{0,0}}],{i,4}]},

@Pane[
Row@MapThread[
Function[{item,overflow,i},
Pane[
Row[{item,overflow,Pane[Graphics[{Disk[{-1,0},.25],Thickness[.05],Line[{{-1,0},{1,0}}],Disk[{1,0},.25]},ImageSize->45],
ImageMargins->{{-141,96},{0,0}}]}],ImageMargins->{{0,-118},{0,0}},BaseStyle->{LineBreakWithin->False}]],
{items,overflows[[2;;]],Range[Length[items]]}],
ImageMargins->{{0,118},{0,0}},
BaseStyle->{
LinebreakAdjustments->{10,1,1,10,10},LineIndent->0}]]

We don’t need the last overflow button, so replace it with the last item...

Overflow: Solution Without Dynamics

Pane[Pane[Magnify[#,.8],{1050,Automatic}],{Full,Automatic},ImageSizeAction->"ResizeToFit"]&@
Grid[{{
Pane[DynamicModule[{t=0,s=1},
Column[{
Module[
{
overflows=Table[Pane[Overlay[{Framed[Pane[,{100,100},Alignment->{Center,Center},ContentPadding->False],FrameMargins->None,
Background->],Row[{Spacer[5],i}]},Alignment->{Left,Top}],FrameMargins->{{8,8},{0,0}}],
{i,5}],
items=Table[Pane[Framed[Pane[i,{100,100},Alignment->{Center,Center},ContentPadding->False],FrameMargins->None,
Background->],FrameMargins->{{8,8},{0,0}}],
{i,5}],
pairs},

overflows=ReplacePart[overflows,-1->items[[-1]]];

items=ReplacePart[items,{
3->PaneSelector[
{
False->items[[3]],
True->Framed["",ImageSize->{10,100},ImageMargins->
{{1.75,.25}(110-10)/2-{76-50,0},{0,0}},
Background->]},
Dynamic[s===2],ImageSize->Automatic]}];

overflows=ReplacePart[overflows,
3->PaneSelector[
{
False->overflows[[3]],
True->Framed["",ImageSize->{10,100},ImageMargins->{{.22,1.92}(110-10)/2-{0,50},{0,0}},Background->]},
Dynamic[s===2],ImageSize->Automatic]];

items=items[[;;-2]];

pairs=MapThread[
Function[{item,overflow,i},
Pane[
Row[{item,overflow,Pane[Graphics[{Disk[{-1,0},.25],Thickness[.05],Line[{{-1,0},{1,0}}],Disk[{1,0},.25]},ImageSize->45],
ImageMargins->Dynamic@{If[i===2&&s===2,{-141+50,-50},{-141,0}],{0,0}}]}],
ImageMargins->{{0,-118},{0,0}},
FrameMargins->Dynamic@{{0,96},{0,t 140(i-1)}},
BaselinePosition->Top]],
{items,overflows[[2;;]],Range[Length[items]]}];

pairs=ReplacePart[pairs,{
2->PaneSelector[
{
False->pairs[[2]],
True->Replace[pairs[[2]],
(ImageMargins->{{l_,r_},{b_,u_}}):>ImageMargins->{{l,r},{b,u}},
1]},
Dynamic[s===2],ImageSize->Automatic],

3->PaneSelector[
{
False->pairs[[3]],
True->Pane[
Row[{Framed["",ImageSize->{10,100},Background->],
Framed["",ImageSize->{10,100},Background->]}],
FrameMargins->Dynamic@{{0,96},{0,t 140(3-1)}},
ImageMargins->{{100,-170},{0,0}},
BaselinePosition->Top]},
Dynamic[s===3],ImageSize->Automatic],

4->PaneSelector[
{
False->pairs[[4]],
True->Replace[
ReplacePart[pairs[[4]],
{1,1}->Prepend[pairs[[4,1,1]],
Framed["",ImageSize->{22,102},Background->White,ImageMargins->{{99,-99-22},{0,0}},FrameStyle->White]]],
(ImageMargins->{{l_,r_},{b_,u_}}):>ImageMargins->{{l-46,r},{b,u}},
1]},
Dynamic[s===3],ImageSize->Automatic]}];

@Pane[
Row@pairs,
{Automatic,Automatic},
ImageMargins->{{0,118},{0,0}},
ScrollPosition->Dynamic[{0,0},None],
BaseStyle->{
LinebreakAdjustments->{10,1,1,10,10},LineIndent->0,LineSpacing->{100,0}}]],

(*Row[{
RadioButtonBar[Dynamic[s],#1->Pane[#2,BaselinePosition->Center]&@@@{1->"○",2->"×",3->"✓"},ImageMargins->0,BaselinePosition->Center],
Spacer[30],
Slider[Dynamic[t],{0,1},BaselinePosition->Center]}]*)
Slider[Dynamic[t],{0,1},BaselinePosition->Center]},

Alignment->Left],

Initialization:>(t=0; s=1)],{700,700},ScrollPosition->Dynamic[{0,0},None]],

Magnify[Column[RawBoxes[RowBox[{StyleBox[StyleBox[AdjustmentBox["•",BoxBaselineShift->-0.3`],Alignment->Top,FontColor->,Magnification->0.7`],"Item",FontSize->30],Append[#,FontSize->44]}]]&/@{Cell[TextData[{"An ",StyleBox["overflow button",FontColor->]," breaks away"}],"Item",CellMargins->,CellChangeTimes->{{3.870100323064288`*^9,3.870100338384926`*^9},{3.870100665873967`*^9,3.870100675643697`*^9},{3.870102989248291`*^9,3.870103005278224`*^9},{3.87010606412125`*^9,3.870106083878395`*^9},{3.8701061427251`*^9,3.87010624116215`*^9},{3.870106319132308`*^9,3.870106319351912`*^9},3.870153461682057`*^9,{3.8749208704590197`*^9,3.8749208711793957`*^9}}],Cell[TextData[{"It takes the left-adjacent ",StyleBox["item",FontColor->]," with it"}],"Item",CellMargins->,CellChangeTimes->{{3.870100323064288`*^9,3.870100338384926`*^9},{3.870100665873967`*^9,3.870100675643697`*^9},{3.870102989248291`*^9,3.870103005278224`*^9},{3.87010606412125`*^9,3.870106083878395`*^9},{3.8701061427251`*^9,3.870106278285685`*^9},{3.870153454869569`*^9,3.870153469355866`*^9},3.8749208719186783`*^9,{3.8749209724952793`*^9,3.874920973332192`*^9}}],Cell[TextData[{"The next ",StyleBox["overflow button",FontColor->]," is revealed"}],"Item",CellMargins->,CellChangeTimes->{{3.870100323064288`*^9,3.870100338384926`*^9},{3.870100665873967`*^9,3.870100675643697`*^9},{3.870102989248291`*^9,3.870103005278224`*^9},{3.87010606412125`*^9,3.870106083878395`*^9},{3.8701061427251`*^9,3.8701062871644583`*^9},3.8701534647321463`*^9,3.8749208740643597`*^9,{3.8749209750933847`*^9,3.87492097546651`*^9}}]},Alignment->Left],.8]}},

ItemSize->{{Fit,Automatic}},Alignment->{Left,Top}]

Overflow: Solution Without Dynamics

Connect items to overflow buttons with AttachCell

The items need to cover the overflow buttons

Overflow buttons are parents, items are attached cells:

DynamicModule[{},(RowDefault[(Spacer1), 8]),
Initialization:>
AttachCell[EvaluationBox[],7,Left,Automatic,Right]]

Overflow: Solution Without Dynamics

Implementation details:

Outline

Find the widths of each item (require explicit or use Rasterize)

Rasterize[item,"BoundingBox"]

Generate a list of overflow buttons, and either:

match the button widths to the item widths,

or add spacers to the list to match the item widths.

{OvButton1, Spacer[s1],OvButton2, Spacer[s2],...}

Use DynamicModule, Initialization and AttachCell to attach the (n^th) item to the (((n+1))^th) overflow button

The last button/item is a special case

Constrain the Row of items with a Pane, and set appropriate Alignment, ScrollPosition and LinebreakingAdjustments

Pane[Row[OvButtons],{Automatic,height},
Alignment->Top,
ScrollPosition->Dynamic[{0,0},None],
BaseStyle->{LinebreakAdjustments->{10,1,1,10,10}}]

Parameterize Out the Items

Avoid repeatedly storing boxes in each overflow button by parameterizing out the items.

Could store items in a DynamicModule variable, and load with Initialization

With[{boxes=ToBoxes[items]},
DynamicModule[{items},Pane[...],Initialization:>(items=boxes)]]

Retrieve items with Dynamic[items[[i]]]

Could store items as TaggingRules on the enclosing cell (inline/docked/attached)

RawBoxes@Cell[
BoxData[ToBoxes[Pane[...]]],
TaggingRules-><|"Item1"->...,"Item2"->...|>]

Retrieve items with Dynamic[CurrentValue[{TaggingRules, "Item1"}]]

The option DestroyAfterEvaluation can be added to Dynamic to remove the DynamicBox wrapper after it resolves.

The Notebook Toolbar uses FrontEndResource to retrieve items from Text Resource files. Potentially relevant if you’re authoring a paclet.

Code

(Evaluation time is lengthened by rasterizing each item — we could require the widths be specified to avoid this)

items={1,2,3,4,5,6,7,8};

construct[lineSpacing_?NumericQ]:=

Module[{widths,makeOvButton,overflowButtons,assembly,taggingRules},

(* Calculate the item widths *)
widths=Rasterize[#,"BoundingBox"][[1]]&/@items;

(* Function: create an overflow button given its index i, such that items i and greater are in its overflow menu, and item i-1 is attached to it. *)
makeOvButton=Function[i,
With[
(* Populate the overflow menu: *)
{contents=Table[
With[{str=ToString[j]},
Dynamic[CurrentValue[{TaggingRules,"Items",str}],DestroyAfterEvaluation->True]]:>Null(*Action*),
{j,i,Length[items]}],
(* Retrieve the item to attach: *)
attachedItem=With[{str=ToString[i-1]},
Dynamic[CurrentValue[{TaggingRules,"Items",str}],DestroyAfterEvaluation->True]]},

(* First overflow button does not need to attach an item: *)
If[i===1,#,
DynamicModule[{},#,
Initialization:>
AttachCell[EvaluationBox[],attachedItem,Left,Automatic,Right]]]&@
(* Last overflow button gets replaced with the last item: *)
If[i===Length[items],
Dynamic[CurrentValue[{TaggingRules,"Items",ToString[i]}],DestroyAfterEvaluation->True],
Pane[#,FrameMargins->{{5,5},{0,0}}]&@
ActionMenu[,contents,Appearance->"Frameless"]]]];

(* Overflow buttons are 60pts wide (and all items are >= 60pts). Find difference between item and overflow button widths, and a corresponding spacer to the right of the overflow button. *)
(* Also provide each overflow button with its position index for populating its overflow menu and knowing which item to attach. *)
overflowButtons=Flatten@MapIndexed[
Function[{width, i},
{makeOvButton[First[i]],Spacer[{width-60,0}]}],
widths];

(* Wrap the items in Row, and constrict the view to the first line only with Pane and opts *)
assembly=Pane[Row[overflowButtons],
{Automatic,50+2},
Alignment->Top,
ScrollPosition->Dynamic[{0,0},None],
BaseStyle->{
LinebreakAdjustments->{10,1,1,10,10},LineIndent->0,
LineSpacing->{lineSpacing,0}}];

(* Construct tagging rules to store the item boxes in the final cell *)
taggingRules=Association@MapIndexed[
Function[{item,i},ToString[First[i]]->item],
items];

(* Construct the final cell *)
Deploy@RawBoxes@Cell[
BoxData[ToBoxes[assembly]],
TaggingRules-><|"Items"->taggingRules|>]];

[construct[1.5]]

Overflow: Solution Without Dynamics

[construct[1.5]]

This almost works. And it contains no Dynamic updating (after Initializations fire).

...But we can still see the attached cells even when their parents are hidden by the Pane.

Hack: we could increase LineSpacing to some enormous number.

[construct[100]]

When the containing interface is known not to exceed a certain height, increasing the LineSpacing is a perfectly reasonable solution.

Overflow: Solution Without Dynamics

Recall that the docked cell area clips attached cells

The toolbar is only one line tall, so the LineSpacing solution works

NotebookPut@
Notebook[{},,
DockedCells->Cell[
BoxData@ToBoxes@construct[1.5],
CellSize->Dynamic[{Automatic,h}],
LineBreakWithin->Automatic]];

Overflow: Solution Without Dynamics

Compare this to the notebook toolbar:

Dynamically Hide/Show Items

The efficiency gains we’ve made allow us to use Dynamics elsewhere

E.g. Dynamic item hiding/showing:

Add a DynamicWrapper to track the relevant state

DynamicModule[{state},
DynamicWrapper[toolbar,state=CurrentValue[...]]]

Use PaneSelectors to swap an item and overflow button to zero-width spacers

PaneSelector[{x->item,y->Spacer[{0,0}]},Dynamic[state],
ImageSize->Automatic]

PaneSelector[{x->overflowButton,y->Spacer[{0,0}]},Dynamic[state],
ImageSize->Automatic]

Dynamically Hide/Show Items

Suppose we want to hide item 3:

Pane[Pane[Magnify[#,.9],{1050,Automatic}],{Full,Automatic},ImageSizeAction->"ResizeToFit"]&@
DynamicModule[{t=0,s=1},
Column[{
Module[
{
overflows=Table[Pane[Overlay[{Framed[Pane[,{100,100},Alignment->{Center,Center},ContentPadding->False],FrameMargins->None,
Background->],Row[{Spacer[5],i}]},Alignment->{Left,Top}],FrameMargins->{{8,8},{0,0}}],
{i,5}],
items=Table[Pane[Framed[Pane[i,{100,100},Alignment->{Center,Center},ContentPadding->False],FrameMargins->None,
Background->],FrameMargins->{{8,8},{0,0}}],
{i,5}],
pairs},

overflows=ReplacePart[overflows,-1->items[[-1]]];

items=ReplacePart[items,{
3->PaneSelector[
{
False->items[[3]],
True->Framed["",ImageSize->{10,100},ImageMargins->
{{1.75,.25}(110-10)/2-{76-50,0},{0,0}},
Background->]},
Dynamic[s===2],ImageSize->Automatic]}];

overflows=ReplacePart[overflows,
3->PaneSelector[
{
False->overflows[[3]],
True->Framed["",ImageSize->{10,100},ImageMargins->{{.22,1.92}(110-10)/2-{0,50},{0,0}},Background->]},
Dynamic[s===2],ImageSize->Automatic]];

items=items[[;;-2]];

pairs=MapThread[
Function[{item,overflow,i},
Pane[
Row[{item,overflow,Pane[Graphics[{Disk[{-1,0},.25],Thickness[.05],Line[{{-1,0},{1,0}}],Disk[{1,0},.25]},ImageSize->45],
ImageMargins->Dynamic@{If[i===2&&s===2,{-141+50,-50},{-141,0}],{0,0}}]}],
ImageMargins->{{0,-118},{0,0}},
FrameMargins->Dynamic@{{0,96},{0,t 140(i-1)}},
BaselinePosition->Top]],
{items,overflows[[2;;]],Range[Length[items]]}];

pairs=ReplacePart[pairs,{
2->PaneSelector[
{
False->pairs[[2]],
True->Replace[pairs[[2]],
(ImageMargins->{{l_,r_},{b_,u_}}):>ImageMargins->{{l,r},{b,u}},
1]},
Dynamic[s===2],ImageSize->Automatic],

3->PaneSelector[
{
False->pairs[[3]],
True->Pane[
Row[{Framed["",ImageSize->{10,100},Background->],
Framed["",ImageSize->{10,100},Background->]}],
FrameMargins->Dynamic@{{0,96},{0,t 140(3-1)}},
ImageMargins->{{100,-170},{0,0}},
BaselinePosition->Top]},
Dynamic[s===3],ImageSize->Automatic],

4->PaneSelector[
{
False->pairs[[4]],
True->Replace[
ReplacePart[pairs[[4]],
{1,1}->Prepend[pairs[[4,1,1]],
Framed["",ImageSize->{22,102},Background->White,ImageMargins->{{99,-99-22},{0,0}},FrameStyle->White]]],
(ImageMargins->{{l_,r_},{b_,u_}}):>ImageMargins->{{l-46,r},{b,u}},
1]},
Dynamic[s===3],ImageSize->Automatic]}];

@Pane[
Row@pairs,
{Automatic,Automatic},
ImageMargins->{{0,118},{0,0}},
ScrollPosition->Dynamic[{0,0},None],
BaseStyle->{
LinebreakAdjustments->{10,1,1,10,10},LineIndent->0,LineSpacing->{100,0}}]],

Row[{
RadioButtonBar[Dynamic[s],#1->Pane[#2,BaselinePosition->Center]&@@@{1->"○",2->"×",3->"✓"},ImageMargins->0,BaselinePosition->Center],
Spacer[30],
Slider[Dynamic[t],{0,1},BaselinePosition->Center]}]},

Alignment->Left],

Initialization:>(t=0; s=1)]

We must hide attached pairs of items and overflow buttons
(i.e. the (n^th) item and the (((n+1))^th) overflow button)

Other things to note

Overflow buttons or spacing elements must expand/contract if items are different widths

Attaching a cell is expensive, so instead of destroying it when hiding the item, just turn it into a zero-width Spacer:

DynamicModule[{},PaneSelector[{x->overflowButton,y->Spacer[0]},Dynamic[state],
ImageSize->Automatic],
Initialization:>
AttachCell[EvaluationBox[],
PaneSelector[{x->item,y->Spacer[0]},Dynamic[state],
ImageSize->Automatic],
...]]

Issue 2: Popup Alignment

Docked cells and the notebook body are separate content areas

AttachCell[,,];

AttachCell[,,];

Effective anchor points:

Pane[Pane[#,{350,Automatic}],{Full,Automatic},ImageSizeAction->"ResizeToFit"]&@Column[{
DynamicModule[{},Framed[Slider2D[Dynamic[posRed],{{0,-1},{1,0}},ImageSize->AbsoluteCurrentValue[{WindowSize,1}]1.1{130,40}/1280],FrameStyle->Directive[Red,Thickness[2]],RoundingRadius->5,FrameMargins->None],Initialization:>(posRed={.5,-.5})],

DynamicModule[{},Framed[Slider2D[Dynamic[posBlue],{{0,-1},{1,0}},ImageSize->AbsoluteCurrentValue[{WindowSize,1}]1.1{130,120}/1280],FrameStyle->Directive[,Thickness[2]],RoundingRadius->5,FrameMargins->None],Initialization:>(posBlue={.5,-.5})]},

Spacings->.2]

Popups much be attached to the notebook body.
How do we align them with buttons in the docked cell?

AttachCell[EvaluationNotebook[],popup,alignment=?]

Popup Alignment: Suboptimal Solution

Pre-calculate the horizontal positions of each button/control, given their widths.

Details and Disadvantages

By knowing widths of items, spacers, etc. we could calculate the horizontal coordinate for each popup

May not be pixel-perfect

May require system-dependent offsets

Complicated by dynamically hidden/shown items

Must know the horizontal position of the overall construct:

Popup Alignment: MousePosition Differences

Subtract the mouse position relative to the item, from the mouse position relative to the notebook.

Wrap items in EventHandlers to get item-relative mouse positions:

EventHandler[#,{},PassEventsDown->True]&@
Framed[Dynamic[MousePosition["EventHandlerAbsolute"]]]

Mouse position relative to the window given by “ViewAbsolute”:

Dynamic[MousePosition["ViewAbsolute"]]

Popup Alignment: MousePosition Differences

Locate the bottom left corner:

MousePosition["ViewAbsolute"]-{1,-1}*MousePosition["EventHandlerAbsolute"]

With[{w=400,h=300,t=10,dir=Sequence[Arrowheads[Large],
AbsoluteThickness[5]],style=Style[##,FontFamily->"Source Sans Pro",Bold,30]&},
DynamicModule[{ehxy={0,0},nbxy={0,0},mouseoverQ=False,cell1,cell2},
EventHandler[
Framed[Graphics[
{dir,,
Dynamic[If[mouseoverQ,{
Arrow[Dynamic[{{0,0},ehxy+{-7,7}}]],
Text[Framed[style["EHAbs",],FrameStyle->None,Background->White],Dynamic[Offset[{2,-2},.5(ehxy+{-7,7})]],{-1,1}]},{}]]
},
PlotRange->{{0,w},{0,h}},
ImageSize->{w,h}],FrameMargins->None,FrameStyle->Directive[Thickness[2],GrayLevel[.3]]],
{
"MouseEntered":>(
mouseoverQ=True;
cell1=AttachCell[
EvaluationNotebook[],
DynamicModule[{},
Graphics[{dir,,Arrow[{{0,1},{1,0}}]},
PlotRange->{{0,1},{0,1}},ImagePadding->2,
AspectRatio->Full,
ImageSize->Dynamic[If[ehxy==={0,0},{0,0},nbxy+{-5,-5}]]],
InheritScope->True,
Initialization:>AttachCell[EvaluationCell[],
Framed[style["ViewAbs",],FrameStyle->None,Background->White],
{Center,Center},Offset[{2,2},Automatic],{Left,Bottom}]],
{Left,Top},Automatic,{Left,Top}];
cell2=AttachCell[
EvaluationNotebook[],
DynamicModule[{},
Graphics[{dir,,Arrow[{{0,1},{1,0}}]},
PlotRange->{{0,1},{0,1}},ImagePadding->2,
AspectRatio->Full,
ImageSize->Dynamic[If[ehxy==={0,0},{0,0},nbxy-{1,-1}*ehxy]]],
InheritScope->True],
{Left,Top},Automatic,{Left,Top}]),
"MouseExited":>(
mouseoverQ=False;
NotebookDelete[{cell1,cell2}]),
"MouseMoved":>(
ehxy=MousePosition["EventHandlerAbsolute",{0,0}];
nbxy=MousePosition["ViewAbsolute",{0,0}])}]]]

((MousePosition["EventHandlerAbsolute"])/(MousePosition["EventHandlerScaled"]))  gives the item size.

Details: Optimal Alignment of Toolbar Popups

Maximize window space for a popup:

Left-align popups and buttons in the left half of the window

Right-align popups and buttons in the right half of the window

Algorithm to run on button click

Determine in which half of the window the button is:

First[MousePosition["ViewScaled"]]<.5

If the click was in the right half, we want to attach to the right edge of the button, so find its width:

First[MousePosition["EventHandlerAbsolute"]/MousePosition["EventHandlerScaled"]]

Locate the left edge of the button (add width if attaching to right edge)

MousePosition["ViewAbsolute"]-MousePosition["EventHandlerAbsolute"]

Attach the popup to the appropriate edge

AttachCell[EvaluationNotebook[],popup,
{Left,Top},
Offset[{edgeCoord,0},Automatic],
{Left/Right,Top}]

Summary

Reviewed the front end boxes and features available to us

Overflow Construction

Minimize the use of Dynamic for an efficient interface

Used an attached cell and linebreaking method to construct an overflow interface free of Dynamics

Popup Alignment

Found a general way to locate and size items when moused over

Achieved with combinations of various relative mouse positions