Repository navigation
Use assigned workspace tab color for selected sidebar rows #2569
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -75,6 +75,68 @@ func cmuxAccentColor() -> Color { | |
| Color(nsColor: cmuxAccentNSColor()) | ||
| } | ||
|
|
||
| private func sidebarSelectedWorkspaceRelativeLuminance(_ color: NSColor) -> CGFloat { | ||
| let rgbColor = color.usingColorSpace(.sRGB) ?? color | ||
| var red: CGFloat = 0 | ||
| var green: CGFloat = 0 | ||
| var blue: CGFloat = 0 | ||
| var alpha: CGFloat = 0 | ||
| rgbColor.getRed(&red, green: &green, blue: &blue, alpha: &alpha) | ||
|
|
||
| func linearized(_ component: CGFloat) -> CGFloat { | ||
| if component <= 0.03928 { | ||
| return component / 12.92 | ||
| } | ||
| return pow((component + 0.055) / 1.055, 2.4) | ||
| } | ||
|
|
||
| let linearRed = linearized(red) | ||
| let linearGreen = linearized(green) | ||
| let linearBlue = linearized(blue) | ||
| return (0.2126 * linearRed) + (0.7152 * linearGreen) + (0.0722 * linearBlue) | ||
| } | ||
|
|
||
| private func sidebarSelectedWorkspaceContrastRatio( | ||
| between first: NSColor, | ||
| and second: NSColor | ||
| ) -> CGFloat { | ||
| let firstLuminance = sidebarSelectedWorkspaceRelativeLuminance(first) | ||
| let secondLuminance = sidebarSelectedWorkspaceRelativeLuminance(second) | ||
| let lighter = max(firstLuminance, secondLuminance) | ||
| let darker = min(firstLuminance, secondLuminance) | ||
| return (lighter + 0.05) / (darker + 0.05) | ||
| } | ||
|
|
||
| private func sidebarSelectedWorkspaceReadableBackgroundNSColor(_ color: NSColor) -> NSColor { | ||
| let minimumContrast: CGFloat = 4.5 | ||
| var adjusted = color.usingColorSpace(.sRGB) ?? color | ||
| var iteration = 0 | ||
|
|
||
| // Keep the assigned hue, but darken overly bright custom colors until the | ||
| // existing white selected-state foreground remains readable. | ||
| while sidebarSelectedWorkspaceContrastRatio(between: adjusted, and: NSColor.white) < minimumContrast, | ||
| iteration < 12 { | ||
| guard let darkened = adjusted.blended(withFraction: 0.12, of: .black) else { break } | ||
| adjusted = darkened.usingColorSpace(.sRGB) ?? darkened | ||
| iteration += 1 | ||
| } | ||
|
|
||
| return adjusted | ||
| } | ||
|
Comment on lines
+115
to
+125
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The readability loop always measures contrast against while sidebarSelectedWorkspaceContrastRatio(between: adjusted, and: NSColor.white) < minimumContrast,This is only correct when the selected-row label text is actually white. In light-mode appearances, the sidebar's selected-state text is often rendered in a dark color (e.g., Consider passing |
||
|
|
||
| private func sidebarSelectedWorkspaceCustomBackgroundNSColor( | ||
| hex: String, | ||
| colorScheme: ColorScheme | ||
| ) -> NSColor? { | ||
| guard let color = WorkspaceTabColorSettings.displayNSColor( | ||
| hex: hex, | ||
| colorScheme: colorScheme | ||
| ) else { | ||
| return nil | ||
| } | ||
| return sidebarSelectedWorkspaceReadableBackgroundNSColor(color) | ||
| } | ||
|
|
||
| struct SidebarRemoteErrorCopyEntry: Equatable { | ||
| let workspaceTitle: String | ||
| let target: String | ||
|
|
@@ -112,8 +174,19 @@ enum SidebarRemoteErrorCopySupport { | |
| } | ||
| } | ||
|
|
||
| func sidebarSelectedWorkspaceBackgroundNSColor(for colorScheme: ColorScheme) -> NSColor { | ||
| if let hex = UserDefaults.standard.string(forKey: "sidebarSelectionColorHex"), | ||
| func sidebarSelectedWorkspaceBackgroundNSColor( | ||
| for colorScheme: ColorScheme, | ||
| customHex: String? = nil, | ||
| sidebarSelectionColorHex: String? = UserDefaults.standard.string(forKey: "sidebarSelectionColorHex") | ||
| ) -> NSColor { | ||
| if let customHex, | ||
| let customColor = sidebarSelectedWorkspaceCustomBackgroundNSColor( | ||
| hex: customHex, | ||
| colorScheme: colorScheme | ||
| ) { | ||
| return customColor | ||
| } | ||
| if let hex = sidebarSelectionColorHex, | ||
| let parsed = NSColor(hex: hex) { | ||
| return parsed | ||
| } | ||
|
|
@@ -13323,10 +13396,11 @@ private struct TabItemView: View, Equatable { | |
| } | ||
|
|
||
| private var selectionBackgroundColor: NSColor { | ||
| if let hex = sidebarSelectionColorHex, let parsed = NSColor(hex: hex) { | ||
| return parsed | ||
| } | ||
| return cmuxAccentNSColor(for: colorScheme) | ||
| sidebarSelectedWorkspaceBackgroundNSColor( | ||
| for: colorScheme, | ||
| customHex: tab.customColor, | ||
| sidebarSelectionColorHex: sidebarSelectionColorHex | ||
| ) | ||
| } | ||
|
|
||
| private var backgroundColor: Color { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
forceBrightomitted — potential visual inconsistency inleftRailmodeWorkspaceTabColorSettings.displayNSColoris called here withoutforceBright:Every other call site in
TabItemViewpassesforceBright: activeTabIndicatorStyle == .leftRail(lines 13437–13440, 13445–13448). This means the selection background inleftRailmode starts from the base (un-brightened) color, while the left-rail indicator and the color swatch both use the brightened version. The contrast-darkening loop will then operate on a dimmer starting color and may produce a slightly different shade than expected. If this is intentional (avoiding double-brightness before darkening), a comment explaining the decision would help.