import AppKit import CoreText @MainActor final class ShortcutIndicator: NSStackView { init(_ keys: String...) { super.init(frame: .zero) orientation = .horizontal alignment = .centerY spacing = 2 setHuggingPriority(.required, for: .horizontal) setHuggingPriority(.required, for: .vertical) translatesAutoresizingMaskIntoConstraints = false setAccessibilityElement(false) for key in keys { let badge = ShortcutKeyBadge(labelWithString: key) badge.font = .systemFont(ofSize: 12, weight: .medium) badge.textColor = SunsetPalette.secondaryText badge.alignment = .center badge.wantsLayer = true badge.layer?.cornerRadius = 5 badge.layer?.borderWidth = 1 badge.layer?.borderColor = SunsetPalette.secondaryText.withAlphaComponent(0.35).cgColor badge.setAccessibilityElement(false) badge.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ badge.widthAnchor.constraint(equalToConstant: 18), badge.heightAnchor.constraint(equalToConstant: 18) ]) addArrangedSubview(badge) } } required init?(coder: NSCoder) { fatalError("Conjure creates shortcut indicators programmatically") } } @MainActor private final class ShortcutKeyBadge: NSTextField { // NSTextField's horizontal alignment insets otherwise make an 18-point badge 22 points wide. override var alignmentRectInsets: NSEdgeInsets { NSEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) } override func draw(_ dirtyRect: NSRect) { guard let context = NSGraphicsContext.current?.cgContext else { return } let line = CTLineCreateWithAttributedString(attributedStringValue) let ink = CTLineGetBoundsWithOptions(line, .useGlyphPathBounds) context.saveGState() context.textMatrix = .identity // Center visible ink, not the font's asymmetric ascender/descender line box. context.translateBy(x: bounds.midX - ink.midX, y: bounds.midY + ink.midY) context.scaleBy(x: 1, y: -1) context.textPosition = .zero CTLineDraw(line, context) context.restoreGState() } }