SPB Git

spb/zyquo-agent Public MIT

The autonomous agent that actually operates your Mac — plans, runs real commands, verifies its own work.

Swift 94.7% Shell 4.1% Python 0.7% Makefile 0.5%
4.5 KB · 111 lines swift
Raw Blame History
1//2//  AppearanceSettingsTab.swift3//  Zyquo Agent4//5//  Author: Simon-Pierre Boucher6//  Mail: contact@spboucher.ai7//8//  Settings › Appearance — theme mode (Light/Dark/System), the five accent9//  choices with swatches (violet flagship + graphite, sky, emerald, amber),10//  and the chat font size slider (12–18pt) with live preview.11//1213import SwiftUI1415struct AppearanceSettingsTab: View {16    @EnvironmentObject private var appearance: AppearanceStore1718    var body: some View {19        Form {20            Picker("Theme", selection: $appearance.themeMode) {21                ForEach(ThemeMode.allCases) { mode in22                    Text(mode.displayName).tag(mode)23                }24            }25            .pickerStyle(.segmented)2627            VStack(alignment: .leading, spacing: ZyquoSpacing.xs) {28                Text("Accent")29                HStack(spacing: ZyquoSpacing.sm) {30                    ForEach(AccentChoice.allCases) { choice in31                        accentSwatch(choice)32                    }33                    Spacer(minLength: 0)34                }35            }3637            VStack(alignment: .leading, spacing: ZyquoSpacing.xs) {38                HStack {39                    Text("Chat font size")40                    Spacer()41                    Text(String(format: "%.1f pt", appearance.chatFontSize))42                        .font(ZyquoFont.caption)43                        .foregroundStyle(ZyquoColor.textSecondary)44                        .monospacedDigit()45                }46                Slider(value: $appearance.chatFontSize, in: 12...18, step: 0.5)47                VStack(alignment: .leading, spacing: ZyquoSpacing.xxs) {48                    Text("Preview")49                        .font(ZyquoFont.caption)50                        .foregroundStyle(ZyquoColor.textTertiary)51                    Text("The quick brown fox jumps over the lazy dog — Zyquo Agent renders task text at this size, with generous 1.45 line height for readability.")52                        .font(ZyquoFont.body(size: appearance.chatFontSize))53                        .lineSpacing(appearance.chatFontSize * ZyquoFont.bodyLineSpacingFactor)54                        .foregroundStyle(ZyquoColor.textPrimary)55                        .padding(ZyquoSpacing.sm)56                        .frame(maxWidth: .infinity, alignment: .leading)57                        .background(58                            RoundedRectangle(cornerRadius: ZyquoRadius.medium, style: .continuous)59                                .fill(ZyquoColor.surface)60                                .overlay(61                                    RoundedRectangle(cornerRadius: ZyquoRadius.medium, style: .continuous)62                                        .strokeBorder(ZyquoColor.border, lineWidth: ZyquoMetrics.hairline)63                                )64                        )65                }66            }67        }68        .formStyle(.grouped)69    }7071    private func accentSwatch(_ choice: AccentChoice) -> some View {72        let isSelected = appearance.accent == choice73        return Button {74            withAnimation(ZyquoMotion.appear) { appearance.accent = choice }75        } label: {76            VStack(spacing: ZyquoSpacing.xxs) {77                Circle()78                    .fill(swatchColor(choice))79                    .frame(width: 26, height: 26)80                    .overlay(81                        Circle().strokeBorder(82                            isSelected ? ZyquoColor.textPrimary : ZyquoColor.border,83                            lineWidth: isSelected ? 2 : ZyquoMetrics.hairline84                        )85                    )86                    .overlay {87                        if isSelected {88                            Image(systemName: "checkmark")89                                .font(.system(size: 10, weight: .bold))90                                .foregroundStyle(.white)91                        }92                    }93                Text(choice.displayName)94                    .font(ZyquoFont.caption)95                    .foregroundStyle(isSelected ? ZyquoColor.textPrimary : ZyquoColor.textSecondary)96            }97        }98        .buttonStyle(PressableButtonStyle())99        .help("\(choice.displayName) accent")100    }101102    /// Appearance-resolved swatch color for one accent choice.103    private func swatchColor(_ choice: AccentChoice) -> Color {104        let (light, dark) = choice.accentHex105        return Color(nsColor: NSColor(name: nil) { appearance in106            let hex = appearance.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua ? dark : light107            return NSColor(hex: hex)108        })109    }110}111