You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit a8ad908
Browse filesBrowse the repository at this point in the historyBrowse files
[Shell] Render the active tab's head in the top bar, not just the page body (#1027)
A tab's title + primary-actions head sits above its screen today, but
that row is inside the page the workspace's tabs sit on, which cannot
reach the window's own top bar -- the issue's repro.
ShellFrame gains a dedicated _headSlot beside the title, built in the
constructor like every other top-bar child, with its own independent
stretch so it keeps claiming width even while the mounted row is
invisible (a screen with no head). Workspace::headRowForActive()
exposes the same reactive head Node headRow() already builds for the
in-body rendering, read directly off the model's own active tab id --
splitting headRow()'s construction into a Row-returning helper both
methods share, since a Node, once built, cannot be mutated further.
shell.cpp mounts it, re-mounting only on a genuine active-tab change
(compared by tab id, not Workspace::active()'s own index, which is a
bar position and not stable across a close) -- the mounted Node is
itself reactive, so in-tab status/action changes update without a
re-mount. The mount and its comparison key reset together, ahead of
_workspace, on every path that tears the workspace down directly
rather than through its own model callback: the destructor and
buildFrame()'s own rebuild (where a fresh Workspace instance restarts
its tab-id numbering from 1, which would otherwise collide with the
pre-rebuild key and silently drop the head on the very screen a sign-in
just opened).
Trailing-edge action alignment inside the row is deliberately not
attempted here: pushing the row's own spacer to stretch would need a
change to ui::spacer() that also affects the existing in-body
rendering, out of scope for a change that only adds a new mount point.
Part (b) of the issue -- an optional second builder for arbitrary
document-authored chrome content -- is explicitly out of scope; this
covers only the ScreenHead-shaped repro the issue actually reports.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: docs/spec/ui/shell_frame.md
+6-1Lines changed: 6 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -19,11 +19,16 @@ and the page the workspace's tabs sit on. It is built from backend widgets, so e
19
19
| a row, stretch × stretch |`shell`| the whole frame |
20
20
| a row, surface `sidebar`, `fixed(kShellSidebarWidth)` (28) × stretch, gap 3, its content padded by spacers |`shell_sidebar`| the application's name (`shell_application`, a heading) and a `ui::Navigator` over `ShellFrameOptions::navigator`, whose group headings are sections and whose entries are body text, so the scale runs name, section, entry |
21
21
| a column, stretch × stretch | — | the main column |
22
-
| a row, surface `toolbar`, gap 3, `align: center`, padded by spacers at both ends |`shell_topbar`| the shown screen's title (`shell_title`, a heading that stretches), the principal (`shell_principal`, muted) and a sign-out button (`shell_signOut`) |
22
+
| a row, surface `toolbar`, gap 3, `align: center`, padded by spacers at both ends |`shell_topbar`| the shown screen's title (`shell_title`, a heading that stretches), a slot for its active tab's head row (`shell_head`, its own independent stretch), the principal (`shell_principal`, muted) and a sign-out button (`shell_signOut`) |
23
23
| a column, surface `page`, stretch × stretch |`shell_page`| the page: zero-sized spacers above and either side of the content, each a gap of step 4 away, so the content is padded by step 4 |
24
24
25
25
-`page()` is the content container, where the client places the workspace.
26
26
-`navigator()` is the navigator, for its pins and search.
27
+
-`headSlot()` is the container a client mounts the active tab's own head row into — `Workspace::
28
+
headRowForActive()` builds it — beside the title. Its own `stretch` is independent of whether the mounted row is
29
+
currently visible (a screen with no head mounts an invisible row), so the slot keeps claiming its share of the
30
+
bar's width either way; `_title` keeps its own separate stretch, so the two split the bar's spare width, and the
31
+
mounted row renders at its own natural width within the slot rather than reaching the slot's own trailing edge.
27
32
-`setTitle` and `setPrincipal` set the top bar's texts. The bar centres its children across it, so the principal's
28
33
line sits level with the sign-out button's label rather than on the bar's top edge.
29
34
- The sign-out button calls `ShellFrameOptions::onSignOut`; with none, it is hidden.
0 commit comments