Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 39 additions & 19 deletions Sources/Bonsplit/Internal/Views/TabBarView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -182,28 +182,19 @@ struct TabBarView: View {
}
}
.frame(height: TabBarMetrics.barHeight)
.mask(fadeOverlays)
// Split buttons + fade mask behind them, all fading in/out together.
.mask(combinedMask)
// Buttons float on top. No backdrop color needed because
// the mask hides scroll content and the tab bar's own
// background shows through naturally.
.overlay(alignment: .trailing) {
if showSplitButtons {
let shouldShow = presentationMode != "minimal" || isHoveringTabBar
let bg = Color(nsColor: Self.buttonBackdropColor(for: appearance, focused: isFocused, style: fadeColorStyle))
ZStack(alignment: .trailing) {
// Backdrop: fade gradient then solid
HStack(spacing: 0) {
LinearGradient(colors: [bg.opacity(0), bg], startPoint: .leading, endPoint: .trailing)
.frame(width: 24)
Rectangle().fill(bg)
}
.frame(width: 114)
// Buttons on top
splitButtons
.saturation(tabBarSaturation)
}
.padding(.bottom, 1)
.opacity(shouldShow ? 1 : 0)
.allowsHitTesting(shouldShow)
.animation(.easeInOut(duration: 0.14), value: shouldShow)
splitButtons
.saturation(tabBarSaturation)
.padding(.bottom, 1)
.opacity(shouldShow ? 1 : 0)
.allowsHitTesting(shouldShow)
.animation(.easeInOut(duration: 0.14), value: shouldShow)
}
}
}
Expand Down Expand Up @@ -579,6 +570,35 @@ struct TabBarView: View {
return NSColor(red: r, green: g, blue: b, alpha: 1.0)
}

// MARK: - Combined Mask (scroll fades + button area)

@ViewBuilder
private var combinedMask: some View {
let fadeWidth: CGFloat = 24
let shouldShowButtons = showSplitButtons && (presentationMode != "minimal" || isHoveringTabBar)
let buttonClearWidth: CGFloat = shouldShowButtons ? 90 : 0
let buttonFadeWidth: CGFloat = shouldShowButtons ? fadeWidth : 0
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Unused variable buttonFadeWidth

buttonFadeWidth is computed and assigned but never referenced anywhere in combinedMask. It appears to be a leftover from development. Consider removing it.

Suggested change
let buttonFadeWidth: CGFloat = shouldShowButtons ? fadeWidth : 0
let buttonClearWidth: CGFloat = shouldShowButtons ? 90 : 0


HStack(spacing: 0) {
// Left scroll fade
LinearGradient(colors: [.clear, .black], startPoint: .leading, endPoint: .trailing)
.frame(width: canScrollLeft ? fadeWidth : 0)

// Visible content area
Rectangle().fill(Color.black)

// Right: either scroll fade or button area fade
LinearGradient(colors: [.black, .clear], startPoint: .leading, endPoint: .trailing)
.frame(width: canScrollRight || shouldShowButtons ? fadeWidth : 0)

// Button clear area (content hidden here)
if shouldShowButtons {
Color.clear.frame(width: buttonClearWidth)
}
}
.animation(.easeInOut(duration: 0.14), value: shouldShowButtons)
}

// MARK: - Fade Overlays

/// Mask that fades scroll content at the edges instead of overlaying
Expand Down
Loading