Skip to content

Instantly share code, notes, and snippets.

@larsaugustin
Created May 26, 2021 15:33
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save larsaugustin/80df680285d21b086c38257469f5461e to your computer and use it in GitHub Desktop.
Save larsaugustin/80df680285d21b086c38257469f5461e to your computer and use it in GitHub Desktop.
A macOS dock replacement with a modernized version of the design used before Yosemite
import SwiftUI
// MARK: - Constants
// Items in the dock: Add any application you’d like to see in here
let items =
[
"file:///Applications/Xcode.app",
"file:///Applications/Safari.app",
"file:///System/Applications/Messages.app",
"file:///System/Applications/Music.app"
]
// MARK: - View
struct ContentView: View {
// Used to refresh the view periodically
@State var refresh = false
var body: some View {
VStack {
Spacer()
// Front
ZStack(alignment: .bottom) {
RoundedRectangle(cornerRadius: 5)
.fill(
Color(red: 216/255, green: 216/255, blue: 216/255).opacity(0.9))
.mask(
VStack {
Spacer()
Rectangle()
.fill(Color.blue)
.frame(height: 6).padding(.horizontal, 1.5)
}
)
// Shelf
RoundedRectangle(cornerRadius: 5)
.fill(
LinearGradient(
gradient: Gradient(
colors: [Color(red: 155/255, green: 155/255, blue: 155/255).opacity(0.5), Color.white.opacity(0.85)]),
startPoint: .top, endPoint: .bottom)
)
.frame(height: 85)
.rotation3DEffect(
Angle(degrees: 50),
axis: (x: 1, y: 0, z: 0), anchor: .bottom
)
.offset(x: 0, y: -4)
.shadow(color: .white, radius: 0, x: 0, y: 1)
// Icons
HStack {
ForEach(items, id: \.self) { item in
Button {
guard let url = URL(string: item) else { return }
NSWorkspace.shared.open(url)
} label: {
SystemIcon(forURL: item)?.resizable().aspectRatio(contentMode: .fit)
}.buttonStyle(PlainButtonStyle())
}
}.frame(height: 75).offset(y: -15)
// Reflections
HStack {
ForEach(items, id: \.self) { item in
SystemIcon(forURL: item)?.resizable().aspectRatio(contentMode: .fit)
}
}.frame(height: 75)
.rotation3DEffect(
Angle(degrees: 180),
axis: (x: 1, y: 0, z: 0.0)
)
.offset(y: 57)
.mask(
Rectangle()
.offset(y: -2)
)
.blur(radius: 4)
.opacity(0.3)
// Running indicators
HStack(alignment: .bottom, spacing: 70) {
ForEach(items, id: \.self) { item in
if NSWorkspace.shared
.runningApplications
.first(where: { $0.bundleURL?.absoluteString.contains(item) ?? false }) != nil {
Rectangle()
.fill(Color.white)
.frame(width: 13, height: 8)
.offset(y: 5)
.shadow(color: Color(red: 168/255, green: 238/255, blue: 1), radius: 7, x: 0, y: 0)
} else {
Spacer().frame(width: 13)
}
}.opacity(refresh ? 1 : 1)
}
}
}.onAppear {
_ = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: { _ in
refresh.toggle()
})
}
}
}
// MARK: - Supporting Functions
func SystemIcon(forURL url: String) -> Image? {
guard let icon =
NSWorkspace.shared.icon(forFile: url.replacingOccurrences(of: "file://", with: ""))
.representations
.first(where: { $0.size.width > 150 })?
.cgImage(forProposedRect: nil, context: nil, hints: nil)
else { return nil }
let nsImage = NSImage(cgImage: icon, size: CGSize(width: icon.width, height: icon.height))
return Image(nsImage: nsImage)
}
import Cocoa
import SwiftUI
@main
class AppDelegate: NSObject, NSApplicationDelegate {
var window: NSWindow!
func applicationDidFinishLaunching(_ aNotification: Notification) {
let contentView = ContentView()
let width = CGFloat(items.count) * 83 + 80
window = NSWindow(
contentRect: NSRect(x: (NSScreen.main!.frame.width - width) / 2, y: 0, width: width, height: 130),
styleMask: [.fullSizeContentView],
backing: .buffered, defer: false)
window.hasShadow = false
window.backgroundColor = .clear
window.level = NSWindow.Level(1000)
window.collectionBehavior = .canJoinAllSpaces
window.contentView = NSHostingView(rootView: contentView)
window.makeKeyAndOrderFront(nil)
}
func applicationWillTerminate(_ aNotification: Notification) { }
}

If you want to hide the application’s icon from the actual dock (which you can place on either side of the screen and hide), add the LSUIElement key to your Info.plist.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment