โ back to Ticket System
Ticket desktop bar: add night/day theme toggle (๐/โ๏ธ button)
61e600af61cab4f420f8b93b7392cac8387d17fb ยท 2026-09-03 10:04:59 -0700 ยท Steve Abrams
Adds a ๐/โ๏ธ button at the right of the bar that flips the whole bar between
night (dark, default) and day (light) โ panel background, tile backgrounds, and
all label/button colors are theme-driven via applyTheme(). Choice persists in
ticketBarNight. Mirrors the board's night/day control on the native bar.
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 61e600af61cab4f420f8b93b7392cac8387d17fb
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Thu Sep 3 10:04:59 2026 -0700
Ticket desktop bar: add night/day theme toggle (๐/โ๏ธ button)
Adds a ๐/โ๏ธ button at the right of the bar that flips the whole bar between
night (dark, default) and day (light) โ panel background, tile backgrounds, and
all label/button colors are theme-driven via applyTheme(). Choice persists in
ticketBarNight. Mirrors the board's night/day control on the native bar.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015XNcHvXXepEQar7Qsb7GGy
---
desktop-bar/TicketBar.swift | 51 ++++++++++++++++++++++++++++++++++++++-------
1 file changed, 43 insertions(+), 8 deletions(-)
diff --git a/desktop-bar/TicketBar.swift b/desktop-bar/TicketBar.swift
index 83e305b8..097a0259 100644
--- a/desktop-bar/TicketBar.swift
+++ b/desktop-bar/TicketBar.swift
@@ -74,6 +74,9 @@ private final class BarController: NSObject, NSApplicationDelegate, NSWindowDele
private let latest = NSTextField(labelWithString: "Latest ยท โ")
private var stack: NSStackView!
private var tiles: [BarTile] = []
+ private var openButton: NSButton!
+ private var themeButton: NSButton!
+ private var isNight = true
private var statusDetails: [String: [String]] = [:]
private var workingDetails: [String] = []
private var latestDetail = "No activity yet"
@@ -104,18 +107,14 @@ private final class BarController: NSObject, NSApplicationDelegate, NSWindowDele
panel.hasShadow = true
panel.hidesOnDeactivate = false
+ isNight = UserDefaults.standard.object(forKey: "ticketBarNight") as? Bool ?? true
let countLabels = [openLabel, blockedLabel, doingLabel]
for label in countLabels + [working, latest] {
- label.textColor = .white
label.font = .systemFont(ofSize: 12, weight: countLabels.contains(label) ? .bold : .medium)
label.lineBreakMode = .byTruncatingTail
label.maximumNumberOfLines = 1
}
- openLabel.textColor = NSColor(calibratedRed: 0.31, green: 0.63, blue: 1.00, alpha: 1) // blue
- blockedLabel.textColor = NSColor(calibratedRed: 0.88, green: 0.42, blue: 0.46, alpha: 1) // red
- doingLabel.textColor = NSColor(calibratedRed: 0.43, green: 0.70, blue: 0.95, alpha: 1) // light blue
- working.textColor = NSColor(calibratedRed: 0.45, green: 0.78, blue: 1, alpha: 1)
- latest.textColor = NSColor(calibratedWhite: 0.72, alpha: 1)
+ // Text/tile/panel colors are theme-driven โ see applyTheme().
let savedWidths = UserDefaults.standard.dictionary(forKey: "ticketBarWidths") as? [String: CGFloat] ?? [:]
// OPEN / BLOCKED / DOING are now THREE separate tiles โ each opens its own
@@ -140,14 +139,19 @@ private final class BarController: NSObject, NSApplicationDelegate, NSWindowDele
}
let open = NSButton(title: "Open Fleet โ", target: self, action: #selector(openViewer))
open.bezelStyle = .inline
- open.contentTintColor = .white
- stack = NSStackView(views: tiles + [open])
+ openButton = open
+ themeButton = NSButton(title: isNight ? "๐" : "โ๏ธ", target: self, action: #selector(toggleTheme))
+ themeButton.bezelStyle = .inline
+ themeButton.isBordered = false
+ themeButton.toolTip = "Toggle night / day"
+ stack = NSStackView(views: tiles + [open, themeButton])
stack.orientation = .horizontal
stack.spacing = 6
stack.alignment = .centerY
stack.distribution = .fill
for tile in tiles { tile.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) }
open.setContentHuggingPriority(.required, for: .horizontal)
+ themeButton.setContentHuggingPriority(.required, for: .horizontal)
// Center the tile group horizontally in the full-width bar (was left-anchored).
let container = NSView()
@@ -161,10 +165,41 @@ private final class BarController: NSObject, NSApplicationDelegate, NSWindowDele
])
panel.contentView = container
installDragMonitor()
+ applyTheme()
reposition()
panel.orderFrontRegardless()
}
+ @objc private func toggleTheme() {
+ isNight.toggle()
+ UserDefaults.standard.set(isNight, forKey: "ticketBarNight")
+ applyTheme()
+ }
+
+ // Night = dark bar (default), Day = light bar. Toggled by the ๐/โ๏ธ button.
+ private func applyTheme() {
+ let night = isNight
+ panel.backgroundColor = night ? NSColor(calibratedWhite: 0.055, alpha: 0.97)
+ : NSColor(calibratedWhite: 0.95, alpha: 0.98)
+ let tileBG = (night ? NSColor(calibratedWhite: 0.11, alpha: 0.90)
+ : NSColor(calibratedWhite: 0.86, alpha: 0.95)).cgColor
+ for tile in tiles { tile.layer?.backgroundColor = tileBG }
+ openLabel.textColor = night ? NSColor(calibratedRed: 0.31, green: 0.63, blue: 1.00, alpha: 1)
+ : NSColor(calibratedRed: 0.13, green: 0.38, blue: 0.82, alpha: 1)
+ blockedLabel.textColor = night ? NSColor(calibratedRed: 0.88, green: 0.42, blue: 0.46, alpha: 1)
+ : NSColor(calibratedRed: 0.74, green: 0.18, blue: 0.22, alpha: 1)
+ doingLabel.textColor = night ? NSColor(calibratedRed: 0.43, green: 0.70, blue: 0.95, alpha: 1)
+ : NSColor(calibratedRed: 0.16, green: 0.44, blue: 0.72, alpha: 1)
+ working.textColor = night ? NSColor(calibratedRed: 0.45, green: 0.78, blue: 1.00, alpha: 1)
+ : NSColor(calibratedRed: 0.10, green: 0.45, blue: 0.82, alpha: 1)
+ latest.textColor = night ? NSColor(calibratedWhite: 0.72, alpha: 1)
+ : NSColor(calibratedWhite: 0.30, alpha: 1)
+ openButton?.contentTintColor = night ? .white : NSColor(calibratedWhite: 0.15, alpha: 1)
+ themeButton?.title = night ? "๐" : "โ๏ธ"
+ panel.invalidateShadow()
+ panel.contentView?.needsDisplay = true
+ }
+
private func installDragMonitor() {
guard dragMonitor == nil else { return }
dragMonitor = NSEvent.addLocalMonitorForEvents(matching: [.leftMouseDown, .leftMouseDragged, .leftMouseUp]) { [weak self] event in
โ 3fa9bcca Ticket desktop bar: split OPEN/BLOCKED/DOING into 3 separate
ยท
back to Ticket System
ยท
Log TK-11180 yoloforever cycle 2fb6496c โ