Add hover background to split action buttons (#2271)
* Add hover background to split action buttons Split buttons (terminal, browser, split right/down) now show a subtle rounded-rect background highlight on hover. Matches standard macOS toolbar button behavior. * Prevent fade overlays from bleeding into bottom separator * Render bottom separator above fade overlays to prevent bleed * Exclude drop zone from scroll fade threshold * Revert button hover, fix fade threshold with 32pt buffer * Fix right fade threshold: subtract drop zone, 4pt tolerance * Add leading padding to split buttons, fix fade threshold * Rework tab bar: full-width scroll with floating split buttons * Use ultraThinMaterial blur for floating split buttons * Make split buttons group full height * Full-height split button blur background * Inset split buttons from bottom separator * Fix blur overlapping separator * Use matching tab bar bg for split buttons, clear separator * Use regularMaterial blur for split buttons * Try thickMaterial for split buttons * Fade gradient + solid barFill for floating split buttons * Use extended right fade as split buttons backdrop * Add 5 debug styles for split button background * Add Split Button Style debug window to Debug menu * Clean up: no-bg floating buttons, alphabetical debug menu - Split buttons float with no background (tabBarBackground covers the area, scroll padding prevents tabs from appearing behind buttons) - Default splitButtonsWidth to 120 so first render has correct padding - Remove split button style debug window and debug styles - Alphabetize Debug Windows menu entries, remove dividers * Revert to HStack sibling layout, add debug menu docs to CLAUDE.md - Split buttons are HStack siblings of the ScrollView, not overlays. Single .background() on parent, no compositing mismatch. - Alphabetize Debug Windows menu, remove dividers. - Document Debug menu in CLAUDE.md. * Add Split Button Layout debug window with 5 switchable approaches * Fix fade gradient color to match tab bar background * Add fade color debug window with 6 color options * Use mask for scroll fades, fixes color mismatch * Hide scroll fades in minimal mode unless hovering * Remove split buttons from layout when hidden in minimal mode * Always show fades, overlay buttons to prevent scroll jump * Add hover-only mask fade behind split buttons * Reduce button mask area to 90pt * Animate button mask smoothly * Fade entire button group together via opacity * Add blur behind buttons with fade mask * Use theme barBackground for button backdrop * Blur + theme tint for button backdrop * More tint (0.85), less blur * Tint 0.2, clear bottom border * Use terminal bg color, add scroll trailing padding for buttons * Less blur, paneBackground at 0.75 opacity * paneBackground at 0.9 opacity * 0.97 opacity for button backdrop * Test: fully opaque paneBackground * Test: solid red backdrop * Gradient + solid paneBackground backdrop, no mask * Force opaque paneBackground for button backdrop * Use barBackground for button backdrop * Use terminal bg (paneBackground forced opaque) * Pre-composite backdrop color for exact match * Add 6 switchable backdrop styles in debug window * Mask-based button area hiding, no backdrop color needed --------- Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
This commit is contained in:
parent
d015ace094
commit
978dd2c023
3 changed files with 92 additions and 21 deletions
|
|
@ -141,6 +141,14 @@ When adding a regression test for a bug fix, use a two-commit structure so CI pr
|
||||||
|
|
||||||
This makes it visible in the GitHub PR UI (Commits tab, check statuses) that the test genuinely fails without the fix.
|
This makes it visible in the GitHub PR UI (Commits tab, check statuses) that the test genuinely fails without the fix.
|
||||||
|
|
||||||
|
## Debug menu
|
||||||
|
|
||||||
|
The app has a **Debug** menu in the macOS menu bar (only in DEBUG builds). Use it for visual iteration:
|
||||||
|
|
||||||
|
- **Debug > Debug Windows** contains panels for tuning layout, colors, and behavior. Entries are alphabetical with no dividers.
|
||||||
|
- To add a debug toggle or visual option: create an `NSWindowController` subclass with a `shared` singleton, add it to the "Debug Windows" menu in `Sources/cmuxApp.swift`, and add a SwiftUI view with `@AppStorage` bindings for live changes.
|
||||||
|
- When the user says "debug menu" or "debug window", they mean this menu, not `defaults write`.
|
||||||
|
|
||||||
## Pitfalls
|
## Pitfalls
|
||||||
|
|
||||||
- **Custom UTTypes** for drag-and-drop must be declared in `Resources/Info.plist` under `UTExportedTypeDeclarations` (e.g. `com.splittabbar.tabtransfer`, `com.cmux.sidebar-tab-reorder`).
|
- **Custom UTTypes** for drag-and-drop must be declared in `Resources/Info.plist` under `UTExportedTypeDeclarations` (e.g. `com.splittabbar.tabtransfer`, `com.cmux.sidebar-tab-reorder`).
|
||||||
|
|
|
||||||
|
|
@ -474,14 +474,12 @@ struct cmuxApp: App {
|
||||||
|
|
||||||
Divider()
|
Divider()
|
||||||
Menu("Debug Windows") {
|
Menu("Debug Windows") {
|
||||||
Button("Debug Window Controls…") {
|
Button("Background Debug…") {
|
||||||
DebugWindowControlsWindowController.shared.show()
|
BackgroundDebugWindowController.shared.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
Button("Browser Import Hint Debug…") {
|
Button("Browser Import Hint Debug…") {
|
||||||
BrowserImportHintDebugWindowController.shared.show()
|
BrowserImportHintDebugWindowController.shared.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
Button(
|
Button(
|
||||||
String(
|
String(
|
||||||
localized: "debug.menu.browserProfilePopoverDebug",
|
localized: "debug.menu.browserProfilePopoverDebug",
|
||||||
|
|
@ -490,26 +488,21 @@ struct cmuxApp: App {
|
||||||
) {
|
) {
|
||||||
BrowserProfilePopoverDebugWindowController.shared.show()
|
BrowserProfilePopoverDebugWindowController.shared.show()
|
||||||
}
|
}
|
||||||
|
Button("Debug Window Controls…") {
|
||||||
Button("Settings/About Titlebar Debug…") {
|
DebugWindowControlsWindowController.shared.show()
|
||||||
SettingsAboutTitlebarDebugWindowController.shared.show()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Divider()
|
|
||||||
Button("Sidebar Debug…") {
|
|
||||||
SidebarDebugWindowController.shared.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
Button("Background Debug…") {
|
|
||||||
BackgroundDebugWindowController.shared.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
Button("Menu Bar Extra Debug…") {
|
Button("Menu Bar Extra Debug…") {
|
||||||
MenuBarExtraDebugWindowController.shared.show()
|
MenuBarExtraDebugWindowController.shared.show()
|
||||||
}
|
}
|
||||||
|
Button("Settings/About Titlebar Debug…") {
|
||||||
Divider()
|
SettingsAboutTitlebarDebugWindowController.shared.show()
|
||||||
|
}
|
||||||
|
Button("Sidebar Debug…") {
|
||||||
|
SidebarDebugWindowController.shared.show()
|
||||||
|
}
|
||||||
|
Button("Split Button Layout Debug…") {
|
||||||
|
SplitButtonLayoutDebugWindowController.shared.show()
|
||||||
|
}
|
||||||
Button("Open All Debug Windows") {
|
Button("Open All Debug Windows") {
|
||||||
openAllDebugWindows()
|
openAllDebugWindows()
|
||||||
}
|
}
|
||||||
|
|
@ -3337,6 +3330,76 @@ private struct MenuBarExtraDebugView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Split Button Layout Debug Window
|
||||||
|
|
||||||
|
private final class SplitButtonLayoutDebugWindowController: NSWindowController, NSWindowDelegate {
|
||||||
|
static let shared = SplitButtonLayoutDebugWindowController()
|
||||||
|
|
||||||
|
private init() {
|
||||||
|
let window = NSPanel(
|
||||||
|
contentRect: NSRect(x: 0, y: 0, width: 320, height: 240),
|
||||||
|
styleMask: [.titled, .closable, .utilityWindow],
|
||||||
|
backing: .buffered,
|
||||||
|
defer: false
|
||||||
|
)
|
||||||
|
window.title = "Split Button Layout"
|
||||||
|
window.titleVisibility = .visible
|
||||||
|
window.titlebarAppearsTransparent = false
|
||||||
|
window.isMovableByWindowBackground = true
|
||||||
|
window.isReleasedWhenClosed = false
|
||||||
|
window.identifier = NSUserInterfaceItemIdentifier("cmux.splitButtonLayoutDebug")
|
||||||
|
window.center()
|
||||||
|
window.contentView = NSHostingView(rootView: SplitButtonLayoutDebugView())
|
||||||
|
AppDelegate.shared?.applyWindowDecorations(to: window)
|
||||||
|
super.init(window: window)
|
||||||
|
window.delegate = self
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(*, unavailable)
|
||||||
|
required init?(coder: NSCoder) { fatalError() }
|
||||||
|
|
||||||
|
func show() {
|
||||||
|
window?.center()
|
||||||
|
window?.makeKeyAndOrderFront(nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct SplitButtonLayoutDebugView: View {
|
||||||
|
@AppStorage("debugFadeColorStyle") private var backdropStyle = 0
|
||||||
|
|
||||||
|
private let options: [(Int, String)] = [
|
||||||
|
(0, "Pre-composited paneBackground"),
|
||||||
|
(1, "Raw paneBackground (opaque)"),
|
||||||
|
(2, "barBackground (tab chrome)"),
|
||||||
|
(3, "windowBackgroundColor"),
|
||||||
|
(4, "controlBackgroundColor"),
|
||||||
|
(5, "Pre-composited barBackground"),
|
||||||
|
]
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack(alignment: .leading, spacing: 10) {
|
||||||
|
Text("Button Backdrop Color")
|
||||||
|
.font(.headline)
|
||||||
|
|
||||||
|
ForEach(options, id: \.0) { id, label in
|
||||||
|
HStack {
|
||||||
|
Image(systemName: backdropStyle == id ? "checkmark.circle.fill" : "circle")
|
||||||
|
.foregroundColor(backdropStyle == id ? .accentColor : .secondary)
|
||||||
|
Text(label)
|
||||||
|
}
|
||||||
|
.contentShape(Rectangle())
|
||||||
|
.onTapGesture { backdropStyle = id }
|
||||||
|
}
|
||||||
|
|
||||||
|
Text("Changes apply live.")
|
||||||
|
.font(.caption)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
}
|
||||||
|
.padding(16)
|
||||||
|
.frame(maxWidth: .infinity, alignment: .topLeading)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Background Debug Window
|
// MARK: - Background Debug Window
|
||||||
|
|
||||||
private final class BackgroundDebugWindowController: NSWindowController, NSWindowDelegate {
|
private final class BackgroundDebugWindowController: NSWindowController, NSWindowDelegate {
|
||||||
|
|
|
||||||
2
vendor/bonsplit
vendored
2
vendor/bonsplit
vendored
|
|
@ -1 +1 @@
|
||||||
Subproject commit 447ac42b45256bdf333659d2dbe955afcaa87f6b
|
Subproject commit aff9f7073125d412fed07bce1adab0e78f907b14
|
||||||
Loading…
Add table
Add a link
Reference in a new issue