diff --git a/macos/Sources/Features/Command Palette/CommandPalette.swift b/macos/Sources/Features/Command Palette/CommandPalette.swift index 73d192e76..9a3ed3965 100644 --- a/macos/Sources/Features/Command Palette/CommandPalette.swift +++ b/macos/Sources/Features/Command Palette/CommandPalette.swift @@ -4,7 +4,7 @@ struct CommandOption: Identifiable, Hashable { let id = UUID() let title: String let description: String? - let shortcut: String? + let symbols: [String]? let action: () -> Void static func == (lhs: CommandOption, rhs: CommandOption) -> Bool { @@ -18,7 +18,6 @@ struct CommandOption: Identifiable, Hashable { struct CommandPaletteView: View { @Binding var isPresented: Bool - var backgroundColor: Color = Color(nsColor: .windowBackgroundColor) var options: [CommandOption] @State private var query = "" @State private var selectedIndex: UInt? @@ -89,7 +88,6 @@ struct CommandPaletteView: View { } Divider() - .padding(.bottom, 4) CommandTable( options: filteredOptions, @@ -100,15 +98,13 @@ struct CommandPaletteView: View { } } .frame(maxWidth: 500) - .background( - RoundedRectangle(cornerRadius: 12) - .fill(backgroundColor) - .shadow(color: .black.opacity(0.4), radius: 10, x: 0, y: 10) - .overlay( - RoundedRectangle(cornerRadius: 12) - .stroke(Color.black.opacity(0.1), lineWidth: 1) - ) + .background(BackgroundVisualEffectView()) + .clipShape(RoundedRectangle(cornerRadius: 10)) + .overlay( + RoundedRectangle(cornerRadius: 10) + .stroke(Color(nsColor: .tertiaryLabelColor).opacity(0.75)) ) + .shadow(radius: 32, x: 0, y: 12) .padding() } } @@ -147,8 +143,9 @@ fileprivate struct CommandPaletteQuery: View { TextField("Execute a command…", text: $query) .padding() - .font(.system(size: 14)) - .textFieldStyle(PlainTextFieldStyle()) + .font(.system(size: 20, weight: .light)) + .frame(height: 48) + .textFieldStyle(.plain) .focused($isTextFieldFocused) .onAppear { isTextFieldFocused = true @@ -178,7 +175,7 @@ fileprivate struct CommandTable: View { .padding() } else { ScrollViewReader { proxy in - ScrollView(showsIndicators: false) { + ScrollView { VStack(alignment: .leading, spacing: 0) { ForEach(Array(options.enumerated()), id: \.1.id) { index, option in CommandRow( @@ -198,6 +195,7 @@ fileprivate struct CommandTable: View { } } } + .padding(10) } .frame(maxHeight: 200) .onChange(of: selectedIndex) { _ in @@ -223,20 +221,12 @@ fileprivate struct CommandRow: View { HStack { Text(option.title) Spacer() - if let shortcut = option.shortcut { - Text(shortcut) - .font(.system(.body, design: .monospaced)) - .kerning(1.5) - .padding(.horizontal, 6) - .padding(.vertical, 2) - .background( - RoundedRectangle(cornerRadius: 6) - .fill(Color.gray.opacity(0.2)) - ) + if let symbols = option.symbols { + ShortcutSymbolsView(symbols: symbols) + .foregroundStyle(.secondary) } } - .padding(.horizontal, 6) - .padding(.vertical, 8) + .padding(8) .background( isSelected ? Color.accentColor.opacity(0.2) @@ -244,14 +234,43 @@ fileprivate struct CommandRow: View { ? Color.secondary.opacity(0.2) : Color.clear) ) - .cornerRadius(6) + .cornerRadius(5) } .help(option.description ?? "") - .buttonStyle(PlainButtonStyle()) + .buttonStyle(.plain) .onHover { hovering in hoveredID = hovering ? option.id : nil } - .padding(.horizontal, 4) - .padding(.vertical, 1) + } +} + +/// A view that creates a semi-transparent blurry background. +fileprivate struct BackgroundVisualEffectView: NSViewRepresentable { + func makeNSView(context: Context) -> NSVisualEffectView { + let view = NSVisualEffectView() + + view.blendingMode = .withinWindow + view.state = .active + view.material = .sidebar + + return view + } + + func updateNSView(_ nsView: NSVisualEffectView, context: Context) { + // + } +} + +/// A row of Text representing a shortcut. +fileprivate struct ShortcutSymbolsView: View { + let symbols: [String] + + var body: some View { + HStack(spacing: 1) { + ForEach(symbols, id: \.self) { symbol in + Text(symbol) + .frame(minWidth: 13) + } + } } } diff --git a/macos/Sources/Features/Command Palette/TerminalCommandPalette.swift b/macos/Sources/Features/Command Palette/TerminalCommandPalette.swift index 2e895d4d9..f2c0f1989 100644 --- a/macos/Sources/Features/Command Palette/TerminalCommandPalette.swift +++ b/macos/Sources/Features/Command Palette/TerminalCommandPalette.swift @@ -40,7 +40,7 @@ struct TerminalCommandPaletteView: View { return CommandOption( title: String(cString: c.title), description: String(cString: c.description), - shortcut: ghosttyConfig.keyboardShortcut(for: action)?.description + symbols: ghosttyConfig.keyboardShortcut(for: action)?.keyList ) { onAction(action) } @@ -59,7 +59,6 @@ struct TerminalCommandPaletteView: View { CommandPaletteView( isPresented: $isPresented, - backgroundColor: ghosttyConfig.backgroundColor, options: commandOptions ) .transition( diff --git a/macos/Sources/Helpers/KeyboardShortcut+Extension.swift b/macos/Sources/Helpers/KeyboardShortcut+Extension.swift index ebef82c46..7891f12d7 100644 --- a/macos/Sources/Helpers/KeyboardShortcut+Extension.swift +++ b/macos/Sources/Helpers/KeyboardShortcut+Extension.swift @@ -1,12 +1,9 @@ import SwiftUI extension KeyboardShortcut: @retroactive CustomStringConvertible { - public var description: String { - var result = "" + public var keyList: [String] { + var result: [String] = [] - if modifiers.contains(.command) { - result.append("⌘") - } if modifiers.contains(.control) { result.append("⌃") } @@ -16,6 +13,9 @@ extension KeyboardShortcut: @retroactive CustomStringConvertible { if modifiers.contains(.shift) { result.append("⇧") } + if modifiers.contains(.command) { + result.append("⌘") + } let keyString: String switch key { @@ -24,14 +24,14 @@ extension KeyboardShortcut: @retroactive CustomStringConvertible { case .delete: keyString = "⌫" case .space: keyString = "␣" case .tab: keyString = "⇥" - case .upArrow: keyString = "↑" - case .downArrow: keyString = "↓" - case .leftArrow: keyString = "←" - case .rightArrow: keyString = "→" - case .pageUp: keyString = "PgUp" - case .pageDown: keyString = "PgDown" - case .end: keyString = "End" - case .home: keyString = "Home" + case .upArrow: keyString = "▲" + case .downArrow: keyString = "▼" + case .leftArrow: keyString = "◀" + case .rightArrow: keyString = "▶" + case .pageUp: keyString = "↑" + case .pageDown: keyString = "↓" + case .home: keyString = "⤒" + case .end: keyString = "⤓" default: keyString = String(key.character.uppercased()) } @@ -39,6 +39,10 @@ extension KeyboardShortcut: @retroactive CustomStringConvertible { result.append(keyString) return result } + + public var description: String { + return self.keyList.joined() + } } // This is available in macOS 14 so this only applies to early macOS versions.