Card windows drop the title from the title bar — the body already says it
The card's name renders as part of the card body, so the chrome said it twice. HostedWindowController gains a titleVisibility slot on the same retained-slot pattern as the accessory and toolbar (reapplied at attach, so the macOS 26 provisional-window swap can't lose it); CardWindowHost opts in beside installToolbar, board windows keep AppKit's default. window.title itself is untouched — navigationTitle still feeds the Window menu, Exposé, VoiceOver and restoration. Known consequence, probed empirically: under .hidden AppKit collapses title and subtitle into one hidden field, so the "board › lane" navigationSubtitle disappears with it — and the details sidebar carries no placement rows, so a card window currently shows its home nowhere. Filed on the Redesign board to bless or relocate; 05-card-window.md's subtitle sentence needs reconciling either way. Claude-Session: https://claude.ai/code/session_01CqjXB7ASoWtbyoGod68k97
This commit is contained in:
@@ -91,6 +91,22 @@ final class HostedWindowController: NSObject, NSWindowDelegate {
|
||||
/// their board has loaded.
|
||||
private var toolbarController: WindowToolbarController?
|
||||
|
||||
/// Whether this window's title is hidden from the title bar — **card windows only**
|
||||
/// (05-card-window.md ▸ Window: the card's name is shown as part of the card's body, not the
|
||||
/// chrome). `nil` leaves AppKit's own default (`.visible`) untouched, which is what every board
|
||||
/// window keeps without a call of its own — the same "nothing to do" posture `titlebarAccessory`
|
||||
/// has on welcome, the bootstrap and card windows, mirrored here for the one window kind that
|
||||
/// *does* have an opinion.
|
||||
///
|
||||
/// A slot, not a one-shot write, for the accessory and toolbar's own reason: the value has to
|
||||
/// survive the provisional-window swap (`detach()`'s doc comment) and reapply itself when the
|
||||
/// real window attaches, which a write made once at `onAttach` time would not survive if that
|
||||
/// closure only fired for the provisional window. `NSWindow.title` itself is a different slot
|
||||
/// entirely — SwiftUI's `navigationTitle` sets it directly, and it is left alone on purpose: the
|
||||
/// Window menu, Mission Control/Exposé, VoiceOver and state restoration all read the string, not
|
||||
/// what the chrome draws from it.
|
||||
private var titleVisibility: NSWindow.TitleVisibility?
|
||||
|
||||
private static let logger = Logger(subsystem: "dev.rzen.indie.Kanban", category: "window")
|
||||
|
||||
// MARK: Attachment
|
||||
@@ -110,6 +126,7 @@ final class HostedWindowController: NSObject, NSWindowDelegate {
|
||||
// window existed is installed here instead, and one handed over later installs immediately.
|
||||
addTitlebarAccessoryIfPossible()
|
||||
applyToolbarIfPossible()
|
||||
applyTitleVisibilityIfPossible()
|
||||
}
|
||||
|
||||
/// Puts the previous delegate back and takes the titlebar accessory and toolbar off the window —
|
||||
@@ -192,6 +209,26 @@ final class HostedWindowController: NSObject, NSWindowDelegate {
|
||||
window.toolbar = nil
|
||||
}
|
||||
|
||||
// MARK: Title visibility
|
||||
|
||||
/// Hides this window's title from the title bar, leaving the toolbar exactly as it renders today
|
||||
/// — the card-window seam (`CardWindowHost`, 05-card-window.md ▸ Window). `window.title` is
|
||||
/// untouched by this call on purpose; see the property's doc comment for why.
|
||||
///
|
||||
/// Safe to call whenever the caller learns it wants this — before the window exists (the value is
|
||||
/// held and applied at `attach`) or after (applied immediately) — and safe to call more than once,
|
||||
/// unlike the accessory and toolbar slots: writing `NSWindow.titleVisibility` twice has no side
|
||||
/// effect worth guarding against, so this is not an install-once seam.
|
||||
func hideTitle() {
|
||||
titleVisibility = .hidden
|
||||
applyTitleVisibilityIfPossible()
|
||||
}
|
||||
|
||||
private func applyTitleVisibilityIfPossible() {
|
||||
guard let window, let titleVisibility else { return }
|
||||
window.titleVisibility = titleVisibility
|
||||
}
|
||||
|
||||
/// Closes the window for real, after the flush has run. `performClose` rather than `close` so the
|
||||
/// standard path runs — SwiftUI's own delegate gets its callbacks, tabbing behaves — with the
|
||||
/// flag telling our own `windowShouldClose` to stand aside.
|
||||
|
||||
Reference in New Issue
Block a user