Func is one button with a dark panel of functions; Translator (⌃⌥R or Func): selected text RU<->EN via macOS Translation or claude Haiku, card holds the notch open

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
maksarsanjeev
2026-10-07 15:57:06 +03:00
parent 9570dc190f
commit e11d06c73e
7 changed files with 356 additions and 13 deletions
+83 -13
View File
@@ -13,23 +13,93 @@ import Darwin
struct FuncPill: View {
@ObservedObject var state: AppState
@Binding var showSystem: Bool
@State private var open = false
@State private var hovered = false
var body: some View {
HStack(spacing: 6) {
Text("Func")
.font(.system(size: 12, weight: .semibold, design: .monospaced))
.foregroundColor(Color(hex: "#8E939C"))
.padding(.leading, 12)
Spacer(minLength: 4)
FuncButton(symbol: "eyedropper", title: "Пипетка") { ColorPicking.start(state: state) }
FuncButton(symbol: "cpu", title: "Мак") {
withAnimation(.easeOut(duration: 0.18)) { showSystem.toggle() }
Button { open.toggle() } label: {
HStack(spacing: 8) {
Image(systemName: "square.grid.2x2.fill")
.font(.system(size: 13))
.foregroundColor(Color(hex: "#A78BFA"))
Text("Func")
.font(.system(size: 13, weight: .semibold, design: .monospaced))
.foregroundColor(Color(hex: "#F5F6F8"))
Spacer(minLength: 4)
Image(systemName: open ? "chevron.up" : "chevron.down")
.font(.system(size: 9, weight: .semibold))
.foregroundColor(Color(hex: "#5F646D"))
}
.padding(.horizontal, 12)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(RoundedRectangle(cornerRadius: 14, style: .continuous)
.fill(hovered || open ? Color(hex: "#A78BFA").opacity(0.14) : Color(hex: "#0E0F11")))
.overlay(RoundedRectangle(cornerRadius: 14, style: .continuous)
.stroke(Color(hex: "#A78BFA").opacity(hovered || open ? 0.5 : 0.2), lineWidth: 1))
.contentShape(Rectangle())
}
.padding(.trailing, 6)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(RoundedRectangle(cornerRadius: 14, style: .continuous).fill(Color(hex: "#0E0F11")))
.overlay(RoundedRectangle(cornerRadius: 14, style: .continuous).stroke(Color.white.opacity(0.10), lineWidth: 1))
.buttonStyle(.plain)
.onHover { h in withAnimation(.easeOut(duration: 0.12)) { hovered = h } }
.popover(isPresented: $open, arrowEdge: .bottom) {
VStack(alignment: .leading, spacing: 2) {
FuncRow(symbol: "eyedropper", color: "#F472B6", title: "Пипетка",
subtitle: "цвет пикселя во всех форматах", hint: nil) {
open = false
ColorPicking.start(state: state)
}
FuncRow(symbol: "cpu", color: "#34D399", title: "Мак",
subtitle: "CPU, ядра, ОЗУ, SSD", hint: nil) {
open = false
state.translation = nil
withAnimation(.easeOut(duration: 0.18)) { showSystem = true }
}
FuncRow(symbol: "character.bubble", color: "#60A5FA", title: "Переводчик",
subtitle: "выделенный текст RU ↔ EN", hint: "⌃⌥R") {
open = false
showSystem = false
TranslatorRun.start(state: state)
}
}
.padding(8)
.frame(width: 280)
.notchPopoverStyle()
}
}
}
struct FuncRow: View {
let symbol: String
let color: String
let title: String
let subtitle: String
let hint: String?
let action: () -> Void
@State private var hovered = false
var body: some View {
Button(action: action) {
HStack(spacing: 10) {
Image(systemName: symbol)
.font(.system(size: 13, weight: .semibold))
.foregroundColor(Color(hex: color))
.frame(width: 26, height: 26)
.background(RoundedRectangle(cornerRadius: 7).fill(Color(hex: color).opacity(0.15)))
VStack(alignment: .leading, spacing: 1) {
Text(title).font(.system(size: 13, weight: .semibold))
Text(subtitle).font(.system(size: 11)).foregroundColor(.secondary)
}
Spacer()
if let hint {
Text(hint).font(.system(size: 11, design: .rounded)).foregroundColor(.secondary)
}
}
.padding(.horizontal, 8)
.padding(.vertical, 6)
.background(RoundedRectangle(cornerRadius: 8).fill(Color.primary.opacity(hovered ? 0.08 : 0)))
.contentShape(Rectangle())
}
.buttonStyle(.plain)
.onHover { hovered = $0 }
}
}