SPB Git

spb/zyquo-cloud Public MIT

Native macOS AI chat client for 12 cloud providers — your keys, every cloud model, one beautiful chat.

Swift 97.4% Shell 1.7% Makefile 1%
3.3 KB · 113 lines swift
Raw Blame History
1//2//  Components.swift3//  Zyquo Cloud4//5//  Author: Simon-Pierre Boucher6//  Mail: contact@spboucher.ai7//8//  Small reusable design-system components and interaction modifiers shared9//  across all screens: hover states, press scaling, badges, provider glyphs.10//1112import SwiftUI1314// MARK: - Interaction modifiers1516/// Standard hover feedback: background tint fades in over 80ms.17struct HoverHighlight: ViewModifier {18    var cornerRadius: CGFloat = ZyquoRadius.small19    @State private var hovering = false2021    func body(content: Content) -> some View {22        content23            .background(24                RoundedRectangle(cornerRadius: cornerRadius, style: .continuous)25                    .fill(hovering ? ZyquoColor.surfaceSecondary : .clear)26            )27            .onHover { inside in28                withAnimation(ZyquoMotion.hover) { hovering = inside }29            }30    }31}3233/// Button press feedback: scale to 0.97.34struct PressableButtonStyle: ButtonStyle {35    func makeBody(configuration: Configuration) -> some View {36        configuration.label37            .scaleEffect(configuration.isPressed ? ZyquoMotion.pressedScale : 1)38            .animation(ZyquoMotion.hover, value: configuration.isPressed)39    }40}4142extension View {43    func zyquoHoverHighlight(cornerRadius: CGFloat = ZyquoRadius.small) -> some View {44        modifier(HoverHighlight(cornerRadius: cornerRadius))45    }46}4748// MARK: - Badges4950/// Small capsule badge (model chips metadata, capability tags).51struct ZyquoBadge: View {52    let text: String53    var color: Color = ZyquoColor.textSecondary5455    var body: some View {56        Text(text)57            .font(ZyquoFont.caption)58            .foregroundStyle(color)59            .padding(.horizontal, ZyquoSpacing.xs)60            .padding(.vertical, 2)61            .background(62                Capsule().fill(ZyquoColor.surfaceSecondary)63            )64    }65}6667/// Colored status dot (provider key state: verified / unset / failed).68struct StatusDot: View {69    enum Status {70        case verified, unset, failed7172        var color: Color {73            switch self {74            case .verified: return ZyquoColor.success75            case .unset: return ZyquoColor.textTertiary76            case .failed: return ZyquoColor.danger77            }78        }79    }8081    let status: Status8283    var body: some View {84        Circle()85            .fill(status.color)86            .frame(width: 8, height: 8)87    }88}8990// MARK: - Provider glyphs9192extension ProviderID {93    /// SF Symbol used as the provider's glyph in chips, avatars, and Settings.94    /// (Custom vector logos can replace these later without touching call sites.)95    var symbolName: String {96        switch self {97        case .openai: return "sparkle"98        case .anthropic: return "asterisk"99        case .xai: return "xmark.diamond"100        case .mistral: return "wind"101        case .gemini: return "diamond.lefthalf.filled"102        case .qwen: return "q.circle"103        case .deepseek: return "water.waves"104        case .kimi: return "moon.stars"105        case .perplexity: return "magnifyingglass.circle"106        case .together: return "circle.hexagongrid"107        case .deepinfra: return "cube.transparent"108        case .cerebras: return "bolt.circle"109        case .custom: return "wrench.and.screwdriver"110        }111    }112}113