feat: add opt-in spaces hiding, bottom nav bar, and a window title - #10
Conversation
|
Thanks for these. Six focused PRs, each with a clear reason and its own tests. I have merged five: #6, #7, #8, #9, and #11. I am holding this one for two reasons. First, it overlaps #9. Both add the same Second, it is the largest change here and it touches the hidden-titlebar chrome, which has been a repeated source of subtle bugs in this app. You noted yourself that you could not exercise the window drag band. Before it lands I want to run all six layout states and a real drag by hand, and I have not done that yet. None of this is a rejection. The work looks careful and the reasoning in each description helped. Rebase onto current main when you get a chance, and I will take it through the layout checks. |
dbf9dce to
3cf8fc3
Compare
|
Thanks for the thorough look, and for merging the other five. Rebased onto current main. The duplicate On the second point, you are right to gate it on the drag band, and I would not want it to land without that check either. I could not exercise a real window drag from where I was testing, so the |
|
An update, and it is not a rejection: I am parking this one for now, pending some UX exploration. I ran the build on macOS 26 and checked what works. Hiding the spaces bar reflows the content correctly and is reversible. Switching across all three layouts works. The drag band works too in the horizontal layouts: the window moves when you drag the empty top strip. The window title is what gives me pause, for two reasons. First, on macOS 26 it does not render at all. The window's title property gets set, but nothing draws, so the whole configurator is a no-op here. My guess is a version difference in how Rather than merge the layout options and settle the title piecemeal, I want to think through the rail and title UX as a whole first. So I am leaving this open but tabled for the time being. The hide-spaces and bottom-nav work is solid, and I expect it to land once the UX is settled. Thanks again, and sorry to park it after you took the trouble to rebase. |
Two layout options, both defaulting to today's behaviour so an upgrade
changes nothing until the user asks.
Hide the spaces bar
Some setups keep every service in one space, leaving the spaces rail as
permanent dead weight. Adds a persisted `hideSpacesUI` preference with
three ways to flip it: a Settings toggle, View > Hide Spaces Bar
(Ctrl-Cmd-S), and a button in the services rail footer.
That button lives in the SERVICES rail deliberately — the spaces rail
is what disappears, so a control hosted there would remove itself and
leave only the menu as a way back.
Hiding is purely visual: the selected space is untouched, and Cmd-K,
Ctrl-Tab and the menu bar still switch spaces. Services in a space you
aren't viewing stay out of the sidebar as before, so the Settings
caption points at Cmd-K.
Navigation buttons at the bottom
At the top they compete with the traffic lights and the badge cluster.
`ToolbarPosition` (top/bottom) moves them to a bar of their own. At
`.bottom` both the sidebar row and the tab-bar buttons are suppressed
so they never render twice.
Layout corrections that came with the above
- The rails' vertical rules ran the full height and cut through the
traffic-light strip; they now start below it.
- `.topBars` and `.hybrid` inset their service tabs on the assumption
that the spaces rail was there to clear the traffic lights. With it
hidden they take the full inset instead.
- The traffic-light metrics were repeated as literals in two files;
extracted to `WindowChrome` so a rail and the view beside it can't
drift apart.
The window title from the earlier revision of this PR is dropped: it was
a no-op on macOS 26 (the window's title property set, but nothing drew),
and it duplicated the highlighted service icon anyway. The traffic-light
strip is still reserved as empty space so the top nav row clears the
window buttons, but nothing is drawn into it.
New preferences are `Optional`, matching the surrounding pattern, so
SwiftData lightweight migration is a no-op on existing stores. Two tests
cover the preference resolution. Suite green (109).
Verified by the maintainer on macOS 26 in the prior revision: hiding the
spaces bar reflows correctly and reverses, all three layouts switch, and
the window drag band still works in the horizontal layouts.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3cf8fc3 to
e7a19a1
Compare
|
That is fair, and thanks for taking the time to run it on macOS 26 — the title findings are both real, and I would rather know than have it merged half-working. You are right on both counts. It being a no-op under So I have pushed a revision that simply drops the window title. No None of this is meant to jump ahead of the rail-and-title UX rethink you mentioned — if you would still rather hold the whole thing until that is settled, that is completely reasonable and I am happy to leave it parked. I mostly wanted to take the broken and redundant piece off the table, so that whenever you do come back to it, what is open is only the part you already verified works. No rush at all, and thanks again for the careful reviews across all of these. |
Three layout options, all defaulting to today's behaviour so an upgrade
changes nothing until the user asks for it.
Hide the spaces bar
I keep every service in one space, so the spaces rail is permanent
dead weight in my daily use. Adds a persisted
hideSpacesUIpreference with three ways to flip it: a Settings toggle,
View > Hide Spaces Bar (Ctrl-Cmd-S), and a button in the services rail
footer for the everyday case.
That button lives in the SERVICES rail deliberately — the spaces rail
is what disappears, so a control hosted there would remove itself and
leave only the menu as a way back.
Hiding is purely visual: the selected space is untouched, and Cmd-K,
Ctrl-Tab and the menu bar still switch spaces. Services in a space you
aren't viewing stay out of the sidebar as before, so the Settings
caption points at Cmd-K.
Navigation buttons at the bottom
At the top they compete with the traffic lights and the badge cluster.
ToolbarPosition(top/bottom) moves them to a bar of their own. At.bottomboth the sidebar row and the tab-bar buttons are suppressedso they never render twice.
Window title
With the spaces rail hidden there was nothing naming the service in
front. Two things about this are worth recording, because both bit me:
First, the obvious approach fails silently.
.windowStyle(.hiddenTitleBar)hides the title but keeps the bar, andAppKit draws that bar over SwiftUI content — I rendered a solid
rectangle into that strip and nothing appeared on screen. So the title
can't be a SwiftUI view;
WindowTitleConfiguratorsets the window'sown title and makes it visible again, leaving the bar transparent so
layout is unchanged.
Second, it must be per-layout. Only
.sidebarleaves that stripempty.
.topBarsand.hybridput the spaces chips and service tabsthere, and the title lands on top of them — I had this wrong until I
screenshotted those layouts, where "Chorus — Slack" was drawn straight
through the Personal/Work chips. The configurator now takes an
isVisibleflag and only shows the title in.sidebar.Layout corrections that came with the above
traffic-light strip; they now start below it.
.topBarsand.hybridinset their service tabs on the assumptionthat the spaces rail was there to clear the traffic lights. With it
hidden they take the full inset instead.
extracted to
WindowChromeso a rail and the view beside it can'tdrift apart.
The new preferences are
Optional, matchingautoDarkModeEnabledandcontentBlockingEnabled, so SwiftData lightweight migration handlesexisting stores. Verified against a populated store rather than a fresh
one, in both directions — opening it with an older model that lacks
these fields drops the columns and leaves the services, spaces and links
intact.
Checked by running the app and screenshotting all six states: sidebar,
top-bars and hybrid, each with the spaces rail shown and hidden, plus
both toolbar positions. Two new tests cover the preference resolution.
One thing I could not exercise properly: the window drag band. In
.topBarsthe OS drag is off andWindowDragHandles stand in for it. Iconfirmed by reading the code that
ServiceSidebarView.horizontalBodycarries its own handle, so hiding the spaces rail doesn't remove the
only draggable strip — but I could not simulate a real drag to prove it.