← back to Ticket System
Ticket desktop bar: restore left-click dropdowns, center tile group, add Move Bar Up/Down vertical placement
5e92781291c9cf3193cfef36f1d86746ed711f71 · 2026-09-03 09:47:26 -0700 · Steve Abrams
- Remove per-tile clickHandler that short-circuited showDropdown() so the big web
popup opened on every left-click and the dropdown menu was dead code (fixes 'no
dropdowns'). Left-click now opens the tile dropdown; the control window moved to
an 'Open Control Window' menu item + the existing 'Open Fleet' button.
- Center the tile group in the full-width bar via a container + required centerX
(was left-anchored NSStackView with a left edge inset) (fixes 'not centered').
- Add 'Move Bar Up' / 'Move Bar Down' menu controls persisting ticketBarYOffset,
honored in reposition() with on-screen clamping (fixes 'move up and down
vertically').
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015XNcHvXXepEQar7Qsb7GGy
Files touched
M desktop-bar/TicketBar.swift
Diff
commit 5e92781291c9cf3193cfef36f1d86746ed711f71
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Thu Sep 3 09:47:26 2026 -0700
Ticket desktop bar: restore left-click dropdowns, center tile group, add Move Bar Up/Down vertical placement
- Remove per-tile clickHandler that short-circuited showDropdown() so the big web
popup opened on every left-click and the dropdown menu was dead code (fixes 'no
dropdowns'). Left-click now opens the tile dropdown; the control window moved to
an 'Open Control Window' menu item + the existing 'Open Fleet' button.
- Center the tile group in the full-width bar via a container + required centerX
(was left-anchored NSStackView with a left edge inset) (fixes 'not centered').
- Add 'Move Bar Up' / 'Move Bar Down' menu controls persisting ticketBarYOffset,
honored in reposition() with on-screen clamping (fixes 'move up and down
vertically').
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015XNcHvXXepEQar7Qsb7GGy
---
desktop-bar/TicketBar.swift | 45 ++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 40 insertions(+), 5 deletions(-)
diff --git a/desktop-bar/TicketBar.swift b/desktop-bar/TicketBar.swift
index 6827d199..c5b69291 100644
--- a/desktop-bar/TicketBar.swift
+++ b/desktop-bar/TicketBar.swift
@@ -114,7 +114,9 @@ private final class BarController: NSObject, NSApplicationDelegate, NSWindowDele
let tile = BarTile(key: key, label: label, width: savedWidths[key] ?? defaultWidth)
tile.dragHandler = { [weak self] key, x in self?.moveTile(key, toward: x) }
tile.menuProvider = { [weak self] in self?.menu(for: key) ?? NSMenu() }
- tile.clickHandler = { [weak self] in self?.openTicketPopup() }
+ // No clickHandler: left-click a tile now opens its DROPDOWN menu (details +
+ // layout controls). The web control window is reachable from the menu's
+ // "Open Control Window" item and from the "Open Fleet ↗" button below.
return tile
}
let open = NSButton(title: "Open Fleet ↗", target: self, action: #selector(openViewer))
@@ -124,10 +126,21 @@ private final class BarController: NSObject, NSApplicationDelegate, NSWindowDele
stack.orientation = .horizontal
stack.spacing = 6
stack.alignment = .centerY
- stack.edgeInsets = NSEdgeInsets(top: 0, left: 14, bottom: 0, right: 10)
+ stack.distribution = .fill
for tile in tiles { tile.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) }
open.setContentHuggingPriority(.required, for: .horizontal)
- panel.contentView = stack
+
+ // Center the tile group horizontally in the full-width bar (was left-anchored).
+ let container = NSView()
+ stack.translatesAutoresizingMaskIntoConstraints = false
+ container.addSubview(stack)
+ NSLayoutConstraint.activate([
+ stack.centerXAnchor.constraint(equalTo: container.centerXAnchor),
+ stack.centerYAnchor.constraint(equalTo: container.centerYAnchor),
+ stack.leadingAnchor.constraint(greaterThanOrEqualTo: container.leadingAnchor, constant: 14),
+ stack.trailingAnchor.constraint(lessThanOrEqualTo: container.trailingAnchor, constant: -10)
+ ])
+ panel.contentView = container
installDragMonitor()
reposition()
panel.orderFrontRegardless()
@@ -177,6 +190,10 @@ private final class BarController: NSObject, NSApplicationDelegate, NSWindowDele
private func menu(for key: String) -> NSMenu {
let menu = NSMenu(title: key)
+ let openItem = NSMenuItem(title: "Open Control Window ↗", action: #selector(openControlFromMenu), keyEquivalent: "")
+ openItem.target = self
+ menu.addItem(openItem)
+ menu.addItem(.separator())
let details: [String]
if key == "counts" {
details = [counts.stringValue.replacingOccurrences(of: " ", with: " • ")]
@@ -191,7 +208,7 @@ private final class BarController: NSObject, NSApplicationDelegate, NSWindowDele
menu.addItem(item)
}
menu.addItem(.separator())
- for (title, action) in [("Move Left", #selector(moveLeft(_:))), ("Move Right", #selector(moveRight(_:))), ("Wider", #selector(wider(_:))), ("Narrower", #selector(narrower(_:)))] {
+ for (title, action) in [("Move Left", #selector(moveLeft(_:))), ("Move Right", #selector(moveRight(_:))), ("Move Bar Up", #selector(moveBarUp(_:))), ("Move Bar Down", #selector(moveBarDown(_:))), ("Wider", #selector(wider(_:))), ("Narrower", #selector(narrower(_:)))] {
let item = NSMenuItem(title: title, action: action, keyEquivalent: "")
item.target = self
item.representedObject = key
@@ -200,6 +217,18 @@ private final class BarController: NSObject, NSApplicationDelegate, NSWindowDele
return menu
}
+ @objc private func openControlFromMenu() { openTicketPopup() }
+
+ // Vertical bar placement — "ticketBarYOffset" is pixels BELOW the top of the
+ // visible frame (0 = pinned under the menu bar, the original behavior).
+ @objc private func moveBarUp(_ sender: NSMenuItem) { nudgeBar(by: -40) }
+ @objc private func moveBarDown(_ sender: NSMenuItem) { nudgeBar(by: 40) }
+ private func nudgeBar(by delta: CGFloat) {
+ let current = CGFloat(UserDefaults.standard.double(forKey: "ticketBarYOffset"))
+ UserDefaults.standard.set(Double(current + delta), forKey: "ticketBarYOffset")
+ reposition()
+ }
+
@objc private func moveLeft(_ sender: NSMenuItem) { shift(sender.representedObject as? String, by: -1) }
@objc private func moveRight(_ sender: NSMenuItem) { shift(sender.representedObject as? String, by: 1) }
private func shift(_ key: String?, by delta: Int) {
@@ -230,7 +259,13 @@ private final class BarController: NSObject, NSApplicationDelegate, NSWindowDele
@objc private func reposition() {
guard let screen = NSScreen.main ?? NSScreen.screens.first else { return }
let frame = screen.visibleFrame
- panel.setFrame(NSRect(x: frame.minX, y: frame.maxY - 38, width: frame.width, height: 38), display: true)
+ let barHeight: CGFloat = 38
+ let requested = CGFloat(UserDefaults.standard.double(forKey: "ticketBarYOffset")) // px below the top
+ let maxOffset = max(0, frame.height - barHeight)
+ let offset = min(max(0, requested), maxOffset)
+ if offset != requested { UserDefaults.standard.set(Double(offset), forKey: "ticketBarYOffset") }
+ let y = frame.maxY - barHeight - offset
+ panel.setFrame(NSRect(x: frame.minX, y: y, width: frame.width, height: barHeight), display: true)
}
@objc private func openViewer() { NSWorkspace.shared.open(viewerURL) }
← 56550c41 preserve backup canary monitoring evidence
·
back to Ticket System
·
preserve gated canary classifier evidence f9ba422f →