major
#29737
TL Views: a collapsing toolbar measures its commands only when its groups change; a command that shows itself later keeps a 0 px toolbar and draws over the panel title
Reported from the Consulting application on 8.0.0-alpha9 (BOS/Consulting #416).
Problem
A collapsing toolbar (TLToolbar with overflow trailing or leading, #29626) measures its commands only when its list of groups changes. A command that becomes visible later, or changes its label, is never measured: the toolbar keeps the natural width it computed before, and the compact and overflow decisions use the old widths.
The common case is a detail panel whose commands depend on the state of a form. Administration > Blaupausen > Methodiken of the Consulting application, a <form> beside a list, the form's edit commands in its panel header:
| step | inline style of .tlToolbar | widths of the units (data-tlunit) |
| nothing selected | width: 0px | 0, 0, 0 (all three commands hidden) |
| a row selected | width: 0px | 122 (Bearbeiten), 0, 0 |
| "Bearbeiten" pressed | width: 0px | 0, 117 (Speichern), 122 (Abbrechen) |
| page reloaded | width: 123px | 122, 0, 0 |
The groups state does not change between these steps - a button that hides or shows itself only changes its own hidden state - so TLToolbar never measures again: the measurement runs only when the groups array is a new value. Its ResizeObserver observes the toolbar itself, whose width is fixed by the inline style, so a command that appears does not trigger it either. A toolbar that measures while its page is not displayed (a hidden tab or deck card) measures zeros and keeps them the same way.
Consequences:
- The toolbar box is 0 px (or the width of an earlier set of commands) while its commands are wider. With justify-content: flex-end they draw out of the box to the left, over the panel title ("Ab|lauf" with "Speichern" over it at 1440 px), and at a narrow width over the neighbouring pane of a split.
- Compact mode and the overflow menu never engage for such a toolbar, because the full width it compares against is 0.
- The other way round, a toolbar measured with more commands than it now shows keeps a too-wide box and cuts the title before it has to.
Reproduction
Any <panel> with TOOLBAR commands that are hidden while not executable, e.g. the edit commands of a <form> in a master-detail view:
- Open the view with nothing selected; the header's .tlToolbar carries style="width: 0px".
- Select a row: "Bearbeiten" shows, the toolbar box stays 0 px wide and the button is drawn to its left.
- Narrow the window until the button meets the title: it covers the title instead of collapsing to its icon.
Expected
The toolbar measures again whenever the width of one of its units changes for a reason other than its own compact or overflow switch: a command shown or hidden, a label changed, the toolbar shown after it was measured hidden. A ResizeObserver on the [data-tlunit] elements would do it; the measurement already skips units of width 0.
Workaround in the application
script/consulting-toolbar-measure.js observes the units of every .tlToolbar--collapsible, remembers each unit's width per presentation (full or compact), and on a change hands the toolbar its own groups again as a new array through the store createChildContext(id) returns, which makes TLToolbar measure again. To be deleted with this ticket.
Lösung
Eine Messung von TLToolbar gilt nur noch, solange sowohl die Gruppen als auch die Breiten der Einheiten unverändert sind. Ein ResizeObserver beobachtet jedes gerenderte [data-tlunit]-Element (die beobachtete Menge wird nach jedem Rendern abgeglichen). Im eingeschwungenen Zustand vergleicht er die aktuelle Breite einer Einheit mit der für die aktuelle Darstellung (voll oder kompakt) gemessenen Breite; weicht sie ab, laufen die beiden Messdurchgänge (voll, kompakt) erneut. Damit wird neu gemessen, wenn ein Kommando sich ein- oder ausblendet, seine Beschriftung ändert oder die Toolbar sichtbar wird, nachdem sie verborgen gemessen wurde. Während der Messdurchgänge werden Meldungen ignoriert; die eigene Umschaltung auf kompakt oder Überlauf stimmt mit den gespeicherten Breiten überein und löst keine Messung aus.
Nicht abgedeckt: Eine Einheit, die bereits im Überlaufmenü liegt, hat dort keine messbare Breite; ändert sie ihre Sichtbarkeit, gilt ihre alte Breite weiter, bis sich die Gruppen ändern.