Skip to content
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

Added shadows to tab bar when tabs overflow #1412

Merged
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
12 changes: 8 additions & 4 deletions CodeEdit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
285FEC7027FE4B9800E57D53 /* ProjectNavigatorTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 285FEC6F27FE4B9800E57D53 /* ProjectNavigatorTableViewCell.swift */; };
286471AB27ED51FD0039369D /* ProjectNavigatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 286471AA27ED51FD0039369D /* ProjectNavigatorView.swift */; };
287776E927E34BC700D46668 /* TabBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 287776E827E34BC700D46668 /* TabBarView.swift */; };
2897E1C72979A29200741E32 /* OffsettableScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2897E1C62979A29200741E32 /* OffsettableScrollView.swift */; };
2897E1C72979A29200741E32 /* TrackableScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2897E1C62979A29200741E32 /* TrackableScrollView.swift */; };
28A51001281673530087B0CC /* codeedit-xcode-dark.json in Resources */ = {isa = PBXBuildFile; fileRef = 28A50FFF281673530087B0CC /* codeedit-xcode-dark.json */; };
28A51002281673530087B0CC /* codeedit-xcode-light.json in Resources */ = {isa = PBXBuildFile; fileRef = 28A51000281673530087B0CC /* codeedit-xcode-light.json */; };
28A51005281701B40087B0CC /* codeedit-github-light.json in Resources */ = {isa = PBXBuildFile; fileRef = 28A51003281701B40087B0CC /* codeedit-github-light.json */; };
Expand Down Expand Up @@ -374,6 +374,7 @@
B6E41C8B29DE7AE80088F9F4 /* AccountsSettingsSigninView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6E41C8A29DE7AE80088F9F4 /* AccountsSettingsSigninView.swift */; };
B6E41C8F29DE9CD80088F9F4 /* AccountsSettingsDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6E41C8E29DE9CD80088F9F4 /* AccountsSettingsDetailsView.swift */; };
B6E41C9429DEAE260088F9F4 /* SourceControlAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6E41C9329DEAE260088F9F4 /* SourceControlAccount.swift */; };
B6E55C3B2A95368E003ECC7D /* TabBarShadow.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6E55C3A2A95368E003ECC7D /* TabBarShadow.swift */; };
B6EA1FE529DA33DB001BF195 /* ThemeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6EA1FE429DA33DB001BF195 /* ThemeModel.swift */; };
B6EA1FE729DA341D001BF195 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6EA1FE629DA341D001BF195 /* Theme.swift */; };
B6EA1FF529DA380E001BF195 /* TextEditingSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6EA1FF429DA380E001BF195 /* TextEditingSettingsView.swift */; };
Expand Down Expand Up @@ -501,7 +502,7 @@
286471AA27ED51FD0039369D /* ProjectNavigatorView.swift */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = ProjectNavigatorView.swift; sourceTree = "<group>"; tabWidth = 4; };
287776E627E3413200D46668 /* NavigatorSidebarView.swift */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = NavigatorSidebarView.swift; sourceTree = "<group>"; tabWidth = 4; };
287776E827E34BC700D46668 /* TabBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarView.swift; sourceTree = "<group>"; };
2897E1C62979A29200741E32 /* OffsettableScrollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OffsettableScrollView.swift; sourceTree = "<group>"; };
2897E1C62979A29200741E32 /* TrackableScrollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackableScrollView.swift; sourceTree = "<group>"; };
28A50FFF281673530087B0CC /* codeedit-xcode-dark.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "codeedit-xcode-dark.json"; sourceTree = "<group>"; };
28A51000281673530087B0CC /* codeedit-xcode-light.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "codeedit-xcode-light.json"; sourceTree = "<group>"; };
28A51003281701B40087B0CC /* codeedit-github-light.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "codeedit-github-light.json"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -823,6 +824,7 @@
B6E41C8A29DE7AE80088F9F4 /* AccountsSettingsSigninView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountsSettingsSigninView.swift; sourceTree = "<group>"; };
B6E41C8E29DE9CD80088F9F4 /* AccountsSettingsDetailsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountsSettingsDetailsView.swift; sourceTree = "<group>"; };
B6E41C9329DEAE260088F9F4 /* SourceControlAccount.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceControlAccount.swift; sourceTree = "<group>"; };
B6E55C3A2A95368E003ECC7D /* TabBarShadow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarShadow.swift; sourceTree = "<group>"; };
B6EA1FE429DA33DB001BF195 /* ThemeModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThemeModel.swift; sourceTree = "<group>"; };
B6EA1FE629DA341D001BF195 /* Theme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = "<group>"; };
B6EA1FF429DA380E001BF195 /* TextEditingSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextEditingSettingsView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1573,7 +1575,7 @@
587B9D8829300ABD00AC7927 /* SegmentedControl.swift */,
587B9D8C29300ABD00AC7927 /* SettingsTextEditor.swift */,
587B9D8F29300ABD00AC7927 /* ToolbarBranchPicker.swift */,
2897E1C62979A29200741E32 /* OffsettableScrollView.swift */,
2897E1C62979A29200741E32 /* TrackableScrollView.swift */,
6CBA0D502A1BF524002C6FAA /* SegmentedControlImproved.swift */,
B62AEDA92A1FCBE5009A9F52 /* AreaTabBar.swift */,
);
Expand Down Expand Up @@ -1908,6 +1910,7 @@
DE513F51281B672D002260B9 /* TabBarAccessory.swift */,
DE513F53281DE5D0002260B9 /* TabBarXcode.swift */,
B6C6A42F29771F7100A3D28F /* TabBarItemBackground.swift */,
B6E55C3A2A95368E003ECC7D /* TabBarShadow.swift */,
);
path = Views;
sourceTree = "<group>";
Expand Down Expand Up @@ -2881,6 +2884,7 @@
58798235292E30B90085B254 /* FeedbackModel.swift in Sources */,
04C3255C2801F86900C8DA2D /* ProjectNavigatorMenu.swift in Sources */,
587B9E6429301D8F00AC7927 /* GitLabCommit.swift in Sources */,
B6E55C3B2A95368E003ECC7D /* TabBarShadow.swift in Sources */,
58A5DFA229339F6400D1BD5D /* KeybindingManager.swift in Sources */,
B62AEDB32A1FD95B009A9F52 /* DebugAreaTerminalView.swift in Sources */,
58AFAA2E2933C69E00482B53 /* TabBarItemRepresentable.swift in Sources */,
Expand Down Expand Up @@ -2955,7 +2959,7 @@
58822531292C280D00E83CDE /* View+isHovering.swift in Sources */,
587B9E9929301D8F00AC7927 /* GitChangedFile.swift in Sources */,
6C147C4B29A32A7B0089B630 /* Environment+SplitEditor.swift in Sources */,
2897E1C72979A29200741E32 /* OffsettableScrollView.swift in Sources */,
2897E1C72979A29200741E32 /* TrackableScrollView.swift in Sources */,
58F2EB0E292FB2B0004A9BDE /* SoftwareUpdater.swift in Sources */,
587B9E9529301D8F00AC7927 /* BitBucketUser.swift in Sources */,
587B9E7C29301D8F00AC7927 /* GitHubRepositoryRouter.swift in Sources */,
Expand Down
4 changes: 1 addition & 3 deletions CodeEdit/Features/About/Views/AboutDetailView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,7 @@ struct AboutDetailView<Content: View>: View {
var body: some View {
VStack {
Spacer(minLength: smallTitlebarHeight + 1)
OffsettableScrollView(showsIndicator: false) { offset in
scrollOffset = offset.y
} content: {
TrackableScrollView(showIndicators: false, contentOffset: $scrollOffset) {
Spacer(minLength: mediumTitlebarHeight - smallTitlebarHeight - 1 + 8)
content
.padding(.horizontal)
Expand Down
55 changes: 0 additions & 55 deletions CodeEdit/Features/CodeEditUI/Views/OffsettableScrollView.swift

This file was deleted.

112 changes: 112 additions & 0 deletions CodeEdit/Features/CodeEditUI/Views/TrackableScrollView.swift
austincondiff marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
//
// TrackableScrollView.swift
// CodeEdit
//
// Created by Lukas Pistrol on 19.01.23.
//

// Inspired by SwiftUITrackableScrollView by Natchanon A.
// https://github.com/maxnatchanon/trackable-scroll-view

import SwiftUI

private struct ScrollViewOffsetPreferenceKey: PreferenceKey {
typealias Value = [CGFloat]

static var defaultValue: [CGFloat] = [0]

static func reduce(value: inout [CGFloat], nextValue: () -> [CGFloat]) {
value.append(contentsOf: nextValue())
}
}

struct TrackableScrollView<Content>: View where Content: View {
let axes: Axis.Set
let showIndicators: Bool
@Binding var contentOffset: CGFloat
@Binding var contentTrailingOffset: CGFloat?
let content: Content

init(
_ axes: Axis.Set = .vertical,
showIndicators: Bool = true,
contentOffset: Binding<CGFloat>,
@ViewBuilder content: () -> Content
) {
self.axes = axes
self.showIndicators = showIndicators
self._contentOffset = contentOffset
self._contentTrailingOffset = Binding.constant(nil)
self.content = content()
}

init(
_ axes: Axis.Set = .vertical,
showIndicators: Bool = true,
contentOffset: Binding<CGFloat>,
contentTrailingOffset: Binding<CGFloat?>?,
@ViewBuilder content: () -> Content
) {
self.axes = axes
self.showIndicators = showIndicators
self._contentOffset = contentOffset
self._contentTrailingOffset = contentTrailingOffset ?? Binding.constant(nil)
self.content = content()
}

var body: some View {
GeometryReader { outsideProxy in
ScrollView(self.axes, showsIndicators: self.showIndicators) {
ZStack(alignment: self.axes == .vertical ? .top : .leading) {
GeometryReader { insideProxy in
Color.clear
.preference(
key: ScrollViewOffsetPreferenceKey.self,
value: [
self.calculateContentOffset(
fromOutsideProxy: outsideProxy,
insideProxy: insideProxy
),
self.calculateContentTrailingOffset(
fromOutsideProxy: outsideProxy,
insideProxy: insideProxy
)
]
)
}
VStack {
self.content
}
}
}
.onPreferenceChange(ScrollViewOffsetPreferenceKey.self) { value in
self.contentOffset = value[0]
if self.contentTrailingOffset != nil {
self.contentTrailingOffset = value[1]
}
}
}
}

private func calculateContentOffset(
fromOutsideProxy outsideProxy: GeometryProxy,
insideProxy: GeometryProxy
) -> CGFloat {
if axes == .vertical {
return insideProxy.frame(in: .global).minY - outsideProxy.frame(in: .global).minY
} else {
return insideProxy.frame(in: .global).minX - outsideProxy.frame(in: .global).minX
}
}

private func calculateContentTrailingOffset(
fromOutsideProxy outsideProxy: GeometryProxy,
insideProxy: GeometryProxy
) -> CGFloat {
if axes == .vertical {
return insideProxy.frame(in: .global).maxY - outsideProxy.frame(in: .global).maxY
} else {
return insideProxy.frame(in: .global).maxX - outsideProxy.frame(in: .global).maxX
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,27 +57,21 @@ final class CodeEditWindowController: NSWindowController, NSToolbarDelegate, Obs
name: "Quick Open",
title: "Quick Open",
id: "quick_open",
command: CommandClosureWrapper(closure: {
self.openQuickly(self)
})
command: CommandClosureWrapper(closure: { self.openQuickly(self) })
)

CommandManager.shared.addCommand(
name: "Toggle Left Sidebar",
title: "Toggle Left Sidebar",
id: "toggle_left_sidebar",
command: CommandClosureWrapper(closure: {
self.toggleFirstPanel()
})
command: CommandClosureWrapper(closure: { self.toggleFirstPanel() })
)

CommandManager.shared.addCommand(
name: "Toggle Right Sidebar",
title: "Toggle Right Sidebar",
id: "toggle_right_sidebar",
command: CommandClosureWrapper(closure: {
self.toggleLastPanel()
})
command: CommandClosureWrapper(closure: { self.toggleLastPanel() })
)
}

Expand All @@ -91,9 +85,7 @@ final class CodeEditWindowController: NSWindowController, NSToolbarDelegate, Obs
.environmentObject(workspace.tabManager)
}

let navigator = NSSplitViewItem(
sidebarWithViewController: NSHostingController(rootView: navigatorView)
)
let navigator = NSSplitViewItem(sidebarWithViewController: NSHostingController(rootView: navigatorView))
navigator.titlebarSeparatorStyle = .none
navigator.minimumThickness = Self.minSidebarWidth
navigator.collapseBehavior = .useConstraints
Expand All @@ -109,9 +101,7 @@ final class CodeEditWindowController: NSWindowController, NSToolbarDelegate, Obs
}
}

let mainContent = NSSplitViewItem(
viewController: NSHostingController(rootView: workspaceView)
)
let mainContent = NSSplitViewItem(viewController: NSHostingController(rootView: workspaceView))
mainContent.titlebarSeparatorStyle = .line
mainContent.holdingPriority = .init(50)

Expand All @@ -123,9 +113,7 @@ final class CodeEditWindowController: NSWindowController, NSToolbarDelegate, Obs
.environmentObject(workspace.tabManager)
}

let inspector = NSSplitViewItem(
viewController: NSHostingController(rootView: inspectorView)
)
let inspector = NSSplitViewItem(viewController: NSHostingController(rootView: inspectorView))
inspector.titlebarSeparatorStyle = .none
inspector.minimumThickness = Self.minSidebarWidth
inspector.isCollapsed = true
Expand Down
46 changes: 46 additions & 0 deletions CodeEdit/Features/Tabs/Views/TabBarShadow.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//
// TabBarShadow.swift
// CodeEdit
//
// Created by Austin Condiff on 8/22/23.
//

import SwiftUI

struct TabBarShadow: View {
var width: CGFloat
var startPoint: UnitPoint
var endPoint: UnitPoint

@Environment(\.colorScheme)
private var colorScheme

@Environment(\.controlActiveState)
private var activeState

var body: some View {
Rectangle()
.frame(maxHeight: .infinity)
.frame(width: width)
.foregroundColor(.clear)
.background(
LinearGradient(
gradient: Gradient(
stops: [
Gradient.Stop(color: .black.opacity(0.75), location: 0),
Gradient.Stop(color: .black.opacity(0.25), location: 0.5),
Gradient.Stop(color: .black.opacity(0), location: 1)
]
),
startPoint: startPoint,
endPoint: endPoint
)
.opacity(
colorScheme == .dark
? activeState == .inactive ? 0.25882353 : 1
: activeState == .inactive ? 0.09803922 : 0.25882353
)
)
.allowsHitTesting(false)
}
}
Loading