refactor: share footer action pill across launcher tools

This commit is contained in:
2026-10-18 02:08:36 +02:00
parent b13976c516
commit b325b8cfcd
5 changed files with 52 additions and 82 deletions
+43
View File
@@ -0,0 +1,43 @@
import AppKit
@MainActor
final class ActionPill: NSView {
init(primaryButton: NSButton, actionsButton: NSButton) {
super.init(frame: .zero)
wantsLayer = true
layer?.cornerRadius = 18
layer?.borderWidth = 0.5
layer?.borderColor = SunsetPalette.accent.withAlphaComponent(0.35).cgColor
layer?.backgroundColor = SunsetPalette.background.withAlphaComponent(0.25).cgColor
for button in [primaryButton, actionsButton] {
button.isBordered = false
button.font = .systemFont(ofSize: 12, weight: .medium)
button.contentTintColor = SunsetPalette.text
}
primaryButton.keyEquivalent = "\r"
primaryButton.keyEquivalentModifierMask = []
actionsButton.title = "Actions"
actionsButton.keyEquivalent = "k"
actionsButton.keyEquivalentModifierMask = .command
let returnKey = ShortcutIndicator("↵")
let actionKeys = ShortcutIndicator("⌘", "K")
for control in [primaryButton, returnKey, actionsButton, actionKeys] {
control.translatesAutoresizingMaskIntoConstraints = false
addSubview(control)
}
NSLayoutConstraint.activate([
heightAnchor.constraint(equalToConstant: 36),
primaryButton.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 14),
primaryButton.centerYAnchor.constraint(equalTo: centerYAnchor),
returnKey.leadingAnchor.constraint(equalTo: primaryButton.trailingAnchor, constant: 8),
returnKey.centerYAnchor.constraint(equalTo: centerYAnchor),
actionsButton.leadingAnchor.constraint(equalTo: returnKey.trailingAnchor, constant: 14),
actionsButton.centerYAnchor.constraint(equalTo: centerYAnchor),
actionKeys.leadingAnchor.constraint(equalTo: actionsButton.trailingAnchor, constant: 8),
actionKeys.centerYAnchor.constraint(equalTo: centerYAnchor),
actionKeys.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -12),
])
}
required init?(coder: NSCoder) { fatalError("Conjure creates action pills programmatically") }
}
+5 -20
View File
@@ -61,32 +61,17 @@ final class EmojiPickerController: NSViewController, NSCollectionViewDataSource,
status.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
copyButton.target = self
copyButton.action = #selector(copyAndPasteSelection)
copyButton.keyEquivalent = "\r"
copyButton.isBordered = false
copyButton.font = .systemFont(ofSize: 12, weight: .medium)
copyButton.contentTintColor = SunsetPalette.text
actionsButton.target = self
actionsButton.action = #selector(showActions)
actionsButton.keyEquivalent = "k"
actionsButton.keyEquivalentModifierMask = .command
actionsButton.isBordered = false
actionsButton.font = copyButton.font
actionsButton.contentTintColor = SunsetPalette.text
let pill = NSStackView(views: [copyButton, ShortcutIndicator("↵"), actionsButton, ShortcutIndicator("⌘", "K")])
pill.spacing = 8
pill.edgeInsets = NSEdgeInsets(top: 0, left: 14, bottom: 0, right: 12)
pill.wantsLayer = true
pill.layer?.cornerRadius = 18
pill.layer?.borderWidth = 0.5
pill.layer?.borderColor = SunsetPalette.accent.withAlphaComponent(0.35).cgColor
pill.layer?.backgroundColor = SunsetPalette.background.withAlphaComponent(0.25).cgColor
let pill = ActionPill(primaryButton: copyButton, actionsButton: actionsButton)
let footer = NSStackView(views: [status, NSView(), pill])
pill.heightAnchor.constraint(equalToConstant: 36).isActive = true
actions.closed = { [weak self] in
self?.copyButton.keyEquivalent = "\r"
self?.focusSearch?()
}
footer.spacing = 8
footer.orientation = .horizontal
footer.alignment = .centerY
footer.spacing = 12
for child in [category, scroll, empty, footer] {
child.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(child)
@@ -101,7 +86,7 @@ final class EmojiPickerController: NSViewController, NSCollectionViewDataSource,
empty.centerXAnchor.constraint(equalTo: scroll.centerXAnchor),
empty.centerYAnchor.constraint(equalTo: scroll.centerYAnchor),
footer.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
footer.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
footer.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -8),
footer.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -8),
footer.heightAnchor.constraint(equalToConstant: 36),
])
+1 -33
View File
@@ -330,36 +330,16 @@ final class LauncherWindowController: NSWindowController, NSWindowDelegate, NSSe
emptyLabel.textColor = SunsetPalette.secondaryText
emptyLabel.alignment = .center
openButton.isBordered = false
openButton.font = .systemFont(ofSize: 12, weight: .medium)
openButton.contentTintColor = SunsetPalette.text
openButton.keyEquivalent = "\r"
openButton.target = self
openButton.action = #selector(openSelection)
openButton.isEnabled = false
actionsButton.isBordered = false
actionsButton.title = "Actions"
actionsButton.font = .systemFont(ofSize: 12, weight: .medium)
actionsButton.contentTintColor = SunsetPalette.text
actionsButton.keyEquivalent = "k"
actionsButton.keyEquivalentModifierMask = .command
actionsButton.target = self
actionsButton.action = #selector(showActions)
actionsButton.setAccessibilityLabel("Entry actions")
actionsButton.toolTip = "Actions for the selected application or command (Command-K)"
actionsButton.isEnabled = false
openButton.toolTip = "Open the selected application (Return). Use ↑ and ↓ to select."
let returnKey = ShortcutIndicator("↵")
let actionKeys = ShortcutIndicator("⌘", "K")
let actionPill = NSView()
actionPill.wantsLayer = true
actionPill.layer?.cornerRadius = 18
actionPill.layer?.borderWidth = 0.5
for view in [openButton, returnKey, actionsButton, actionKeys] {
view.translatesAutoresizingMaskIntoConstraints = false
actionPill.addSubview(view)
}
let actionPill = ActionPill(primaryButton: openButton, actionsButton: actionsButton)
let footer = NSStackView(views: [statusLabel, NSView(), actionPill])
footer.orientation = .horizontal
@@ -388,22 +368,10 @@ final class LauncherWindowController: NSWindowController, NSWindowDelegate, NSSe
footer.trailingAnchor.constraint(equalTo: content.trailingAnchor, constant: -8),
footer.bottomAnchor.constraint(equalTo: content.bottomAnchor, constant: -8),
footer.heightAnchor.constraint(equalToConstant: 36),
actionPill.heightAnchor.constraint(equalToConstant: 36),
openButton.leadingAnchor.constraint(equalTo: actionPill.leadingAnchor, constant: 14),
openButton.centerYAnchor.constraint(equalTo: actionPill.centerYAnchor),
returnKey.leadingAnchor.constraint(equalTo: openButton.trailingAnchor, constant: 8),
actionsButton.leadingAnchor.constraint(equalTo: returnKey.trailingAnchor, constant: 14),
actionKeys.leadingAnchor.constraint(equalTo: actionsButton.trailingAnchor, constant: 8),
actionKeys.centerYAnchor.constraint(equalTo: actionPill.centerYAnchor),
actionKeys.trailingAnchor.constraint(equalTo: actionPill.trailingAnchor, constant: -12),
actionsButton.centerYAnchor.constraint(equalTo: actionPill.centerYAnchor),
returnKey.centerYAnchor.constraint(equalTo: actionPill.centerYAnchor),
])
window.effectiveAppearance.performAsCurrentDrawingAppearance {
let border = SunsetPalette.secondaryText.withAlphaComponent(0.22).cgColor
content.layer?.borderColor = border
actionPill.layer?.borderColor = SunsetPalette.accent.withAlphaComponent(0.35).cgColor
actionPill.layer?.backgroundColor = SunsetPalette.background.withAlphaComponent(0.25).cgColor
}
window.initialFirstResponder = searchField
launcherViews = [header, sectionLabel, scrollView, emptyLabel, footer]
+1 -29
View File
@@ -102,11 +102,6 @@ final class TranslationController: NSViewController {
languageButton.setAccessibilityLabel("Translation languages")
actionsButton.target = self
actionsButton.action = #selector(showActions)
actionsButton.keyEquivalent = "k"
actionsButton.keyEquivalentModifierMask = .command
actionsButton.isBordered = false
actionsButton.font = .systemFont(ofSize: 12, weight: .medium)
actionsButton.contentTintColor = SunsetPalette.text
actions.closed = { [weak self] in
self?.translateButton.keyEquivalent = "\r"
self?.focusSearch?()
@@ -122,31 +117,8 @@ final class TranslationController: NSViewController {
name: Notification.Name("ConjureTranslationCredentialsChanged"), object: nil)
translateButton.target = self
translateButton.action = #selector(performPrimaryAction)
translateButton.keyEquivalent = "\r"
translateButton.isBordered = false
translateButton.font = .systemFont(ofSize: 12, weight: .medium)
translateButton.contentTintColor = SunsetPalette.text
translateButton.toolTip = "Translate the input (Return). Escape dismisses Conjure."
let returnKey = ShortcutIndicator("↵")
let actionPill = NSView()
stylePill(actionPill)
let actionsKey = ShortcutIndicator("⌘", "K")
for control in [translateButton, returnKey, actionsButton, actionsKey] {
control.translatesAutoresizingMaskIntoConstraints = false
actionPill.addSubview(control)
}
NSLayoutConstraint.activate([
actionPill.heightAnchor.constraint(equalToConstant: 36),
translateButton.leadingAnchor.constraint(equalTo: actionPill.leadingAnchor, constant: 14),
translateButton.centerYAnchor.constraint(equalTo: actionPill.centerYAnchor),
returnKey.leadingAnchor.constraint(equalTo: translateButton.trailingAnchor, constant: 8),
returnKey.centerYAnchor.constraint(equalTo: actionPill.centerYAnchor),
actionsButton.leadingAnchor.constraint(equalTo: returnKey.trailingAnchor, constant: 14),
actionsButton.centerYAnchor.constraint(equalTo: actionPill.centerYAnchor),
actionsKey.leadingAnchor.constraint(equalTo: actionsButton.trailingAnchor, constant: 8),
actionsKey.centerYAnchor.constraint(equalTo: actionPill.centerYAnchor),
actionsKey.trailingAnchor.constraint(equalTo: actionPill.trailingAnchor, constant: -12),
])
let actionPill = ActionPill(primaryButton: translateButton, actionsButton: actionsButton)
let footer = NSStackView(views: [languageButton, status, settingsButton, NSView(), actionPill])
footer.orientation = .horizontal
footer.alignment = .centerY