Skip to content
Merged
Show file tree
Hide file tree
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
37 changes: 37 additions & 0 deletions CodeEdit/Features/CodeEditUI/Views/GlassEffectView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//
// GlassEffectView.swift
// CodeEdit
//
// Created by Khan Winter on 9/2/25.
//

import SwiftUI
import AppKit

struct GlassEffectView: NSViewRepresentable {
var tintColor: NSColor?

init(tintColor: NSColor? = nil) {
self.tintColor = tintColor
}

func makeNSView(context: Context) -> NSView {
#if compiler(>=6.2)
if #available(macOS 26, *) {
let view = NSGlassEffectView()
view.cornerRadius = 0
view.tintColor = tintColor
return view
}
#endif
return NSView()
}

func updateNSView(_ nsView: NSView, context: Context) {
#if compiler(>=6.2)
if #available(macOS 26, *), let view = nsView as? NSGlassEffectView {
view.tintColor = tintColor
}
#endif
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,11 @@ struct EditorTabBackground: View {
ZStack {
if isActive {
// Content background (visible if active)
EffectView(.contentBackground)
.opacity(isActive ? 1 : 0)
if #available(macOS 26, *) {
GlassEffectView()
} else {
EffectView(.contentBackground)
}

// Accent color (visible if active)
Color(.controlAccentColor)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,11 @@ struct EditorTabCloseButton: View {
.frame(width: buttonSize, height: buttonSize)
.background(backgroundColor)
.foregroundColor(isPressingClose ? .primary : .secondary)
.clipShape(RoundedRectangle(cornerRadius: 2))
.if(.tahoe) {
$0.clipShape(Circle())
} else: {
$0.clipShape(RoundedRectangle(cornerRadius: 2))
}
.contentShape(Rectangle())
.gesture(
DragGesture(minimumDistance: 0)
Expand Down
23 changes: 17 additions & 6 deletions CodeEdit/Features/Editor/TabBar/Tabs/Tab/EditorTabView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,11 @@ struct EditorTabView: View {

@ViewBuilder var content: some View {
HStack(spacing: 0.0) {
EditorTabDivider()
.opacity(
(isActive || inHoldingState) ? 0.0 : 1.0
)

if #unavailable(macOS 26) {
EditorTabDivider()
.opacity((isActive || inHoldingState) ? 0.0 : 1.0)
}
// Tab content (icon and text).
HStack(alignment: .center, spacing: 3) {
Image(nsImage: tabFile.nsIcon)
Expand Down Expand Up @@ -165,14 +166,19 @@ struct EditorTabView: View {
}
.frame(maxWidth: .infinity, alignment: .leading)
}
.if(.tahoe) {
$0.padding(.horizontal, 1.5)
}
.opacity(
// Inactive states for tab bar item content.
activeState != .inactive
? 1.0
: isActive ? 0.6 : 0.4
)
EditorTabDivider()
.opacity((isActive || inHoldingState) ? 0.0 : 1.0)
if #unavailable(macOS 26) {
EditorTabDivider()
.opacity((isActive || inHoldingState) ? 0.0 : 1.0)
}
}
.foregroundColor(
isActive && isActiveEditor
Expand Down Expand Up @@ -220,6 +226,11 @@ struct EditorTabView: View {
EditorTabBackground(isActive: isActive, isPressing: isPressing, isDragging: isDragging)
.animation(.easeInOut(duration: 0.08), value: isHovering)
}
.if(.tahoe) {
if #available(macOS 26, *) {
$0.clipShape(Capsule()).clipped().containerShape(Capsule())
}
}
// TODO: Enable the following code snippet when dragging-out behavior should be allowed.
// Since we didn't handle the drop-outside event, dragging-out is disabled for now.
// .onDrag({
Expand Down
25 changes: 25 additions & 0 deletions CodeEdit/Features/Editor/TabBar/Tabs/Views/EditorTabs.swift
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,12 @@ struct EditorTabs: View {
) {
ForEach(Array(openedTabs.enumerated()), id: \.element) { index, id in
if let item = editor.tabs.first(where: { $0.file.id == id }) {
if index != 0
&& editor.selectedTab?.file.id != id
&& editor.selectedTab?.file.id != openedTabs[index - 1] {
EditorTabDivider()
}

EditorTabView(
file: item.file,
index: index,
Expand Down Expand Up @@ -293,6 +299,12 @@ struct EditorTabs: View {
tabWidth: $tabWidth
)
)

if index < openedTabs.count - 1
&& editor.selectedTab?.file.id != id
&& editor.selectedTab?.file.id != openedTabs[index + 1] {
EditorTabDivider()
}
}
}
}
Expand Down Expand Up @@ -357,6 +369,19 @@ struct EditorTabs: View {
)
.opacity((scrollTrailingOffset ?? 0) <= 0 ? 0 : 1)
}
.if(.tahoe) {
if #available(macOS 26.0, *) {
// Unfortunate triple if here due to needing to compile on
// earlier Xcodes.
#if compiler(>=6.2)
$0.background(GlassEffectView(tintColor: .tertiarySystemFill))
.clipShape(Capsule())
.clipped()
#else
$0
#endif
}
}
}
}

Expand Down
45 changes: 44 additions & 1 deletion CodeEdit/Features/Editor/Views/EditorAreaView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ struct EditorAreaView: View {
@Environment(\.window.value)
private var window: NSWindow?

@Environment(\.isEditorLayoutAtEdge)
private var isAtEdge

init(editor: Editor, focus: FocusState<Editor?>.Binding) {
self.editor = editor
self._focus = focus
Expand Down Expand Up @@ -101,6 +104,10 @@ struct EditorAreaView: View {
}

VStack(spacing: 0) {
if isAtEdge != .top, #available(macOS 26, *) {
Spacer().frame(height: 4)
}

if topSafeArea > 0 {
Rectangle()
.fill(.clear)
Expand All @@ -111,7 +118,9 @@ struct EditorAreaView: View {
EditorTabBarView(hasTopInsets: topSafeArea > 0, codeFile: fileBinding)
.id("TabBarView" + editor.id.uuidString)
.environmentObject(editor)
Divider()
if #unavailable(macOS 26) {
Divider()
}
}
if showEditorJumpBar {
EditorJumpBarView(
Expand All @@ -125,13 +134,47 @@ struct EditorAreaView: View {
}
.environmentObject(editor)
.padding(.top, shouldShowTabBar ? -1 : 0)
if #unavailable(macOS 26) {
Divider()
}
}
// On Tahoe we only show one divider
if #available(macOS 26, *), shouldShowTabBar || showEditorJumpBar {
Divider()
}
}
.environment(\.isActiveEditor, editor == editorManager.activeEditor)
.if(.tahoe) {
// FB20047271: Glass toolbar effect ignores floating scroll view views.
// https://openradar.appspot.com/radar?id=EhAKBVJhZGFyEICAgKbGmesJ

// FB20191516: Can't disable backgrounded liquid glass tint
// https://openradar.appspot.com/radar?id=EhAKBVJhZGFyEICAgLqTk-4J
// Tracking Issue: #2191
// Add this to the top:
// ```
// @AppSettings(\.theme.useThemeBackground)
// var useThemeBackground
//
// private var backgroundColor: NSColor {
// let fallback = NSColor.textBackgroundColor
// return if useThemeBackground {
// ThemeModel.shared.selectedTheme?.editor.background.nsColor ?? fallback
// } else {
// fallback
// }
// }
// ```
// And use this:
// ```
// $0.background(
// Rectangle().fill(.clear)
// .glassEffect(.regular.tint(Color(backgroundColor))
// .ignoresSafeArea(.all)
// )
// ```
// When we can figure out how to disable the 'not focused' glass effect.

$0.background(EffectView(.headerView).ignoresSafeArea(.all))
} else: {
$0.background(EffectView(.headerView))
Expand Down
8 changes: 4 additions & 4 deletions CodeEdit/Features/Editor/Views/EditorLayoutView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ struct EditorLayoutView: View {
@Environment(\.window.value)
private var window

@Environment(\.isAtEdge)
@Environment(\.isEditorLayoutAtEdge)
private var isAtEdge

var toolbarHeight: CGFloat {
Expand Down Expand Up @@ -63,7 +63,7 @@ struct EditorLayoutView: View {
var splitView: some View {
ForEach(Array(data.editorLayouts.enumerated()), id: \.offset) { index, item in
EditorLayoutView(layout: item, focus: $focus)
.transformEnvironment(\.isAtEdge) { belowToolbar in
.transformEnvironment(\.isEditorLayoutAtEdge) { belowToolbar in
calcIsAtEdge(current: &belowToolbar, index: index)
}
.environment(\.splitEditor) { [weak data] edge, newEditor in
Expand All @@ -87,12 +87,12 @@ struct EditorLayoutView: View {
}
}

private struct BelowToolbarEnvironmentKey: EnvironmentKey {
struct BelowToolbarEnvironmentKey: EnvironmentKey {
static var defaultValue: VerticalEdge.Set = .all
}

extension EnvironmentValues {
fileprivate var isAtEdge: BelowToolbarEnvironmentKey.Value {
var isEditorLayoutAtEdge: BelowToolbarEnvironmentKey.Value {
get { self[BelowToolbarEnvironmentKey.self] }
set { self[BelowToolbarEnvironmentKey.self] = newValue }
}
Expand Down
10 changes: 10 additions & 0 deletions CodeEdit/Features/SplitView/Views/SplitViewControllerView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,16 @@ final class SplitViewController: NSSplitViewController {
override var dividerThickness: CGFloat {
customDividerStyle.customThickness ?? super.dividerThickness
}

override func drawDivider(in rect: NSRect) {
let safeRect = NSRect(
x: rect.origin.x,
y: max(rect.origin.y, safeAreaRect.origin.y),
width: isVertical ? dividerThickness : rect.width,
height: isVertical ? safeAreaRect.height : dividerThickness
)
super.drawDivider(in: safeRect)
}
}

var items: [SplitViewItem] = []
Expand Down
Loading