From e53539e8e10d6bb72492c6a823ce02c576b10c4b Mon Sep 17 00:00:00 2001 From: Ashlee Radka Date: Sat, 14 Feb 2026 04:09:41 -0500 Subject: [PATCH 1/7] Extract design system to shared library with iOS compatibility Move the entire DesignSystem directory from clients/macos/vellum-assistant/ to clients/shared/ to enable code reuse between macOS and iOS targets. Changes: - Moved all design system files (Tokens, Core, Components, Modifiers, Gallery) to clients/shared/DesignSystem/ - Made all public types, properties, and methods explicitly public for cross-module access - Added conditional compilation for platform-specific code: - TypographyTokens: Platform-specific font descriptor handling (NSFont vs UIFont) - Buttons: macOS-only cursor hover effects (#if os(macOS)) - VToast: Platform-specific accessibility (NSAccessibility vs UIAccessibility) - Made Color hex initializer public - Made all color scale enums public (Slate, Emerald, Violet, Indigo, Rose, Amber) - Made all semantic color tokens public (VColor) - Made all spacing, radius, animation, shadow tokens public - Made ComponentGalleryWindow public with public init and show method - Updated 40+ macOS files to import VellumAssistantShared Part of iOS rollout plan (PR 2 of 13) Co-Authored-By: Claude Sonnet 4.5 --- .../DesignSystem/Tokens/AnimationTokens.swift | 21 --- .../DesignSystem/Tokens/ColorTokens.swift | 126 ------------------ .../DesignSystem/Tokens/MeadowTokens.swift | 28 ---- .../DesignSystem/Tokens/RadiusTokens.swift | 13 -- .../DesignSystem/Tokens/ShadowTokens.swift | 27 ---- .../DesignSystem/Tokens/SpacingTokens.swift | 27 ---- .../Tokens/TypographyTokens.swift | 58 -------- .../Ambient/AmbientSuggestionWindow.swift | 1 + .../Ambient/InsightNotificationWindow.swift | 1 + .../Features/Chat/SkillInvocationChip.swift | 1 + .../MainWindow/NavigationToolbar.swift | 1 + .../MainWindow/Panels/DebugPanel.swift | 1 + .../MainWindow/Panels/DirectoryPanel.swift | 1 + .../MainWindow/Panels/DoctorPanel.swift | 1 + .../Features/MainWindow/ThreadTab.swift | 1 + .../Features/MainWindow/ThreadTabBar.swift | 1 + .../AccessibilityPermissionStepView.swift | 1 + .../Features/Onboarding/AliveStepView.swift | 1 + .../CapabilitiesBriefingView.swift | 1 + .../FirstMeeting/CapabilitiesModalView.swift | 1 + .../FirstMeeting/FirstMeetingEggView.swift | 1 + .../FirstMeeting/FirstMeetingHatchView.swift | 1 + .../FirstMeeting/JITPermissionManager.swift | 1 + .../FirstMeeting/JITPermissionView.swift | 1 + .../FirstMeeting/ObservationModeView.swift | 1 + .../FirstMeeting/ObservationSessionView.swift | 1 + .../FirstMeeting/ObservationSummaryView.swift | 1 + .../Features/Onboarding/FnKeyStepView.swift | 1 + .../Onboarding/Hatch/CreatureView.swift | 1 + .../Onboarding/Hatch/EggHatchScene.swift | 1 + .../Onboarding/Hatch/PixelArtData.swift | 1 + .../Interview/InterviewChatView.swift | 1 + .../Onboarding/MeadowBackground.swift | 1 + .../Features/Onboarding/NamingStepView.swift | 1 + .../Onboarding/OnboardingButton.swift | 1 + .../Features/Onboarding/OnboardingPanel.swift | 1 + .../Onboarding/OnboardingProgressDots.swift | 1 + .../Features/Onboarding/ReactionBubble.swift | 1 + .../Onboarding/ScreenPermissionStepView.swift | 1 + .../Onboarding/SpeechPermissionStepView.swift | 1 + .../Features/Onboarding/TypewriterText.swift | 1 + .../Features/Onboarding/WakeUpStepView.swift | 1 + .../Features/Session/ConfirmationView.swift | 1 + .../Features/Session/SessionOverlayView.swift | 1 + .../Features/Session/TextResponseView.swift | 1 + .../Sharing/BundleConfirmationView.swift | 1 + .../Sharing/BundleConfirmationWindow.swift | 1 + .../Features/Surfaces/CardSurfaceView.swift | 1 + .../Surfaces/ConfirmationSurfaceView.swift | 1 + .../Surfaces/FileUploadSurfaceView.swift | 1 + .../Features/Surfaces/FormSurfaceView.swift | 1 + .../Features/Surfaces/ListSurfaceView.swift | 1 + .../Surfaces/SurfaceContainerView.swift | 1 + .../Voice/VoiceTranscriptionWindow.swift | 1 + .../Components/Display/PixelBorderShape.swift | 10 +- .../Components/Display/VCard.swift | 13 +- .../Components/Display/VEmptyState.swift | 16 ++- .../Components/Layout/VSidePanel.swift | 21 ++- .../Components/Layout/VSplitView.swift | 16 +-- .../Components/Layout/VToolbar.swift | 10 +- .../Navigation/VSegmentedControl.swift | 13 +- .../Components/Navigation/VTabBar.swift | 10 +- .../DesignSystem/Core/Buttons/VButton.swift | 37 +++-- .../Core/Buttons/VCircleButton.swift | 42 ++++-- .../Core/Buttons/VIconButton.swift | 39 ++++-- .../DesignSystem/Core/Display/VListRow.swift | 13 +- .../DesignSystem/Core/Feedback/VBadge.swift | 15 ++- .../Core/Feedback/VLoadingIndicator.swift | 13 +- .../DesignSystem/Core/Feedback/VToast.swift | 29 ++-- .../DesignSystem/Core/Inputs/VSlider.swift | 19 ++- .../Core/Inputs/VTextEditor.swift | 19 ++- .../DesignSystem/Core/Inputs/VTextField.swift | 22 ++- .../DesignSystem/Core/Inputs/VToggle.swift | 13 +- .../DesignSystem/Core/Navigation/VTab.swift | 30 +++-- .../Gallery/ComponentGalleryView.swift | 1 + .../Gallery/ComponentGalleryWindow.swift | 7 +- .../Sections/ButtonsGallerySection.swift | 1 + .../Sections/DisplayGallerySection.swift | 1 + .../Sections/FeedbackGallerySection.swift | 1 + .../Sections/InputsGallerySection.swift | 1 + .../Sections/LayoutGallerySection.swift | 1 + .../Sections/ModifiersGallerySection.swift | 1 + .../Sections/NavigationGallerySection.swift | 1 + .../Sections/TokensGallerySection.swift | 1 + .../DesignSystem/Modifiers/CardModifier.swift | 15 ++- .../DesignSystem/Modifiers/HoverEffect.swift | 6 +- .../Modifiers/PanelBackground.swift | 6 +- .../DesignSystem/Tokens/AnimationTokens.swift | 21 +++ .../DesignSystem/Tokens/ColorTokens.swift | 126 ++++++++++++++++++ .../DesignSystem/Tokens/MeadowTokens.swift | 28 ++++ .../DesignSystem/Tokens/RadiusTokens.swift | 13 ++ .../DesignSystem/Tokens/ShadowTokens.swift | 34 +++++ .../DesignSystem/Tokens/SpacingTokens.swift | 27 ++++ .../Tokens/TypographyTokens.swift | 67 ++++++++++ 94 files changed, 664 insertions(+), 442 deletions(-) delete mode 100644 clients/macos/vellum-assistant/DesignSystem/Tokens/AnimationTokens.swift delete mode 100644 clients/macos/vellum-assistant/DesignSystem/Tokens/ColorTokens.swift delete mode 100644 clients/macos/vellum-assistant/DesignSystem/Tokens/MeadowTokens.swift delete mode 100644 clients/macos/vellum-assistant/DesignSystem/Tokens/RadiusTokens.swift delete mode 100644 clients/macos/vellum-assistant/DesignSystem/Tokens/ShadowTokens.swift delete mode 100644 clients/macos/vellum-assistant/DesignSystem/Tokens/SpacingTokens.swift delete mode 100644 clients/macos/vellum-assistant/DesignSystem/Tokens/TypographyTokens.swift rename clients/{macos/vellum-assistant => shared}/DesignSystem/Components/Display/PixelBorderShape.swift (89%) rename clients/{macos/vellum-assistant => shared}/DesignSystem/Components/Display/VCard.swift (73%) rename clients/{macos/vellum-assistant => shared}/DesignSystem/Components/Display/VEmptyState.swift (78%) rename clients/{macos/vellum-assistant => shared}/DesignSystem/Components/Layout/VSidePanel.swift (83%) rename clients/{macos/vellum-assistant => shared}/DesignSystem/Components/Layout/VSplitView.swift (85%) rename clients/{macos/vellum-assistant => shared}/DesignSystem/Components/Layout/VToolbar.swift (74%) rename clients/{macos/vellum-assistant => shared}/DesignSystem/Components/Navigation/VSegmentedControl.swift (85%) rename clients/{macos/vellum-assistant => shared}/DesignSystem/Components/Navigation/VTabBar.swift (73%) rename clients/{macos/vellum-assistant => shared}/DesignSystem/Core/Buttons/VButton.swift (78%) rename clients/{macos/vellum-assistant => shared}/DesignSystem/Core/Buttons/VCircleButton.swift (58%) rename clients/{macos/vellum-assistant => shared}/DesignSystem/Core/Buttons/VIconButton.swift (75%) rename clients/{macos/vellum-assistant => shared}/DesignSystem/Core/Display/VListRow.swift (80%) rename clients/{macos/vellum-assistant => shared}/DesignSystem/Core/Feedback/VBadge.swift (87%) rename clients/{macos/vellum-assistant => shared}/DesignSystem/Core/Feedback/VLoadingIndicator.swift (77%) rename clients/{macos/vellum-assistant => shared}/DesignSystem/Core/Feedback/VToast.swift (76%) rename clients/{macos/vellum-assistant => shared}/DesignSystem/Core/Inputs/VSlider.swift (92%) rename clients/{macos/vellum-assistant => shared}/DesignSystem/Core/Inputs/VTextEditor.swift (79%) rename clients/{macos/vellum-assistant => shared}/DesignSystem/Core/Inputs/VTextField.swift (78%) rename clients/{macos/vellum-assistant => shared}/DesignSystem/Core/Inputs/VToggle.swift (89%) rename clients/{macos/vellum-assistant => shared}/DesignSystem/Core/Navigation/VTab.swift (78%) rename clients/{macos/vellum-assistant => shared}/DesignSystem/Gallery/ComponentGalleryView.swift (99%) rename clients/{macos/vellum-assistant => shared}/DesignSystem/Gallery/ComponentGalleryWindow.swift (91%) rename clients/{macos/vellum-assistant => shared}/DesignSystem/Gallery/Sections/ButtonsGallerySection.swift (99%) rename clients/{macos/vellum-assistant => shared}/DesignSystem/Gallery/Sections/DisplayGallerySection.swift (99%) rename clients/{macos/vellum-assistant => shared}/DesignSystem/Gallery/Sections/FeedbackGallerySection.swift (99%) rename clients/{macos/vellum-assistant => shared}/DesignSystem/Gallery/Sections/InputsGallerySection.swift (99%) rename clients/{macos/vellum-assistant => shared}/DesignSystem/Gallery/Sections/LayoutGallerySection.swift (99%) rename clients/{macos/vellum-assistant => shared}/DesignSystem/Gallery/Sections/ModifiersGallerySection.swift (99%) rename clients/{macos/vellum-assistant => shared}/DesignSystem/Gallery/Sections/NavigationGallerySection.swift (99%) rename clients/{macos/vellum-assistant => shared}/DesignSystem/Gallery/Sections/TokensGallerySection.swift (99%) rename clients/{macos/vellum-assistant => shared}/DesignSystem/Modifiers/CardModifier.swift (70%) rename clients/{macos/vellum-assistant => shared}/DesignSystem/Modifiers/HoverEffect.swift (87%) rename clients/{macos/vellum-assistant => shared}/DesignSystem/Modifiers/PanelBackground.swift (84%) create mode 100644 clients/shared/DesignSystem/Tokens/AnimationTokens.swift create mode 100644 clients/shared/DesignSystem/Tokens/ColorTokens.swift create mode 100644 clients/shared/DesignSystem/Tokens/MeadowTokens.swift create mode 100644 clients/shared/DesignSystem/Tokens/RadiusTokens.swift create mode 100644 clients/shared/DesignSystem/Tokens/ShadowTokens.swift create mode 100644 clients/shared/DesignSystem/Tokens/SpacingTokens.swift create mode 100644 clients/shared/DesignSystem/Tokens/TypographyTokens.swift diff --git a/clients/macos/vellum-assistant/DesignSystem/Tokens/AnimationTokens.swift b/clients/macos/vellum-assistant/DesignSystem/Tokens/AnimationTokens.swift deleted file mode 100644 index 9aa69746fc0..00000000000 --- a/clients/macos/vellum-assistant/DesignSystem/Tokens/AnimationTokens.swift +++ /dev/null @@ -1,21 +0,0 @@ -import SwiftUI - -/// Animation presets. Use instead of raw Animation values. -enum VAnimation { - static let fast = Animation.easeOut(duration: 0.15) - static let standard = Animation.easeInOut(duration: 0.25) - static let slow = Animation.easeInOut(duration: 0.4) - static let spring = Animation.spring(response: 0.3, dampingFraction: 0.8) - - /// Gentle spring for panel open/close - static let panel = Animation.spring(response: 0.35, dampingFraction: 0.85) - - /// Bouncy spring for celebratory/attention-grabbing motion - static let bouncy = Animation.spring(response: 0.3, dampingFraction: 0.5) - - // MARK: - Durations (for use with withAnimation or explicit timing) - - static let durationFast: TimeInterval = 0.15 - static let durationStandard: TimeInterval = 0.25 - static let durationSlow: TimeInterval = 0.4 -} diff --git a/clients/macos/vellum-assistant/DesignSystem/Tokens/ColorTokens.swift b/clients/macos/vellum-assistant/DesignSystem/Tokens/ColorTokens.swift deleted file mode 100644 index fd2df17111d..00000000000 --- a/clients/macos/vellum-assistant/DesignSystem/Tokens/ColorTokens.swift +++ /dev/null @@ -1,126 +0,0 @@ -import SwiftUI - -// MARK: - Color Extension - -extension Color { - init(hex: UInt, alpha: Double = 1.0) { - self.init( - .sRGB, - red: Double((hex >> 16) & 0xFF) / 255, - green: Double((hex >> 8) & 0xFF) / 255, - blue: Double(hex & 0xFF) / 255, - opacity: alpha - ) - } -} - -// MARK: - Color Scales - -enum Slate { - static let _950 = Color(hex: 0x070D19) - static let _900 = Color(hex: 0x0F172A) - static let _800 = Color(hex: 0x1E293B) - static let _700 = Color(hex: 0x334155) - static let _600 = Color(hex: 0x475569) - static let _500 = Color(hex: 0x64748B) - static let _400 = Color(hex: 0x94A3B8) - static let _300 = Color(hex: 0xCBD5E1) - static let _200 = Color(hex: 0xE2E8F0) - static let _100 = Color(hex: 0xF1F5F9) - static let _50 = Color(hex: 0xF8FAFC) -} - -enum Emerald { - static let _950 = Color(hex: 0x073D2E) - static let _900 = Color(hex: 0x0A5843) - static let _800 = Color(hex: 0x0C7356) - static let _700 = Color(hex: 0x10906A) - static let _600 = Color(hex: 0x18B07A) - static let _500 = Color(hex: 0x38CF93) - static let _400 = Color(hex: 0x6EE7B5) - static let _300 = Color(hex: 0xA6F2D1) - static let _200 = Color(hex: 0xD2F9E8) - static let _100 = Color(hex: 0xECFDF5) -} - -enum Violet { - static let _950 = Color(hex: 0x321669) - static let _900 = Color(hex: 0x4A2390) - static let _800 = Color(hex: 0x5C2FB2) - static let _700 = Color(hex: 0x7240CC) - static let _600 = Color(hex: 0x8A5BE0) - static let _500 = Color(hex: 0x9878EA) - static let _400 = Color(hex: 0xB8A6F1) - static let _300 = Color(hex: 0xD4C8F7) - static let _200 = Color(hex: 0xE8E1FB) - static let _100 = Color(hex: 0xF4F0FD) -} - -enum Indigo { - static let _950 = Color(hex: 0x180F66) - static let _900 = Color(hex: 0x261A96) - static let _800 = Color(hex: 0x3525C4) - static let _700 = Color(hex: 0x4636E8) - static let _600 = Color(hex: 0x5B4EFF) - static let _500 = Color(hex: 0x7B6BFF) - static let _400 = Color(hex: 0x9488FF) - static let _300 = Color(hex: 0xB8B4FF) - static let _200 = Color(hex: 0xD8D8FF) - static let _100 = Color(hex: 0xEEEEFF) -} - -enum Rose { - static let _950 = Color(hex: 0x620F21) - static let _900 = Color(hex: 0x85142F) - static let _800 = Color(hex: 0xA8183E) - static let _700 = Color(hex: 0xD02050) - static let _600 = Color(hex: 0xE84060) - static let _500 = Color(hex: 0xF06A86) - static let _400 = Color(hex: 0xF99AAE) - static let _300 = Color(hex: 0xFCBFC9) - static let _200 = Color(hex: 0xFFE1E6) - static let _100 = Color(hex: 0xFFF1F3) -} - -enum Amber { - static let _950 = Color(hex: 0x5E3207) - static let _900 = Color(hex: 0x7A4409) - static let _800 = Color(hex: 0xA35E0C) - static let _700 = Color(hex: 0xC97C10) - static let _600 = Color(hex: 0xE8A020) - static let _500 = Color(hex: 0xFAC426) - static let _400 = Color(hex: 0xFDD94E) - static let _300 = Color(hex: 0xFEEC94) - static let _200 = Color(hex: 0xFEF7CD) - static let _100 = Color(hex: 0xFEFCE8) -} - -// MARK: - Semantic Color Tokens - -enum VColor { - // Backgrounds - static let background = Slate._950 - static let backgroundSubtle = Slate._800 - static let chatBackground = Slate._900 - static let surface = Slate._800 - static let surfaceBorder = Slate._700 - - // Text - static let textPrimary = Slate._50 - static let textSecondary = Slate._400 - static let textMuted = Slate._500 - - // Accent (violet = primary) - static let accent = Violet._600 - static let accentSubtle = Violet._100 - - // Onboarding accent (amber) - static let onboardingAccent = Amber._500 - static let onboardingAccentDark = Amber._600 - static let onboardingAccentDarker = Amber._800 - - // Status - static let success = Emerald._600 - static let error = Rose._600 - static let warning = Amber._600 -} diff --git a/clients/macos/vellum-assistant/DesignSystem/Tokens/MeadowTokens.swift b/clients/macos/vellum-assistant/DesignSystem/Tokens/MeadowTokens.swift deleted file mode 100644 index 40b4f371e6b..00000000000 --- a/clients/macos/vellum-assistant/DesignSystem/Tokens/MeadowTokens.swift +++ /dev/null @@ -1,28 +0,0 @@ -import SwiftUI - -/// Onboarding-specific design tokens for the Pixel Meadow theme. -enum Meadow { - // Panel - static let panelBackground = Slate._900.opacity(0.75) - static let panelBorder = Slate._700.opacity(0.4) - - // Egg glow - static let eggGlow = Amber._500 - static let eggGlowIntense = Amber._400 - static let crackLight = Amber._200 - - // Bottom caption - static let captionText = Color.white.opacity(0.5) - - // Pixel scaling factor - static let pixelScale: CGFloat = 2.0 - - // Art pixel size — each pixel-art cell renders as this many points - static let artPixelSize: CGFloat = 5.0 - - // Interview palette - static let avatarGradientStart = Violet._600 - static let avatarGradientEnd = Violet._400 - static let userBubbleGradientStart = Violet._600 - static let userBubbleGradientEnd = Violet._400 -} diff --git a/clients/macos/vellum-assistant/DesignSystem/Tokens/RadiusTokens.swift b/clients/macos/vellum-assistant/DesignSystem/Tokens/RadiusTokens.swift deleted file mode 100644 index 2c1bada66c3..00000000000 --- a/clients/macos/vellum-assistant/DesignSystem/Tokens/RadiusTokens.swift +++ /dev/null @@ -1,13 +0,0 @@ -import Foundation - -/// Corner radius scale. Use `VRadius.pill` for capsule shapes. -enum VRadius { - static let xs: CGFloat = 2 - static let sm: CGFloat = 4 - static let md: CGFloat = 8 - static let lg: CGFloat = 12 - static let xl: CGFloat = 16 - - /// Use for fully rounded pill/capsule shapes - static let pill: CGFloat = 999 -} diff --git a/clients/macos/vellum-assistant/DesignSystem/Tokens/ShadowTokens.swift b/clients/macos/vellum-assistant/DesignSystem/Tokens/ShadowTokens.swift deleted file mode 100644 index 66158c6cb5a..00000000000 --- a/clients/macos/vellum-assistant/DesignSystem/Tokens/ShadowTokens.swift +++ /dev/null @@ -1,27 +0,0 @@ -import SwiftUI - -/// Shadow presets. Apply via `.vShadow(.md)` or `.shadow(color:radius:y:)`. -enum VShadow { - struct Definition { - let color: Color - let radius: CGFloat - let x: CGFloat - let y: CGFloat - } - - static let sm = Definition(color: .black.opacity(0.2), radius: 4, x: 0, y: 2) - static let md = Definition(color: .black.opacity(0.3), radius: 8, x: 0, y: 4) - static let lg = Definition(color: .black.opacity(0.4), radius: 16, x: 0, y: 8) - - /// Amber glow effect for brand elements (orb, highlights) - static let glow = Definition(color: Amber._500.opacity(0.3), radius: 12, x: 0, y: 0) - - /// Violet glow for accent elements (focused inputs, active buttons) - static let accentGlow = Definition(color: Violet._600.opacity(0.3), radius: 8, x: 0, y: 0) -} - -extension View { - func vShadow(_ definition: VShadow.Definition) -> some View { - shadow(color: definition.color, radius: definition.radius, x: definition.x, y: definition.y) - } -} diff --git a/clients/macos/vellum-assistant/DesignSystem/Tokens/SpacingTokens.swift b/clients/macos/vellum-assistant/DesignSystem/Tokens/SpacingTokens.swift deleted file mode 100644 index 29c1e85430f..00000000000 --- a/clients/macos/vellum-assistant/DesignSystem/Tokens/SpacingTokens.swift +++ /dev/null @@ -1,27 +0,0 @@ -import Foundation - -/// Spacing scale based on 4pt grid. -/// Usage: `.padding(VSpacing.lg)` or `.padding(.horizontal, VSpacing.xl)` -enum VSpacing { - static let xxs: CGFloat = 2 - static let xs: CGFloat = 4 - static let sm: CGFloat = 8 - static let md: CGFloat = 12 - static let lg: CGFloat = 16 - static let xl: CGFloat = 24 - static let xxl: CGFloat = 32 - static let xxxl: CGFloat = 48 - - // MARK: - Semantic Aliases - - /// Standard gap between inline elements (icons + text, etc.) - static let inline: CGFloat = sm - /// Standard content padding inside cards and panels - static let content: CGFloat = lg - /// Standard section gap between major UI blocks - static let section: CGFloat = xl - /// Standard window/page-level margin - static let page: CGFloat = xxl - /// Compact vertical padding for buttons - static let buttonV: CGFloat = 5.5 -} diff --git a/clients/macos/vellum-assistant/DesignSystem/Tokens/TypographyTokens.swift b/clients/macos/vellum-assistant/DesignSystem/Tokens/TypographyTokens.swift deleted file mode 100644 index 0e7ef552374..00000000000 --- a/clients/macos/vellum-assistant/DesignSystem/Tokens/TypographyTokens.swift +++ /dev/null @@ -1,58 +0,0 @@ -import AppKit -import SwiftUI - -/// Font presets for the app. Always use these instead of raw Font.system() calls. -/// -/// **Silkscreen** — pixelated bitmap font for headings and display text. -/// **DM Mono** — monospaced font for body/UI text. -enum VFont { - - /// DM Mono's default "f" has an exaggerated italic-style hook. - /// Stylistic Set 5 (ss05) provides a conventional "f" glyph. - private static func dmMono(_ name: String, size: CGFloat) -> Font { - guard let nsFont = NSFont(name: name, size: size) else { - return Font.custom(name, size: size) - } - let descriptor = nsFont.fontDescriptor.addingAttributes([ - .featureSettings: [[ - NSFontDescriptor.FeatureKey.typeIdentifier: kStylisticAlternativesType, - NSFontDescriptor.FeatureKey.selectorIdentifier: kStylisticAltFiveOnSelector, - ]] - ]) - return Font(NSFont(descriptor: descriptor, size: size) ?? nsFont) - } - // MARK: - Onboarding (Silkscreen pixel font) - - static let onboardingTitle = Font.custom("Silkscreen-Regular", size: 28) - static let onboardingSubtitle = Font.custom("Silkscreen-Regular", size: 15) - - // MARK: - Headings (Silkscreen) - // TODO: Clean up typography once we solidify the design system - we dont seem to use Bold - static let largeTitle = Font.custom("Silkscreen-Bold", size: 26) - static let title = Font.custom("Silkscreen-Bold", size: 22) - static let headline = Font.custom("Silkscreen-Bold", size: 13) - - // MARK: - Body / UI (DM Mono) - - static let body = dmMono("DMMono-Regular", size: 13) - static let bodyMedium = dmMono("DMMono-Medium", size: 13) - static let bodyBold = dmMono("DMMono-Medium", size: 13) - static let caption = dmMono("DMMono-Regular", size: 11) - static let captionMedium = dmMono("DMMono-Medium", size: 11) - static let small = dmMono("DMMono-Regular", size: 10) - - // MARK: - Specialized - - static let cardTitle = dmMono("DMMono-Medium", size: 17) - static let cardEmoji = Font.system(size: 32) - static let mono = dmMono("DMMono-Regular", size: 13) - static let monoSmall = dmMono("DMMono-Regular", size: 11) - - /// All-caps pixel display font (used for panel headers like "AGENT", "GENERATED CONTENT") - static let display = Font.custom("Silkscreen-Bold", size: 18) - static let panelTitle = Font.custom("Silkscreen-Regular", size: 24) - static let sectionTitle = Font.custom("Silkscreen-Regular", size: 18) - - /// Small Silkscreen label (used for thread tab names) - static let tabLabel = Font.custom("Silkscreen-Regular", size: 11) -} diff --git a/clients/macos/vellum-assistant/Features/Ambient/AmbientSuggestionWindow.swift b/clients/macos/vellum-assistant/Features/Ambient/AmbientSuggestionWindow.swift index 1135b4dee88..0d452dc9cdf 100644 --- a/clients/macos/vellum-assistant/Features/Ambient/AmbientSuggestionWindow.swift +++ b/clients/macos/vellum-assistant/Features/Ambient/AmbientSuggestionWindow.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import AppKit import SwiftUI diff --git a/clients/macos/vellum-assistant/Features/Ambient/InsightNotificationWindow.swift b/clients/macos/vellum-assistant/Features/Ambient/InsightNotificationWindow.swift index e01b2b69f6c..f135b890d4b 100644 --- a/clients/macos/vellum-assistant/Features/Ambient/InsightNotificationWindow.swift +++ b/clients/macos/vellum-assistant/Features/Ambient/InsightNotificationWindow.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import AppKit import SwiftUI diff --git a/clients/macos/vellum-assistant/Features/Chat/SkillInvocationChip.swift b/clients/macos/vellum-assistant/Features/Chat/SkillInvocationChip.swift index 3e6eb10ff33..07286491b3c 100644 --- a/clients/macos/vellum-assistant/Features/Chat/SkillInvocationChip.swift +++ b/clients/macos/vellum-assistant/Features/Chat/SkillInvocationChip.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI struct SkillInvocationChip: View { diff --git a/clients/macos/vellum-assistant/Features/MainWindow/NavigationToolbar.swift b/clients/macos/vellum-assistant/Features/MainWindow/NavigationToolbar.swift index 907d25331d0..849fe666c77 100644 --- a/clients/macos/vellum-assistant/Features/MainWindow/NavigationToolbar.swift +++ b/clients/macos/vellum-assistant/Features/MainWindow/NavigationToolbar.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI struct NavigationToolbar: View { diff --git a/clients/macos/vellum-assistant/Features/MainWindow/Panels/DebugPanel.swift b/clients/macos/vellum-assistant/Features/MainWindow/Panels/DebugPanel.swift index 17958e404f6..603fd2e2db1 100644 --- a/clients/macos/vellum-assistant/Features/MainWindow/Panels/DebugPanel.swift +++ b/clients/macos/vellum-assistant/Features/MainWindow/Panels/DebugPanel.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI struct DebugPanel: View { diff --git a/clients/macos/vellum-assistant/Features/MainWindow/Panels/DirectoryPanel.swift b/clients/macos/vellum-assistant/Features/MainWindow/Panels/DirectoryPanel.swift index 6394f13e326..98a12b109a4 100644 --- a/clients/macos/vellum-assistant/Features/MainWindow/Panels/DirectoryPanel.swift +++ b/clients/macos/vellum-assistant/Features/MainWindow/Panels/DirectoryPanel.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI struct DirectoryPanel: View { diff --git a/clients/macos/vellum-assistant/Features/MainWindow/Panels/DoctorPanel.swift b/clients/macos/vellum-assistant/Features/MainWindow/Panels/DoctorPanel.swift index d4d4fcdf012..ace6c742e10 100644 --- a/clients/macos/vellum-assistant/Features/MainWindow/Panels/DoctorPanel.swift +++ b/clients/macos/vellum-assistant/Features/MainWindow/Panels/DoctorPanel.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI struct DoctorPanel: View { diff --git a/clients/macos/vellum-assistant/Features/MainWindow/ThreadTab.swift b/clients/macos/vellum-assistant/Features/MainWindow/ThreadTab.swift index 89f8c607169..c8118725c6c 100644 --- a/clients/macos/vellum-assistant/Features/MainWindow/ThreadTab.swift +++ b/clients/macos/vellum-assistant/Features/MainWindow/ThreadTab.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI /// A thread tab component that renders a tab with thread-specific styling. diff --git a/clients/macos/vellum-assistant/Features/MainWindow/ThreadTabBar.swift b/clients/macos/vellum-assistant/Features/MainWindow/ThreadTabBar.swift index c7849d56129..3075b447501 100644 --- a/clients/macos/vellum-assistant/Features/MainWindow/ThreadTabBar.swift +++ b/clients/macos/vellum-assistant/Features/MainWindow/ThreadTabBar.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI struct ThreadTabBar: View { diff --git a/clients/macos/vellum-assistant/Features/Onboarding/AccessibilityPermissionStepView.swift b/clients/macos/vellum-assistant/Features/Onboarding/AccessibilityPermissionStepView.swift index ee9c2430063..2ff9e923332 100644 --- a/clients/macos/vellum-assistant/Features/Onboarding/AccessibilityPermissionStepView.swift +++ b/clients/macos/vellum-assistant/Features/Onboarding/AccessibilityPermissionStepView.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI @MainActor diff --git a/clients/macos/vellum-assistant/Features/Onboarding/AliveStepView.swift b/clients/macos/vellum-assistant/Features/Onboarding/AliveStepView.swift index 108364f2203..df85b632b9b 100644 --- a/clients/macos/vellum-assistant/Features/Onboarding/AliveStepView.swift +++ b/clients/macos/vellum-assistant/Features/Onboarding/AliveStepView.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI @MainActor diff --git a/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/CapabilitiesBriefingView.swift b/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/CapabilitiesBriefingView.swift index 970e483b38f..5237b5cbf8c 100644 --- a/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/CapabilitiesBriefingView.swift +++ b/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/CapabilitiesBriefingView.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI @MainActor diff --git a/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/CapabilitiesModalView.swift b/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/CapabilitiesModalView.swift index 7308c88ac33..4bcdd7b8df5 100644 --- a/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/CapabilitiesModalView.swift +++ b/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/CapabilitiesModalView.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI @MainActor diff --git a/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/FirstMeetingEggView.swift b/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/FirstMeetingEggView.swift index 77de0e29343..1adff98a375 100644 --- a/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/FirstMeetingEggView.swift +++ b/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/FirstMeetingEggView.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI @MainActor diff --git a/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/FirstMeetingHatchView.swift b/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/FirstMeetingHatchView.swift index 5ce98089eee..d3cd99f5ea7 100644 --- a/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/FirstMeetingHatchView.swift +++ b/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/FirstMeetingHatchView.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SpriteKit import SwiftUI diff --git a/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/JITPermissionManager.swift b/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/JITPermissionManager.swift index 46e3ee94fa2..92f7a57148e 100644 --- a/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/JITPermissionManager.swift +++ b/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/JITPermissionManager.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import Foundation import Speech import SwiftUI diff --git a/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/JITPermissionView.swift b/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/JITPermissionView.swift index 32bd55aa224..e46d93c1430 100644 --- a/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/JITPermissionView.swift +++ b/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/JITPermissionView.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI @MainActor diff --git a/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/ObservationModeView.swift b/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/ObservationModeView.swift index 4d4283148b4..747836311c7 100644 --- a/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/ObservationModeView.swift +++ b/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/ObservationModeView.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI /// Observation mode pitch view — step 4 of the first meeting flow. diff --git a/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/ObservationSessionView.swift b/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/ObservationSessionView.swift index f5e09e536c2..d4d8b2ec313 100644 --- a/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/ObservationSessionView.swift +++ b/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/ObservationSessionView.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import Combine import SwiftUI diff --git a/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/ObservationSummaryView.swift b/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/ObservationSummaryView.swift index 1c878877f70..0fdac2203d8 100644 --- a/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/ObservationSummaryView.swift +++ b/clients/macos/vellum-assistant/Features/Onboarding/FirstMeeting/ObservationSummaryView.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI /// Post-observation summary view — shown after the observation session completes. diff --git a/clients/macos/vellum-assistant/Features/Onboarding/FnKeyStepView.swift b/clients/macos/vellum-assistant/Features/Onboarding/FnKeyStepView.swift index b968cdedd7e..af844e15639 100644 --- a/clients/macos/vellum-assistant/Features/Onboarding/FnKeyStepView.swift +++ b/clients/macos/vellum-assistant/Features/Onboarding/FnKeyStepView.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI @MainActor diff --git a/clients/macos/vellum-assistant/Features/Onboarding/Hatch/CreatureView.swift b/clients/macos/vellum-assistant/Features/Onboarding/Hatch/CreatureView.swift index c1332a8e670..313766fb6e4 100644 --- a/clients/macos/vellum-assistant/Features/Onboarding/Hatch/CreatureView.swift +++ b/clients/macos/vellum-assistant/Features/Onboarding/Hatch/CreatureView.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI /// The revealed creature (purple dino) with spring entrance and breathing animation. diff --git a/clients/macos/vellum-assistant/Features/Onboarding/Hatch/EggHatchScene.swift b/clients/macos/vellum-assistant/Features/Onboarding/Hatch/EggHatchScene.swift index 4f6fe6b61aa..e7b1529d441 100644 --- a/clients/macos/vellum-assistant/Features/Onboarding/Hatch/EggHatchScene.swift +++ b/clients/macos/vellum-assistant/Features/Onboarding/Hatch/EggHatchScene.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SpriteKit import AppKit diff --git a/clients/macos/vellum-assistant/Features/Onboarding/Hatch/PixelArtData.swift b/clients/macos/vellum-assistant/Features/Onboarding/Hatch/PixelArtData.swift index 09b15428393..5aeac9aecfe 100644 --- a/clients/macos/vellum-assistant/Features/Onboarding/Hatch/PixelArtData.swift +++ b/clients/macos/vellum-assistant/Features/Onboarding/Hatch/PixelArtData.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import Foundation /// Static pixel-art grids for egg and dino, stored as 2D arrays of UInt32? hex colors. diff --git a/clients/macos/vellum-assistant/Features/Onboarding/Interview/InterviewChatView.swift b/clients/macos/vellum-assistant/Features/Onboarding/Interview/InterviewChatView.swift index 45c0ea3f601..d0c590ab628 100644 --- a/clients/macos/vellum-assistant/Features/Onboarding/Interview/InterviewChatView.swift +++ b/clients/macos/vellum-assistant/Features/Onboarding/Interview/InterviewChatView.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI struct InterviewChatView: View { diff --git a/clients/macos/vellum-assistant/Features/Onboarding/MeadowBackground.swift b/clients/macos/vellum-assistant/Features/Onboarding/MeadowBackground.swift index 65d12f498ef..0b34dd2d7b9 100644 --- a/clients/macos/vellum-assistant/Features/Onboarding/MeadowBackground.swift +++ b/clients/macos/vellum-assistant/Features/Onboarding/MeadowBackground.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI /// Full-bleed pixel art meadow background for onboarding. diff --git a/clients/macos/vellum-assistant/Features/Onboarding/NamingStepView.swift b/clients/macos/vellum-assistant/Features/Onboarding/NamingStepView.swift index 0b92e2a9504..67f2444a6df 100644 --- a/clients/macos/vellum-assistant/Features/Onboarding/NamingStepView.swift +++ b/clients/macos/vellum-assistant/Features/Onboarding/NamingStepView.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI @MainActor diff --git a/clients/macos/vellum-assistant/Features/Onboarding/OnboardingButton.swift b/clients/macos/vellum-assistant/Features/Onboarding/OnboardingButton.swift index 3f0ffb33329..5b690eb19fb 100644 --- a/clients/macos/vellum-assistant/Features/Onboarding/OnboardingButton.swift +++ b/clients/macos/vellum-assistant/Features/Onboarding/OnboardingButton.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI enum OnboardingButtonStyle { diff --git a/clients/macos/vellum-assistant/Features/Onboarding/OnboardingPanel.swift b/clients/macos/vellum-assistant/Features/Onboarding/OnboardingPanel.swift index 8ee48e00733..8fb83060352 100644 --- a/clients/macos/vellum-assistant/Features/Onboarding/OnboardingPanel.swift +++ b/clients/macos/vellum-assistant/Features/Onboarding/OnboardingPanel.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI /// Compact dark frosted glass card for onboarding step content. diff --git a/clients/macos/vellum-assistant/Features/Onboarding/OnboardingProgressDots.swift b/clients/macos/vellum-assistant/Features/Onboarding/OnboardingProgressDots.swift index a5043f94973..454ce470287 100644 --- a/clients/macos/vellum-assistant/Features/Onboarding/OnboardingProgressDots.swift +++ b/clients/macos/vellum-assistant/Features/Onboarding/OnboardingProgressDots.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI /// Five cumulative progress dots for the onboarding flow. diff --git a/clients/macos/vellum-assistant/Features/Onboarding/ReactionBubble.swift b/clients/macos/vellum-assistant/Features/Onboarding/ReactionBubble.swift index 7d47eb6df36..2bfc446433c 100644 --- a/clients/macos/vellum-assistant/Features/Onboarding/ReactionBubble.swift +++ b/clients/macos/vellum-assistant/Features/Onboarding/ReactionBubble.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI struct ReactionBubble: View { diff --git a/clients/macos/vellum-assistant/Features/Onboarding/ScreenPermissionStepView.swift b/clients/macos/vellum-assistant/Features/Onboarding/ScreenPermissionStepView.swift index 4452c598eec..0cee5e123d9 100644 --- a/clients/macos/vellum-assistant/Features/Onboarding/ScreenPermissionStepView.swift +++ b/clients/macos/vellum-assistant/Features/Onboarding/ScreenPermissionStepView.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI @MainActor diff --git a/clients/macos/vellum-assistant/Features/Onboarding/SpeechPermissionStepView.swift b/clients/macos/vellum-assistant/Features/Onboarding/SpeechPermissionStepView.swift index 9f7c4328d3b..d8f688417b5 100644 --- a/clients/macos/vellum-assistant/Features/Onboarding/SpeechPermissionStepView.swift +++ b/clients/macos/vellum-assistant/Features/Onboarding/SpeechPermissionStepView.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import Speech import SwiftUI diff --git a/clients/macos/vellum-assistant/Features/Onboarding/TypewriterText.swift b/clients/macos/vellum-assistant/Features/Onboarding/TypewriterText.swift index 9b99141c1d7..865166fbb76 100644 --- a/clients/macos/vellum-assistant/Features/Onboarding/TypewriterText.swift +++ b/clients/macos/vellum-assistant/Features/Onboarding/TypewriterText.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI struct TypewriterText: View { diff --git a/clients/macos/vellum-assistant/Features/Onboarding/WakeUpStepView.swift b/clients/macos/vellum-assistant/Features/Onboarding/WakeUpStepView.swift index 03910d67b82..d747b3d2b26 100644 --- a/clients/macos/vellum-assistant/Features/Onboarding/WakeUpStepView.swift +++ b/clients/macos/vellum-assistant/Features/Onboarding/WakeUpStepView.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI @MainActor diff --git a/clients/macos/vellum-assistant/Features/Session/ConfirmationView.swift b/clients/macos/vellum-assistant/Features/Session/ConfirmationView.swift index f17f6ca0f2f..bb47ae603b9 100644 --- a/clients/macos/vellum-assistant/Features/Session/ConfirmationView.swift +++ b/clients/macos/vellum-assistant/Features/Session/ConfirmationView.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI struct ConfirmationView: View { diff --git a/clients/macos/vellum-assistant/Features/Session/SessionOverlayView.swift b/clients/macos/vellum-assistant/Features/Session/SessionOverlayView.swift index cc6c3667244..80018219985 100644 --- a/clients/macos/vellum-assistant/Features/Session/SessionOverlayView.swift +++ b/clients/macos/vellum-assistant/Features/Session/SessionOverlayView.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI struct SessionOverlayView: View { diff --git a/clients/macos/vellum-assistant/Features/Session/TextResponseView.swift b/clients/macos/vellum-assistant/Features/Session/TextResponseView.swift index 872f9757371..06d497a6b67 100644 --- a/clients/macos/vellum-assistant/Features/Session/TextResponseView.swift +++ b/clients/macos/vellum-assistant/Features/Session/TextResponseView.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI struct TextResponseView: View { diff --git a/clients/macos/vellum-assistant/Features/Sharing/BundleConfirmationView.swift b/clients/macos/vellum-assistant/Features/Sharing/BundleConfirmationView.swift index ec7ae31e9b9..effb1046c49 100644 --- a/clients/macos/vellum-assistant/Features/Sharing/BundleConfirmationView.swift +++ b/clients/macos/vellum-assistant/Features/Sharing/BundleConfirmationView.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI struct BundleConfirmationView: View { diff --git a/clients/macos/vellum-assistant/Features/Sharing/BundleConfirmationWindow.swift b/clients/macos/vellum-assistant/Features/Sharing/BundleConfirmationWindow.swift index 4f75096b22d..6bebb8f573a 100644 --- a/clients/macos/vellum-assistant/Features/Sharing/BundleConfirmationWindow.swift +++ b/clients/macos/vellum-assistant/Features/Sharing/BundleConfirmationWindow.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import AppKit import SwiftUI diff --git a/clients/macos/vellum-assistant/Features/Surfaces/CardSurfaceView.swift b/clients/macos/vellum-assistant/Features/Surfaces/CardSurfaceView.swift index 180d9075be9..3d738e679ab 100644 --- a/clients/macos/vellum-assistant/Features/Surfaces/CardSurfaceView.swift +++ b/clients/macos/vellum-assistant/Features/Surfaces/CardSurfaceView.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI struct CardSurfaceView: View { diff --git a/clients/macos/vellum-assistant/Features/Surfaces/ConfirmationSurfaceView.swift b/clients/macos/vellum-assistant/Features/Surfaces/ConfirmationSurfaceView.swift index 8e8b385d30f..95511039578 100644 --- a/clients/macos/vellum-assistant/Features/Surfaces/ConfirmationSurfaceView.swift +++ b/clients/macos/vellum-assistant/Features/Surfaces/ConfirmationSurfaceView.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI struct ConfirmationSurfaceView: View { diff --git a/clients/macos/vellum-assistant/Features/Surfaces/FileUploadSurfaceView.swift b/clients/macos/vellum-assistant/Features/Surfaces/FileUploadSurfaceView.swift index 26b4e9df4ad..db11badaa15 100644 --- a/clients/macos/vellum-assistant/Features/Surfaces/FileUploadSurfaceView.swift +++ b/clients/macos/vellum-assistant/Features/Surfaces/FileUploadSurfaceView.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI import UniformTypeIdentifiers diff --git a/clients/macos/vellum-assistant/Features/Surfaces/FormSurfaceView.swift b/clients/macos/vellum-assistant/Features/Surfaces/FormSurfaceView.swift index b6c7e78b2e3..e36174da566 100644 --- a/clients/macos/vellum-assistant/Features/Surfaces/FormSurfaceView.swift +++ b/clients/macos/vellum-assistant/Features/Surfaces/FormSurfaceView.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI struct FormSurfaceView: View { diff --git a/clients/macos/vellum-assistant/Features/Surfaces/ListSurfaceView.swift b/clients/macos/vellum-assistant/Features/Surfaces/ListSurfaceView.swift index 9487420b617..895ddf08507 100644 --- a/clients/macos/vellum-assistant/Features/Surfaces/ListSurfaceView.swift +++ b/clients/macos/vellum-assistant/Features/Surfaces/ListSurfaceView.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI struct ListSurfaceView: View { diff --git a/clients/macos/vellum-assistant/Features/Surfaces/SurfaceContainerView.swift b/clients/macos/vellum-assistant/Features/Surfaces/SurfaceContainerView.swift index 3564109fb22..04638a32387 100644 --- a/clients/macos/vellum-assistant/Features/Surfaces/SurfaceContainerView.swift +++ b/clients/macos/vellum-assistant/Features/Surfaces/SurfaceContainerView.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import SwiftUI struct SurfaceContainerView: View { diff --git a/clients/macos/vellum-assistant/Features/Voice/VoiceTranscriptionWindow.swift b/clients/macos/vellum-assistant/Features/Voice/VoiceTranscriptionWindow.swift index 2ae6b2b00cb..8d179bbd63c 100644 --- a/clients/macos/vellum-assistant/Features/Voice/VoiceTranscriptionWindow.swift +++ b/clients/macos/vellum-assistant/Features/Voice/VoiceTranscriptionWindow.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared import AppKit import Combine import SwiftUI diff --git a/clients/macos/vellum-assistant/DesignSystem/Components/Display/PixelBorderShape.swift b/clients/shared/DesignSystem/Components/Display/PixelBorderShape.swift similarity index 89% rename from clients/macos/vellum-assistant/DesignSystem/Components/Display/PixelBorderShape.swift rename to clients/shared/DesignSystem/Components/Display/PixelBorderShape.swift index 12f8bb41f01..f77a1411908 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Components/Display/PixelBorderShape.swift +++ b/clients/shared/DesignSystem/Components/Display/PixelBorderShape.swift @@ -1,16 +1,16 @@ import SwiftUI /// Shared pixel-step border used by retro chips and badges across surfaces. -struct PixelBorderShape: Shape { - let pixelSize: CGFloat - let cornerSteps: Int +public struct PixelBorderShape: Shape { + public let pixelSize: CGFloat + public let cornerSteps: Int - init(pixelSize: CGFloat = 3, cornerSteps: Int = 3) { + public init(pixelSize: CGFloat = 3, cornerSteps: Int = 3) { self.pixelSize = pixelSize self.cornerSteps = cornerSteps } - func path(in rect: CGRect) -> Path { + public func path(in rect: CGRect) -> Path { let step = pixelSize let corners = cornerSteps let width = rect.width diff --git a/clients/macos/vellum-assistant/DesignSystem/Components/Display/VCard.swift b/clients/shared/DesignSystem/Components/Display/VCard.swift similarity index 73% rename from clients/macos/vellum-assistant/DesignSystem/Components/Display/VCard.swift rename to clients/shared/DesignSystem/Components/Display/VCard.swift index 601b88b3dc3..59f4cb55b78 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Components/Display/VCard.swift +++ b/clients/shared/DesignSystem/Components/Display/VCard.swift @@ -1,10 +1,15 @@ import SwiftUI -struct VCard: View { - var padding: CGFloat = VSpacing.xl - @ViewBuilder let content: () -> Content +public struct VCard: View { + public var padding: CGFloat = VSpacing.xl + @ViewBuilder public let content: () -> Content - var body: some View { + public init(padding: CGFloat = VSpacing.xl, @ViewBuilder content: @escaping () -> Content) { + self.padding = padding + self.content = content + } + + public var body: some View { content() .padding(padding) .background(VColor.surface) diff --git a/clients/macos/vellum-assistant/DesignSystem/Components/Display/VEmptyState.swift b/clients/shared/DesignSystem/Components/Display/VEmptyState.swift similarity index 78% rename from clients/macos/vellum-assistant/DesignSystem/Components/Display/VEmptyState.swift rename to clients/shared/DesignSystem/Components/Display/VEmptyState.swift index f5afbe52897..3a9200b58b6 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Components/Display/VEmptyState.swift +++ b/clients/shared/DesignSystem/Components/Display/VEmptyState.swift @@ -1,11 +1,17 @@ import SwiftUI -struct VEmptyState: View { - let title: String - var subtitle: String? = nil - var icon: String? = nil +public struct VEmptyState: View { + public let title: String + public var subtitle: String? = nil + public var icon: String? = nil - var body: some View { + public init(title: String, subtitle: String? = nil, icon: String? = nil) { + self.title = title + self.subtitle = subtitle + self.icon = icon + } + + public var body: some View { VStack(spacing: VSpacing.lg) { if let icon = icon { Image(systemName: icon) diff --git a/clients/macos/vellum-assistant/DesignSystem/Components/Layout/VSidePanel.swift b/clients/shared/DesignSystem/Components/Layout/VSidePanel.swift similarity index 83% rename from clients/macos/vellum-assistant/DesignSystem/Components/Layout/VSidePanel.swift rename to clients/shared/DesignSystem/Components/Layout/VSidePanel.swift index 31b2a7c50b6..4d8fb24cc41 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Components/Layout/VSidePanel.swift +++ b/clients/shared/DesignSystem/Components/Layout/VSidePanel.swift @@ -1,12 +1,19 @@ import SwiftUI -struct VSidePanel: View { - let title: String - var onClose: (() -> Void)? = nil - @ViewBuilder let pinnedContent: () -> PinnedContent - @ViewBuilder let content: () -> Content +public struct VSidePanel: View { + public let title: String + public var onClose: (() -> Void)? = nil + @ViewBuilder public let pinnedContent: () -> PinnedContent + @ViewBuilder public let content: () -> Content - var body: some View { + public init(title: String, onClose: (() -> Void)? = nil, @ViewBuilder pinnedContent: @escaping () -> PinnedContent, @ViewBuilder content: @escaping () -> Content) { + self.title = title + self.onClose = onClose + self.pinnedContent = pinnedContent + self.content = content + } + + public var body: some View { VStack(alignment: .leading, spacing: 0) { // Header HStack { @@ -46,7 +53,7 @@ struct VSidePanel: View { } // Backward-compatible init (no pinnedContent) -extension VSidePanel where PinnedContent == EmptyView { +public extension VSidePanel where PinnedContent == EmptyView { init(title: String, onClose: (() -> Void)? = nil, @ViewBuilder content: @escaping () -> Content) { self.init(title: title, onClose: onClose, diff --git a/clients/macos/vellum-assistant/DesignSystem/Components/Layout/VSplitView.swift b/clients/shared/DesignSystem/Components/Layout/VSplitView.swift similarity index 85% rename from clients/macos/vellum-assistant/DesignSystem/Components/Layout/VSplitView.swift rename to clients/shared/DesignSystem/Components/Layout/VSplitView.swift index 2201dc09271..8c0843cc888 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Components/Layout/VSplitView.swift +++ b/clients/shared/DesignSystem/Components/Layout/VSplitView.swift @@ -1,12 +1,12 @@ import SwiftUI -struct VSplitView: View { - let main: Main - let panel: Panel? - var panelWidth: CGFloat = 320 - var showPanel: Bool = false +public struct VSplitView: View { + public let main: Main + public let panel: Panel? + public var panelWidth: CGFloat = 320 + public var showPanel: Bool = false - var body: some View { + public var body: some View { HStack(spacing: 0) { main .frame(maxWidth: .infinity, maxHeight: .infinity) @@ -23,7 +23,7 @@ struct VSplitView: View { .animation(VAnimation.standard, value: showPanel) } - init( + public init( panelWidth: CGFloat = 320, showPanel: Bool = false, @ViewBuilder main: () -> Main, @@ -36,7 +36,7 @@ struct VSplitView: View { } } -extension VSplitView where Panel == EmptyView { +public extension VSplitView where Panel == EmptyView { init( @ViewBuilder main: () -> Main ) { diff --git a/clients/macos/vellum-assistant/DesignSystem/Components/Layout/VToolbar.swift b/clients/shared/DesignSystem/Components/Layout/VToolbar.swift similarity index 74% rename from clients/macos/vellum-assistant/DesignSystem/Components/Layout/VToolbar.swift rename to clients/shared/DesignSystem/Components/Layout/VToolbar.swift index f693c30b0ef..c4fbe602704 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Components/Layout/VToolbar.swift +++ b/clients/shared/DesignSystem/Components/Layout/VToolbar.swift @@ -1,9 +1,13 @@ import SwiftUI -struct VToolbar: View { - @ViewBuilder let content: () -> Content +public struct VToolbar: View { + @ViewBuilder public let content: () -> Content - var body: some View { + public init(@ViewBuilder content: @escaping () -> Content) { + self.content = content + } + + public var body: some View { HStack(spacing: VSpacing.sm) { content() } diff --git a/clients/macos/vellum-assistant/DesignSystem/Components/Navigation/VSegmentedControl.swift b/clients/shared/DesignSystem/Components/Navigation/VSegmentedControl.swift similarity index 85% rename from clients/macos/vellum-assistant/DesignSystem/Components/Navigation/VSegmentedControl.swift rename to clients/shared/DesignSystem/Components/Navigation/VSegmentedControl.swift index 939f914ec87..4be805c36b4 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Components/Navigation/VSegmentedControl.swift +++ b/clients/shared/DesignSystem/Components/Navigation/VSegmentedControl.swift @@ -1,10 +1,15 @@ import SwiftUI -struct VSegmentedControl: View { - let items: [String] - @Binding var selection: Int +public struct VSegmentedControl: View { + public let items: [String] + @Binding public var selection: Int - var body: some View { + public init(items: [String], selection: Binding) { + self.items = items + self._selection = selection + } + + public var body: some View { HStack(spacing: 0) { ForEach(items.indices, id: \.self) { index in Button(action: { selection = index }) { diff --git a/clients/macos/vellum-assistant/DesignSystem/Components/Navigation/VTabBar.swift b/clients/shared/DesignSystem/Components/Navigation/VTabBar.swift similarity index 73% rename from clients/macos/vellum-assistant/DesignSystem/Components/Navigation/VTabBar.swift rename to clients/shared/DesignSystem/Components/Navigation/VTabBar.swift index d1bcb53a858..9f36770cf42 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Components/Navigation/VTabBar.swift +++ b/clients/shared/DesignSystem/Components/Navigation/VTabBar.swift @@ -1,9 +1,13 @@ import SwiftUI -struct VTabBar: View { - @ViewBuilder let content: () -> Content +public struct VTabBar: View { + @ViewBuilder public let content: () -> Content - var body: some View { + public init(@ViewBuilder content: @escaping () -> Content) { + self.content = content + } + + public var body: some View { ScrollView(.horizontal, showsIndicators: false) { HStack(spacing: VSpacing.xs) { content() diff --git a/clients/macos/vellum-assistant/DesignSystem/Core/Buttons/VButton.swift b/clients/shared/DesignSystem/Core/Buttons/VButton.swift similarity index 78% rename from clients/macos/vellum-assistant/DesignSystem/Core/Buttons/VButton.swift rename to clients/shared/DesignSystem/Core/Buttons/VButton.swift index 51bc3c84c93..430bd02dcee 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Core/Buttons/VButton.swift +++ b/clients/shared/DesignSystem/Core/Buttons/VButton.swift @@ -1,23 +1,44 @@ import SwiftUI +#if os(macOS) +import AppKit +#endif -struct VButton: View { - enum Style: Hashable { case primary, ghost, danger } +public struct VButton: View { + public enum Style: Hashable { case primary, ghost, danger } - let label: String - var style: Style = .primary - var isFullWidth: Bool = false - var isDisabled: Bool = false - let action: () -> Void + public let label: String + public var style: Style = .primary + public var isFullWidth: Bool = false + public var isDisabled: Bool = false + public let action: () -> Void @State private var isHovered = false - var body: some View { + public init(label: String, style: Style = .primary, isFullWidth: Bool = false, isDisabled: Bool = false, action: @escaping () -> Void) { + self.label = label + self.style = style + self.isFullWidth = isFullWidth + self.isDisabled = isDisabled + self.action = action + } + + public var body: some View { Button(action: action) { Text(label) .font(VFont.bodyMedium) } .buttonStyle(VButtonStyle(style: style, isHovered: isHovered, isFullWidth: isFullWidth)) + #if os(macOS) + .onHover { hovering in + isHovered = isDisabled ? false : hovering + if !isDisabled { + if hovering { NSCursor.pointingHand.set() } + else { NSCursor.arrow.set() } + } + } + #else .onHover { isHovered = isDisabled ? false : $0 } + #endif .disabled(isDisabled) .opacity(isDisabled ? 0.5 : 1.0) .accessibilityHint(isDisabled ? "Button is currently disabled" : "") diff --git a/clients/macos/vellum-assistant/DesignSystem/Core/Buttons/VCircleButton.swift b/clients/shared/DesignSystem/Core/Buttons/VCircleButton.swift similarity index 58% rename from clients/macos/vellum-assistant/DesignSystem/Core/Buttons/VCircleButton.swift rename to clients/shared/DesignSystem/Core/Buttons/VCircleButton.swift index 260e2e5341a..ee26bdf18ed 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Core/Buttons/VCircleButton.swift +++ b/clients/shared/DesignSystem/Core/Buttons/VCircleButton.swift @@ -1,17 +1,30 @@ import SwiftUI +#if os(macOS) +import AppKit +#endif -struct VCircleButton: View { - let icon: String // SF Symbol name - let label: String // Human-readable accessibility label - var fillColor: Color = Emerald._600 - var iconColor: Color = .white - var size: CGFloat = 36 - var iconSize: CGFloat = 14 - let action: () -> Void +public struct VCircleButton: View { + public let icon: String // SF Symbol name + public let label: String // Human-readable accessibility label + public var fillColor: Color = Emerald._600 + public var iconColor: Color = .white + public var size: CGFloat = 36 + public var iconSize: CGFloat = 14 + public let action: () -> Void @State private var isHovered = false - var body: some View { + public init(icon: String, label: String, fillColor: Color = Emerald._600, iconColor: Color = .white, size: CGFloat = 36, iconSize: CGFloat = 14, action: @escaping () -> Void) { + self.icon = icon + self.label = label + self.fillColor = fillColor + self.iconColor = iconColor + self.size = size + self.iconSize = iconSize + self.action = action + } + + public var body: some View { Button(action: action) { Circle() .fill(fillColor) @@ -23,14 +36,15 @@ struct VCircleButton: View { ) } .buttonStyle(VCircleButtonStyle(isHovered: isHovered)) + #if os(macOS) .onHover { hovering in isHovered = hovering - if hovering { - NSCursor.pointingHand.set() - } else { - NSCursor.arrow.set() - } + if hovering { NSCursor.pointingHand.set() } + else { NSCursor.arrow.set() } } + #else + .onHover { isHovered = $0 } + #endif .accessibilityLabel(label) } } diff --git a/clients/macos/vellum-assistant/DesignSystem/Core/Buttons/VIconButton.swift b/clients/shared/DesignSystem/Core/Buttons/VIconButton.swift similarity index 75% rename from clients/macos/vellum-assistant/DesignSystem/Core/Buttons/VIconButton.swift rename to clients/shared/DesignSystem/Core/Buttons/VIconButton.swift index 51a3ad6f83f..15fa542e13e 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Core/Buttons/VIconButton.swift +++ b/clients/shared/DesignSystem/Core/Buttons/VIconButton.swift @@ -1,16 +1,28 @@ import SwiftUI +#if os(macOS) +import AppKit +#endif -struct VIconButton: View { - let label: String - var icon: String = "" - var customIcon: Image? = nil - var isActive: Bool = false - var iconOnly: Bool = false - let action: () -> Void +public struct VIconButton: View { + public let label: String + public var icon: String = "" + public var customIcon: Image? = nil + public var isActive: Bool = false + public var iconOnly: Bool = false + public let action: () -> Void @State private var isHovered = false - var body: some View { + public init(label: String, icon: String = "", customIcon: Image? = nil, isActive: Bool = false, iconOnly: Bool = false, action: @escaping () -> Void) { + self.label = label + self.icon = icon + self.customIcon = customIcon + self.isActive = isActive + self.iconOnly = iconOnly + self.action = action + } + + public var body: some View { Button(action: action) { HStack(spacing: VSpacing.xs) { if let customIcon { @@ -27,14 +39,15 @@ struct VIconButton: View { } } .buttonStyle(VIconButtonStyle(isActive: isActive, isHovered: isHovered, iconOnly: iconOnly)) + #if os(macOS) .onHover { hovering in isHovered = hovering - if hovering { - NSCursor.pointingHand.set() - } else { - NSCursor.arrow.set() - } + if hovering { NSCursor.pointingHand.set() } + else { NSCursor.arrow.set() } } + #else + .onHover { isHovered = $0 } + #endif .accessibilityLabel(label) } } diff --git a/clients/macos/vellum-assistant/DesignSystem/Core/Display/VListRow.swift b/clients/shared/DesignSystem/Core/Display/VListRow.swift similarity index 80% rename from clients/macos/vellum-assistant/DesignSystem/Core/Display/VListRow.swift rename to clients/shared/DesignSystem/Core/Display/VListRow.swift index 9f9048fd36c..c271bdb7ba3 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Core/Display/VListRow.swift +++ b/clients/shared/DesignSystem/Core/Display/VListRow.swift @@ -1,12 +1,17 @@ import SwiftUI -struct VListRow: View { - var onTap: (() -> Void)? = nil - @ViewBuilder let content: () -> Content +public struct VListRow: View { + public var onTap: (() -> Void)? = nil + @ViewBuilder public let content: () -> Content @State private var isHovered = false - var body: some View { + public init(onTap: (() -> Void)? = nil, @ViewBuilder content: @escaping () -> Content) { + self.onTap = onTap + self.content = content + } + + public var body: some View { Group { if let onTap = onTap { Button(action: onTap) { diff --git a/clients/macos/vellum-assistant/DesignSystem/Core/Feedback/VBadge.swift b/clients/shared/DesignSystem/Core/Feedback/VBadge.swift similarity index 87% rename from clients/macos/vellum-assistant/DesignSystem/Core/Feedback/VBadge.swift rename to clients/shared/DesignSystem/Core/Feedback/VBadge.swift index 269348a5114..4b01606387a 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Core/Feedback/VBadge.swift +++ b/clients/shared/DesignSystem/Core/Feedback/VBadge.swift @@ -1,16 +1,21 @@ import SwiftUI -struct VBadge: View { - enum Style { +public struct VBadge: View { + public enum Style { case count(Int) case dot case label(String) } - let style: Style - var color: Color = VColor.accent + public let style: Style + public var color: Color = VColor.accent - var body: some View { + public init(style: Style, color: Color = VColor.accent) { + self.style = style + self.color = color + } + + public var body: some View { switch style { case .count(let count): Text("\(count)") diff --git a/clients/macos/vellum-assistant/DesignSystem/Core/Feedback/VLoadingIndicator.swift b/clients/shared/DesignSystem/Core/Feedback/VLoadingIndicator.swift similarity index 77% rename from clients/macos/vellum-assistant/DesignSystem/Core/Feedback/VLoadingIndicator.swift rename to clients/shared/DesignSystem/Core/Feedback/VLoadingIndicator.swift index fe2770c0b80..02e72593860 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Core/Feedback/VLoadingIndicator.swift +++ b/clients/shared/DesignSystem/Core/Feedback/VLoadingIndicator.swift @@ -1,12 +1,17 @@ import SwiftUI -struct VLoadingIndicator: View { - var size: CGFloat = 20 - var color: Color = VColor.accent +public struct VLoadingIndicator: View { + public var size: CGFloat = 20 + public var color: Color = VColor.accent @State private var isAnimating = false - var body: some View { + public init(size: CGFloat = 20, color: Color = VColor.accent) { + self.size = size + self.color = color + } + + public var body: some View { Circle() .trim(from: 0, to: 0.7) .stroke(color, lineWidth: 2) diff --git a/clients/macos/vellum-assistant/DesignSystem/Core/Feedback/VToast.swift b/clients/shared/DesignSystem/Core/Feedback/VToast.swift similarity index 76% rename from clients/macos/vellum-assistant/DesignSystem/Core/Feedback/VToast.swift rename to clients/shared/DesignSystem/Core/Feedback/VToast.swift index 9b1d25d2a66..9febe0fc38a 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Core/Feedback/VToast.swift +++ b/clients/shared/DesignSystem/Core/Feedback/VToast.swift @@ -1,12 +1,22 @@ import SwiftUI +#if os(macOS) import AppKit +#elseif os(iOS) +import UIKit +#endif -struct VToast: View { - enum Style { case info, success, warning, error } +public struct VToast: View { + public enum Style { case info, success, warning, error } - let message: String - var style: Style = .info - var body: some View { + public let message: String + public var style: Style = .info + + public init(message: String, style: Style = .info) { + self.message = message + self.style = style + } + + public var body: some View { HStack(spacing: VSpacing.md) { Image(systemName: iconName) .foregroundColor(iconColor) @@ -26,14 +36,15 @@ struct VToast: View { .accessibilityElement(children: .ignore) .accessibilityLabel(Text("\(String(describing: style)): \(message)")) .onAppear { + #if os(macOS) NSAccessibility.post( element: NSApp as Any, notification: .announcementRequested, - userInfo: [ - .announcement: "\(style): \(message)" as NSString, - .priority: NSAccessibilityPriorityLevel.high.rawValue - ] + userInfo: [.announcement: message as NSString] ) + #elseif os(iOS) + UIAccessibility.post(notification: .announcement, argument: message) + #endif } } diff --git a/clients/macos/vellum-assistant/DesignSystem/Core/Inputs/VSlider.swift b/clients/shared/DesignSystem/Core/Inputs/VSlider.swift similarity index 92% rename from clients/macos/vellum-assistant/DesignSystem/Core/Inputs/VSlider.swift rename to clients/shared/DesignSystem/Core/Inputs/VSlider.swift index ef5fb26ad88..654f90d6e7f 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Core/Inputs/VSlider.swift +++ b/clients/shared/DesignSystem/Core/Inputs/VSlider.swift @@ -1,10 +1,17 @@ import SwiftUI -struct VSlider: View { - @Binding var value: Double - var range: ClosedRange = 0...100 - var step: Double = 1 - var showTickMarks: Bool = false +public struct VSlider: View { + @Binding public var value: Double + public var range: ClosedRange = 0...100 + public var step: Double = 1 + public var showTickMarks: Bool = false + + public init(value: Binding, range: ClosedRange = 0...100, step: Double = 1, showTickMarks: Bool = false) { + self._value = value + self.range = range + self.step = step + self.showTickMarks = showTickMarks + } // MARK: - Layout Constants @@ -22,7 +29,7 @@ struct VSlider: View { // MARK: - Body - var body: some View { + public var body: some View { GeometryReader { geometry in let trackWidth = geometry.size.width - thumbWidth let fraction = (value - range.lowerBound) / (range.upperBound - range.lowerBound) diff --git a/clients/macos/vellum-assistant/DesignSystem/Core/Inputs/VTextEditor.swift b/clients/shared/DesignSystem/Core/Inputs/VTextEditor.swift similarity index 79% rename from clients/macos/vellum-assistant/DesignSystem/Core/Inputs/VTextEditor.swift rename to clients/shared/DesignSystem/Core/Inputs/VTextEditor.swift index 58feae10ce6..7907736360c 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Core/Inputs/VTextEditor.swift +++ b/clients/shared/DesignSystem/Core/Inputs/VTextEditor.swift @@ -1,14 +1,21 @@ import SwiftUI -struct VTextEditor: View { - let placeholder: String - @Binding var text: String - var minHeight: CGFloat = 80 - var maxHeight: CGFloat = 200 +public struct VTextEditor: View { + public let placeholder: String + @Binding public var text: String + public var minHeight: CGFloat = 80 + public var maxHeight: CGFloat = 200 @FocusState private var isFocused: Bool - var body: some View { + public init(placeholder: String, text: Binding, minHeight: CGFloat = 80, maxHeight: CGFloat = 200) { + self.placeholder = placeholder + self._text = text + self.minHeight = minHeight + self.maxHeight = maxHeight + } + + public var body: some View { ZStack(alignment: .topLeading) { if text.isEmpty { Text(placeholder) diff --git a/clients/macos/vellum-assistant/DesignSystem/Core/Inputs/VTextField.swift b/clients/shared/DesignSystem/Core/Inputs/VTextField.swift similarity index 78% rename from clients/macos/vellum-assistant/DesignSystem/Core/Inputs/VTextField.swift rename to clients/shared/DesignSystem/Core/Inputs/VTextField.swift index 982daa8f8d2..1254b3d9c2c 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Core/Inputs/VTextField.swift +++ b/clients/shared/DesignSystem/Core/Inputs/VTextField.swift @@ -1,15 +1,23 @@ import SwiftUI -struct VTextField: View { - let placeholder: String - @Binding var text: String - var leadingIcon: String? = nil - var trailingIcon: String? = nil - var onSubmit: (() -> Void)? = nil +public struct VTextField: View { + public let placeholder: String + @Binding public var text: String + public var leadingIcon: String? = nil + public var trailingIcon: String? = nil + public var onSubmit: (() -> Void)? = nil @FocusState private var isFocused: Bool - var body: some View { + public init(placeholder: String, text: Binding, leadingIcon: String? = nil, trailingIcon: String? = nil, onSubmit: (() -> Void)? = nil) { + self.placeholder = placeholder + self._text = text + self.leadingIcon = leadingIcon + self.trailingIcon = trailingIcon + self.onSubmit = onSubmit + } + + public var body: some View { HStack(spacing: VSpacing.md) { if let leadingIcon = leadingIcon { Image(systemName: leadingIcon) diff --git a/clients/macos/vellum-assistant/DesignSystem/Core/Inputs/VToggle.swift b/clients/shared/DesignSystem/Core/Inputs/VToggle.swift similarity index 89% rename from clients/macos/vellum-assistant/DesignSystem/Core/Inputs/VToggle.swift rename to clients/shared/DesignSystem/Core/Inputs/VToggle.swift index 116e59bd76c..d43647b4dfd 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Core/Inputs/VToggle.swift +++ b/clients/shared/DesignSystem/Core/Inputs/VToggle.swift @@ -1,8 +1,13 @@ import SwiftUI -struct VToggle: View { - @Binding var isOn: Bool - var label: String? = nil +public struct VToggle: View { + @Binding public var isOn: Bool + public var label: String? = nil + + public init(isOn: Binding, label: String? = nil) { + self._isOn = isOn + self.label = label + } // MARK: - Layout Constants @@ -11,7 +16,7 @@ struct VToggle: View { private let knobSize: CGFloat = 16 private let knobPadding: CGFloat = 3 - var body: some View { + public var body: some View { HStack(spacing: VSpacing.sm) { toggleTrack diff --git a/clients/macos/vellum-assistant/DesignSystem/Core/Navigation/VTab.swift b/clients/shared/DesignSystem/Core/Navigation/VTab.swift similarity index 78% rename from clients/macos/vellum-assistant/DesignSystem/Core/Navigation/VTab.swift rename to clients/shared/DesignSystem/Core/Navigation/VTab.swift index 1218347493a..94ad4dbc42e 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Core/Navigation/VTab.swift +++ b/clients/shared/DesignSystem/Core/Navigation/VTab.swift @@ -1,22 +1,32 @@ import SwiftUI -enum VTabStyle { +public enum VTabStyle { case pill // Shows background fill on selected/hover, fully rounded case flat // No background fill, only text color changes case rectangular // Same as pill but with VRadius.md corners (matches VButton) } -struct VTab: View { - let label: String - var icon: String? = nil // SF Symbol - var isSelected: Bool = false - var isCloseable: Bool = true - var style: VTabStyle = .pill - var onSelect: () -> Void - var onClose: (() -> Void)? = nil +public struct VTab: View { + public let label: String + public var icon: String? = nil // SF Symbol + public var isSelected: Bool = false + public var isCloseable: Bool = true + public var style: VTabStyle = .pill + public var onSelect: () -> Void + public var onClose: (() -> Void)? = nil @State private var isHovered = false + public init(label: String, icon: String? = nil, isSelected: Bool = false, isCloseable: Bool = true, style: VTabStyle = .pill, onSelect: @escaping () -> Void, onClose: (() -> Void)? = nil) { + self.label = label + self.icon = icon + self.isSelected = isSelected + self.isCloseable = isCloseable + self.style = style + self.onSelect = onSelect + self.onClose = onClose + } + private var background: Color { switch style { case .pill, .rectangular: @@ -33,7 +43,7 @@ struct VTab: View { } } - var body: some View { + public var body: some View { Button(action: onSelect) { HStack(spacing: VSpacing.xs) { if let icon = icon { diff --git a/clients/macos/vellum-assistant/DesignSystem/Gallery/ComponentGalleryView.swift b/clients/shared/DesignSystem/Gallery/ComponentGalleryView.swift similarity index 99% rename from clients/macos/vellum-assistant/DesignSystem/Gallery/ComponentGalleryView.swift rename to clients/shared/DesignSystem/Gallery/ComponentGalleryView.swift index a17ac129531..86c933f0cbc 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Gallery/ComponentGalleryView.swift +++ b/clients/shared/DesignSystem/Gallery/ComponentGalleryView.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared #if DEBUG import SwiftUI diff --git a/clients/macos/vellum-assistant/DesignSystem/Gallery/ComponentGalleryWindow.swift b/clients/shared/DesignSystem/Gallery/ComponentGalleryWindow.swift similarity index 91% rename from clients/macos/vellum-assistant/DesignSystem/Gallery/ComponentGalleryWindow.swift rename to clients/shared/DesignSystem/Gallery/ComponentGalleryWindow.swift index cb9777e5395..558db7920b3 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Gallery/ComponentGalleryWindow.swift +++ b/clients/shared/DesignSystem/Gallery/ComponentGalleryWindow.swift @@ -1,12 +1,15 @@ +import VellumAssistantShared #if DEBUG import AppKit import SwiftUI @MainActor -final class ComponentGalleryWindow { +public final class ComponentGalleryWindow { private var window: NSWindow? - func show() { + public init() {} + + public func show() { if let existing = window { existing.makeKeyAndOrderFront(nil) NSApp.activate(ignoringOtherApps: true) diff --git a/clients/macos/vellum-assistant/DesignSystem/Gallery/Sections/ButtonsGallerySection.swift b/clients/shared/DesignSystem/Gallery/Sections/ButtonsGallerySection.swift similarity index 99% rename from clients/macos/vellum-assistant/DesignSystem/Gallery/Sections/ButtonsGallerySection.swift rename to clients/shared/DesignSystem/Gallery/Sections/ButtonsGallerySection.swift index 4ab54351d9e..5b084506772 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Gallery/Sections/ButtonsGallerySection.swift +++ b/clients/shared/DesignSystem/Gallery/Sections/ButtonsGallerySection.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared #if DEBUG import SwiftUI diff --git a/clients/macos/vellum-assistant/DesignSystem/Gallery/Sections/DisplayGallerySection.swift b/clients/shared/DesignSystem/Gallery/Sections/DisplayGallerySection.swift similarity index 99% rename from clients/macos/vellum-assistant/DesignSystem/Gallery/Sections/DisplayGallerySection.swift rename to clients/shared/DesignSystem/Gallery/Sections/DisplayGallerySection.swift index e594a2b30c2..5a44271e023 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Gallery/Sections/DisplayGallerySection.swift +++ b/clients/shared/DesignSystem/Gallery/Sections/DisplayGallerySection.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared #if DEBUG import SwiftUI diff --git a/clients/macos/vellum-assistant/DesignSystem/Gallery/Sections/FeedbackGallerySection.swift b/clients/shared/DesignSystem/Gallery/Sections/FeedbackGallerySection.swift similarity index 99% rename from clients/macos/vellum-assistant/DesignSystem/Gallery/Sections/FeedbackGallerySection.swift rename to clients/shared/DesignSystem/Gallery/Sections/FeedbackGallerySection.swift index d904dc9ccd6..f688383d9ab 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Gallery/Sections/FeedbackGallerySection.swift +++ b/clients/shared/DesignSystem/Gallery/Sections/FeedbackGallerySection.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared #if DEBUG import SwiftUI diff --git a/clients/macos/vellum-assistant/DesignSystem/Gallery/Sections/InputsGallerySection.swift b/clients/shared/DesignSystem/Gallery/Sections/InputsGallerySection.swift similarity index 99% rename from clients/macos/vellum-assistant/DesignSystem/Gallery/Sections/InputsGallerySection.swift rename to clients/shared/DesignSystem/Gallery/Sections/InputsGallerySection.swift index 3e88715efda..46da03af022 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Gallery/Sections/InputsGallerySection.swift +++ b/clients/shared/DesignSystem/Gallery/Sections/InputsGallerySection.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared #if DEBUG import SwiftUI diff --git a/clients/macos/vellum-assistant/DesignSystem/Gallery/Sections/LayoutGallerySection.swift b/clients/shared/DesignSystem/Gallery/Sections/LayoutGallerySection.swift similarity index 99% rename from clients/macos/vellum-assistant/DesignSystem/Gallery/Sections/LayoutGallerySection.swift rename to clients/shared/DesignSystem/Gallery/Sections/LayoutGallerySection.swift index c602fcd29fd..9f86223dfea 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Gallery/Sections/LayoutGallerySection.swift +++ b/clients/shared/DesignSystem/Gallery/Sections/LayoutGallerySection.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared #if DEBUG import SwiftUI diff --git a/clients/macos/vellum-assistant/DesignSystem/Gallery/Sections/ModifiersGallerySection.swift b/clients/shared/DesignSystem/Gallery/Sections/ModifiersGallerySection.swift similarity index 99% rename from clients/macos/vellum-assistant/DesignSystem/Gallery/Sections/ModifiersGallerySection.swift rename to clients/shared/DesignSystem/Gallery/Sections/ModifiersGallerySection.swift index d7c32eaaa34..a6ffe0c3b4f 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Gallery/Sections/ModifiersGallerySection.swift +++ b/clients/shared/DesignSystem/Gallery/Sections/ModifiersGallerySection.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared #if DEBUG import SwiftUI diff --git a/clients/macos/vellum-assistant/DesignSystem/Gallery/Sections/NavigationGallerySection.swift b/clients/shared/DesignSystem/Gallery/Sections/NavigationGallerySection.swift similarity index 99% rename from clients/macos/vellum-assistant/DesignSystem/Gallery/Sections/NavigationGallerySection.swift rename to clients/shared/DesignSystem/Gallery/Sections/NavigationGallerySection.swift index 7ec1b0cc9c3..12fe269b421 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Gallery/Sections/NavigationGallerySection.swift +++ b/clients/shared/DesignSystem/Gallery/Sections/NavigationGallerySection.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared #if DEBUG import SwiftUI diff --git a/clients/macos/vellum-assistant/DesignSystem/Gallery/Sections/TokensGallerySection.swift b/clients/shared/DesignSystem/Gallery/Sections/TokensGallerySection.swift similarity index 99% rename from clients/macos/vellum-assistant/DesignSystem/Gallery/Sections/TokensGallerySection.swift rename to clients/shared/DesignSystem/Gallery/Sections/TokensGallerySection.swift index cb7a45d8faa..b518fe0057b 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Gallery/Sections/TokensGallerySection.swift +++ b/clients/shared/DesignSystem/Gallery/Sections/TokensGallerySection.swift @@ -1,3 +1,4 @@ +import VellumAssistantShared #if DEBUG import SwiftUI diff --git a/clients/macos/vellum-assistant/DesignSystem/Modifiers/CardModifier.swift b/clients/shared/DesignSystem/Modifiers/CardModifier.swift similarity index 70% rename from clients/macos/vellum-assistant/DesignSystem/Modifiers/CardModifier.swift rename to clients/shared/DesignSystem/Modifiers/CardModifier.swift index 476c19c2728..d029102f2ed 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Modifiers/CardModifier.swift +++ b/clients/shared/DesignSystem/Modifiers/CardModifier.swift @@ -1,10 +1,15 @@ import SwiftUI -struct CardModifier: ViewModifier { - var radius: CGFloat = VRadius.md - var background: Color = VColor.surface +public struct CardModifier: ViewModifier { + public var radius: CGFloat = VRadius.md + public var background: Color = VColor.surface - func body(content: Content) -> some View { + public init(radius: CGFloat = VRadius.md, background: Color = VColor.surface) { + self.radius = radius + self.background = background + } + + public func body(content: Content) -> some View { content .background(background) .clipShape(RoundedRectangle(cornerRadius: radius)) @@ -15,7 +20,7 @@ struct CardModifier: ViewModifier { } } -extension View { +public extension View { func vCard(radius: CGFloat = VRadius.md, background: Color = VColor.surface) -> some View { modifier(CardModifier(radius: radius, background: background)) } diff --git a/clients/macos/vellum-assistant/DesignSystem/Modifiers/HoverEffect.swift b/clients/shared/DesignSystem/Modifiers/HoverEffect.swift similarity index 87% rename from clients/macos/vellum-assistant/DesignSystem/Modifiers/HoverEffect.swift rename to clients/shared/DesignSystem/Modifiers/HoverEffect.swift index 13d8b8ef924..2ca4a8c69f1 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Modifiers/HoverEffect.swift +++ b/clients/shared/DesignSystem/Modifiers/HoverEffect.swift @@ -1,9 +1,9 @@ import SwiftUI -struct HoverEffectModifier: ViewModifier { +public struct HoverEffectModifier: ViewModifier { @State private var isHovered = false - func body(content: Content) -> some View { + public func body(content: Content) -> some View { content .background(isHovered ? VColor.surfaceBorder.opacity(0.5) : .clear) .onHover { hovering in @@ -12,7 +12,7 @@ struct HoverEffectModifier: ViewModifier { } } -extension View { +public extension View { func vHover() -> some View { modifier(HoverEffectModifier()) } diff --git a/clients/macos/vellum-assistant/DesignSystem/Modifiers/PanelBackground.swift b/clients/shared/DesignSystem/Modifiers/PanelBackground.swift similarity index 84% rename from clients/macos/vellum-assistant/DesignSystem/Modifiers/PanelBackground.swift rename to clients/shared/DesignSystem/Modifiers/PanelBackground.swift index b2e331c1eef..cb7f28e6528 100644 --- a/clients/macos/vellum-assistant/DesignSystem/Modifiers/PanelBackground.swift +++ b/clients/shared/DesignSystem/Modifiers/PanelBackground.swift @@ -1,14 +1,14 @@ import SwiftUI -struct PanelBackgroundModifier: ViewModifier { - func body(content: Content) -> some View { +public struct PanelBackgroundModifier: ViewModifier { + public func body(content: Content) -> some View { content .frame(maxWidth: .infinity, maxHeight: .infinity) .background(VColor.backgroundSubtle) } } -extension View { +public extension View { func vPanelBackground() -> some View { modifier(PanelBackgroundModifier()) } diff --git a/clients/shared/DesignSystem/Tokens/AnimationTokens.swift b/clients/shared/DesignSystem/Tokens/AnimationTokens.swift new file mode 100644 index 00000000000..e2e1a1e0496 --- /dev/null +++ b/clients/shared/DesignSystem/Tokens/AnimationTokens.swift @@ -0,0 +1,21 @@ +import SwiftUI + +/// Animation presets. Use instead of raw Animation values. +public enum VAnimation { + public static let fast = Animation.easeOut(duration: 0.15) + public static let standard = Animation.easeInOut(duration: 0.25) + public static let slow = Animation.easeInOut(duration: 0.4) + public static let spring = Animation.spring(response: 0.3, dampingFraction: 0.8) + + /// Gentle spring for panel open/close + public static let panel = Animation.spring(response: 0.35, dampingFraction: 0.85) + + /// Bouncy spring for celebratory/attention-grabbing motion + public static let bouncy = Animation.spring(response: 0.3, dampingFraction: 0.5) + + // MARK: - Durations (for use with withAnimation or explicit timing) + + public static let durationFast: TimeInterval = 0.15 + public static let durationStandard: TimeInterval = 0.25 + public static let durationSlow: TimeInterval = 0.4 +} diff --git a/clients/shared/DesignSystem/Tokens/ColorTokens.swift b/clients/shared/DesignSystem/Tokens/ColorTokens.swift new file mode 100644 index 00000000000..d6e2af7b4f9 --- /dev/null +++ b/clients/shared/DesignSystem/Tokens/ColorTokens.swift @@ -0,0 +1,126 @@ +import SwiftUI + +// MARK: - Color Extension + +public extension Color { + init(hex: UInt, alpha: Double = 1.0) { + self.init( + .sRGB, + red: Double((hex >> 16) & 0xFF) / 255, + green: Double((hex >> 8) & 0xFF) / 255, + blue: Double(hex & 0xFF) / 255, + opacity: alpha + ) + } +} + +// MARK: - Color Scales + +public enum Slate { + public static let _950 = Color(hex: 0x070D19) + public static let _900 = Color(hex: 0x0F172A) + public static let _800 = Color(hex: 0x1E293B) + public static let _700 = Color(hex: 0x334155) + public static let _600 = Color(hex: 0x475569) + public static let _500 = Color(hex: 0x64748B) + public static let _400 = Color(hex: 0x94A3B8) + public static let _300 = Color(hex: 0xCBD5E1) + public static let _200 = Color(hex: 0xE2E8F0) + public static let _100 = Color(hex: 0xF1F5F9) + public static let _50 = Color(hex: 0xF8FAFC) +} + +public enum Emerald { + public static let _950 = Color(hex: 0x073D2E) + public static let _900 = Color(hex: 0x0A5843) + public static let _800 = Color(hex: 0x0C7356) + public static let _700 = Color(hex: 0x10906A) + public static let _600 = Color(hex: 0x18B07A) + public static let _500 = Color(hex: 0x38CF93) + public static let _400 = Color(hex: 0x6EE7B5) + public static let _300 = Color(hex: 0xA6F2D1) + public static let _200 = Color(hex: 0xD2F9E8) + public static let _100 = Color(hex: 0xECFDF5) +} + +public enum Violet { + public static let _950 = Color(hex: 0x321669) + public static let _900 = Color(hex: 0x4A2390) + public static let _800 = Color(hex: 0x5C2FB2) + public static let _700 = Color(hex: 0x7240CC) + public static let _600 = Color(hex: 0x8A5BE0) + public static let _500 = Color(hex: 0x9878EA) + public static let _400 = Color(hex: 0xB8A6F1) + public static let _300 = Color(hex: 0xD4C8F7) + public static let _200 = Color(hex: 0xE8E1FB) + public static let _100 = Color(hex: 0xF4F0FD) +} + +public enum Indigo { + public static let _950 = Color(hex: 0x180F66) + public static let _900 = Color(hex: 0x261A96) + public static let _800 = Color(hex: 0x3525C4) + public static let _700 = Color(hex: 0x4636E8) + public static let _600 = Color(hex: 0x5B4EFF) + public static let _500 = Color(hex: 0x7B6BFF) + public static let _400 = Color(hex: 0x9488FF) + public static let _300 = Color(hex: 0xB8B4FF) + public static let _200 = Color(hex: 0xD8D8FF) + public static let _100 = Color(hex: 0xEEEEFF) +} + +public enum Rose { + public static let _950 = Color(hex: 0x620F21) + public static let _900 = Color(hex: 0x85142F) + public static let _800 = Color(hex: 0xA8183E) + public static let _700 = Color(hex: 0xD02050) + public static let _600 = Color(hex: 0xE84060) + public static let _500 = Color(hex: 0xF06A86) + public static let _400 = Color(hex: 0xF99AAE) + public static let _300 = Color(hex: 0xFCBFC9) + public static let _200 = Color(hex: 0xFFE1E6) + public static let _100 = Color(hex: 0xFFF1F3) +} + +public enum Amber { + public static let _950 = Color(hex: 0x5E3207) + public static let _900 = Color(hex: 0x7A4409) + public static let _800 = Color(hex: 0xA35E0C) + public static let _700 = Color(hex: 0xC97C10) + public static let _600 = Color(hex: 0xE8A020) + public static let _500 = Color(hex: 0xFAC426) + public static let _400 = Color(hex: 0xFDD94E) + public static let _300 = Color(hex: 0xFEEC94) + public static let _200 = Color(hex: 0xFEF7CD) + public static let _100 = Color(hex: 0xFEFCE8) +} + +// MARK: - Semantic Color Tokens + +public enum VColor { + // Backgrounds + public static let background = Slate._950 + public static let backgroundSubtle = Slate._800 + public static let chatBackground = Slate._900 + public static let surface = Slate._800 + public static let surfaceBorder = Slate._700 + + // Text + public static let textPrimary = Slate._50 + public static let textSecondary = Slate._400 + public static let textMuted = Slate._500 + + // Accent (violet = primary) + public static let accent = Violet._600 + public static let accentSubtle = Violet._100 + + // Onboarding accent (amber) + public static let onboardingAccent = Amber._500 + public static let onboardingAccentDark = Amber._600 + public static let onboardingAccentDarker = Amber._800 + + // Status + public static let success = Emerald._600 + public static let error = Rose._600 + public static let warning = Amber._600 +} diff --git a/clients/shared/DesignSystem/Tokens/MeadowTokens.swift b/clients/shared/DesignSystem/Tokens/MeadowTokens.swift new file mode 100644 index 00000000000..573ae47c8ca --- /dev/null +++ b/clients/shared/DesignSystem/Tokens/MeadowTokens.swift @@ -0,0 +1,28 @@ +import SwiftUI + +/// Onboarding-specific design tokens for the Pixel Meadow theme. +public enum Meadow { + // Panel + public static let panelBackground = Slate._900.opacity(0.75) + public static let panelBorder = Slate._700.opacity(0.4) + + // Egg glow + public static let eggGlow = Amber._500 + public static let eggGlowIntense = Amber._400 + public static let crackLight = Amber._200 + + // Bottom caption + public static let captionText = Color.white.opacity(0.5) + + // Pixel scaling factor + public static let pixelScale: CGFloat = 2.0 + + // Art pixel size — each pixel-art cell renders as this many points + public static let artPixelSize: CGFloat = 5.0 + + // Interview palette + public static let avatarGradientStart = Violet._600 + public static let avatarGradientEnd = Violet._400 + public static let userBubbleGradientStart = Violet._600 + public static let userBubbleGradientEnd = Violet._400 +} diff --git a/clients/shared/DesignSystem/Tokens/RadiusTokens.swift b/clients/shared/DesignSystem/Tokens/RadiusTokens.swift new file mode 100644 index 00000000000..2a547f701cb --- /dev/null +++ b/clients/shared/DesignSystem/Tokens/RadiusTokens.swift @@ -0,0 +1,13 @@ +import Foundation + +/// Corner radius scale. Use `VRadius.pill` for capsule shapes. +public enum VRadius { + public static let xs: CGFloat = 2 + public static let sm: CGFloat = 4 + public static let md: CGFloat = 8 + public static let lg: CGFloat = 12 + public static let xl: CGFloat = 16 + + /// Use for fully rounded pill/capsule shapes + public static let pill: CGFloat = 999 +} diff --git a/clients/shared/DesignSystem/Tokens/ShadowTokens.swift b/clients/shared/DesignSystem/Tokens/ShadowTokens.swift new file mode 100644 index 00000000000..2c4e44a82d2 --- /dev/null +++ b/clients/shared/DesignSystem/Tokens/ShadowTokens.swift @@ -0,0 +1,34 @@ +import SwiftUI + +/// Shadow presets. Apply via `.vShadow(.md)` or `.shadow(color:radius:y:)`. +public enum VShadow { + public struct Definition { + public let color: Color + public let radius: CGFloat + public let x: CGFloat + public let y: CGFloat + + public init(color: Color, radius: CGFloat, x: CGFloat, y: CGFloat) { + self.color = color + self.radius = radius + self.x = x + self.y = y + } + } + + public static let sm = Definition(color: .black.opacity(0.2), radius: 4, x: 0, y: 2) + public static let md = Definition(color: .black.opacity(0.3), radius: 8, x: 0, y: 4) + public static let lg = Definition(color: .black.opacity(0.4), radius: 16, x: 0, y: 8) + + /// Amber glow effect for brand elements (orb, highlights) + public static let glow = Definition(color: Amber._500.opacity(0.3), radius: 12, x: 0, y: 0) + + /// Violet glow for accent elements (focused inputs, active buttons) + public static let accentGlow = Definition(color: Violet._600.opacity(0.3), radius: 8, x: 0, y: 0) +} + +public extension View { + func vShadow(_ definition: VShadow.Definition) -> some View { + shadow(color: definition.color, radius: definition.radius, x: definition.x, y: definition.y) + } +} diff --git a/clients/shared/DesignSystem/Tokens/SpacingTokens.swift b/clients/shared/DesignSystem/Tokens/SpacingTokens.swift new file mode 100644 index 00000000000..c633a1b00c8 --- /dev/null +++ b/clients/shared/DesignSystem/Tokens/SpacingTokens.swift @@ -0,0 +1,27 @@ +import Foundation + +/// Spacing scale based on 4pt grid. +/// Usage: `.padding(VSpacing.lg)` or `.padding(.horizontal, VSpacing.xl)` +public enum VSpacing { + public static let xxs: CGFloat = 2 + public static let xs: CGFloat = 4 + public static let sm: CGFloat = 8 + public static let md: CGFloat = 12 + public static let lg: CGFloat = 16 + public static let xl: CGFloat = 24 + public static let xxl: CGFloat = 32 + public static let xxxl: CGFloat = 48 + + // MARK: - Semantic Aliases + + /// Standard gap between inline elements (icons + text, etc.) + public static let inline: CGFloat = sm + /// Standard content padding inside cards and panels + public static let content: CGFloat = lg + /// Standard section gap between major UI blocks + public static let section: CGFloat = xl + /// Standard window/page-level margin + public static let page: CGFloat = xxl + /// Compact vertical padding for buttons + public static let buttonV: CGFloat = 5.5 +} diff --git a/clients/shared/DesignSystem/Tokens/TypographyTokens.swift b/clients/shared/DesignSystem/Tokens/TypographyTokens.swift new file mode 100644 index 00000000000..a55d36d068f --- /dev/null +++ b/clients/shared/DesignSystem/Tokens/TypographyTokens.swift @@ -0,0 +1,67 @@ +import SwiftUI +#if os(macOS) +import AppKit +#elseif os(iOS) +import UIKit +#endif + +/// Font presets for the app. Always use these instead of raw Font.system() calls. +/// +/// **Silkscreen** — pixelated bitmap font for headings and display text. +/// **DM Mono** — monospaced font for body/UI text. +public enum VFont { + + /// DM Mono's default "f" has an exaggerated italic-style hook. + /// Stylistic Set 5 (ss05) provides a conventional "f" glyph. + private static func dmMono(_ name: String, size: CGFloat) -> Font { + #if os(macOS) + guard let nsFont = NSFont(name: name, size: size) else { + return Font.custom(name, size: size) + } + let descriptor = nsFont.fontDescriptor.addingAttributes([ + .featureSettings: [[ + NSFontDescriptor.FeatureKey.typeIdentifier: kStylisticAlternativesType, + NSFontDescriptor.FeatureKey.selectorIdentifier: kStylisticAltFiveOnSelector, + ]] + ]) + return Font(NSFont(descriptor: descriptor, size: size) ?? nsFont) + #elseif os(iOS) + // iOS: Use custom font without stylistic alternates (not as widely supported) + return Font.custom(name, size: size) + #endif + } + // MARK: - Onboarding (Silkscreen pixel font) + + public static let onboardingTitle = Font.custom("Silkscreen-Regular", size: 28) + public static let onboardingSubtitle = Font.custom("Silkscreen-Regular", size: 15) + + // MARK: - Headings (Silkscreen) + // TODO: Clean up typography once we solidify the design system - we dont seem to use Bold + public static let largeTitle = Font.custom("Silkscreen-Bold", size: 26) + public static let title = Font.custom("Silkscreen-Bold", size: 22) + public static let headline = Font.custom("Silkscreen-Bold", size: 13) + + // MARK: - Body / UI (DM Mono) + + public static let body = dmMono("DMMono-Regular", size: 13) + public static let bodyMedium = dmMono("DMMono-Medium", size: 13) + public static let bodyBold = dmMono("DMMono-Medium", size: 13) + public static let caption = dmMono("DMMono-Regular", size: 11) + public static let captionMedium = dmMono("DMMono-Medium", size: 11) + public static let small = dmMono("DMMono-Regular", size: 10) + + // MARK: - Specialized + + public static let cardTitle = dmMono("DMMono-Medium", size: 17) + public static let cardEmoji = Font.system(size: 32) + public static let mono = dmMono("DMMono-Regular", size: 13) + public static let monoSmall = dmMono("DMMono-Regular", size: 11) + + /// All-caps pixel display font (used for panel headers like "AGENT", "GENERATED CONTENT") + public static let display = Font.custom("Silkscreen-Bold", size: 18) + public static let panelTitle = Font.custom("Silkscreen-Regular", size: 24) + public static let sectionTitle = Font.custom("Silkscreen-Regular", size: 18) + + /// Small Silkscreen label (used for thread tab names) + public static let tabLabel = Font.custom("Silkscreen-Regular", size: 11) +} From 9b9c8fc64debac7312946b536160305b5f2d47a5 Mon Sep 17 00:00:00 2001 From: Ashlee Radka Date: Sat, 14 Feb 2026 04:15:57 -0500 Subject: [PATCH 2/7] Address review feedback: Fix iOS compilation and accessibility - ComponentGalleryWindow: Add os(macOS) guard to #if DEBUG to prevent iOS compilation failure - VToast: Restore style prefix and priority in NSAccessibility announcement for VoiceOver users Fixes identified by Devin and Codex review bots. Co-Authored-By: Claude Sonnet 4.5 --- clients/shared/DesignSystem/Core/Feedback/VToast.swift | 5 ++++- .../shared/DesignSystem/Gallery/ComponentGalleryWindow.swift | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/clients/shared/DesignSystem/Core/Feedback/VToast.swift b/clients/shared/DesignSystem/Core/Feedback/VToast.swift index 9febe0fc38a..1be964b9b4f 100644 --- a/clients/shared/DesignSystem/Core/Feedback/VToast.swift +++ b/clients/shared/DesignSystem/Core/Feedback/VToast.swift @@ -40,7 +40,10 @@ public struct VToast: View { NSAccessibility.post( element: NSApp as Any, notification: .announcementRequested, - userInfo: [.announcement: message as NSString] + userInfo: [ + .announcement: "\(style): \(message)" as NSString, + .priority: NSAccessibilityPriorityLevel.high.rawValue + ] ) #elseif os(iOS) UIAccessibility.post(notification: .announcement, argument: message) diff --git a/clients/shared/DesignSystem/Gallery/ComponentGalleryWindow.swift b/clients/shared/DesignSystem/Gallery/ComponentGalleryWindow.swift index 558db7920b3..4f03cf77e5b 100644 --- a/clients/shared/DesignSystem/Gallery/ComponentGalleryWindow.swift +++ b/clients/shared/DesignSystem/Gallery/ComponentGalleryWindow.swift @@ -1,5 +1,5 @@ import VellumAssistantShared -#if DEBUG +#if DEBUG && os(macOS) import AppKit import SwiftUI From 54c4a92d5ed0b78e2a5640be61d5adf3d550db1f Mon Sep 17 00:00:00 2001 From: Ashlee Radka Date: Sat, 14 Feb 2026 04:21:24 -0500 Subject: [PATCH 3/7] Add style prefix to iOS VoiceOver announcement in VToast iOS VoiceOver users now hear severity context (e.g., "error: Something went wrong") matching the macOS experience. Previously iOS only announced the bare message without the style prefix. Addresses Devin review feedback. Co-Authored-By: Claude Sonnet 4.5 --- clients/shared/DesignSystem/Core/Feedback/VToast.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/shared/DesignSystem/Core/Feedback/VToast.swift b/clients/shared/DesignSystem/Core/Feedback/VToast.swift index 1be964b9b4f..500545bd619 100644 --- a/clients/shared/DesignSystem/Core/Feedback/VToast.swift +++ b/clients/shared/DesignSystem/Core/Feedback/VToast.swift @@ -46,7 +46,7 @@ public struct VToast: View { ] ) #elseif os(iOS) - UIAccessibility.post(notification: .announcement, argument: message) + UIAccessibility.post(notification: .announcement, argument: "\(style): \(message)") #endif } } From fec7e379eae99122868c947246df9252ea107c5e Mon Sep 17 00:00:00 2001 From: Ashlee Radka Date: Sat, 14 Feb 2026 04:24:31 -0500 Subject: [PATCH 4/7] Polish: Remove self-imports, add iOS font parity, add public inits - Remove redundant `import VellumAssistantShared` from gallery files (cosmetic) - Add UIFontDescriptor implementation for Stylistic Set 5 on iOS for visual parity with macOS - Add explicit public init() to HoverEffectModifier and PanelBackgroundModifier for cross-module instantiation Addresses user review feedback. Co-Authored-By: Claude Sonnet 4.5 --- .../DesignSystem/Gallery/ComponentGalleryView.swift | 1 - .../Gallery/ComponentGalleryWindow.swift | 1 - .../Gallery/Sections/ButtonsGallerySection.swift | 1 - .../Gallery/Sections/DisplayGallerySection.swift | 1 - .../Gallery/Sections/FeedbackGallerySection.swift | 1 - .../Gallery/Sections/InputsGallerySection.swift | 1 - .../Gallery/Sections/LayoutGallerySection.swift | 1 - .../Gallery/Sections/ModifiersGallerySection.swift | 1 - .../Gallery/Sections/NavigationGallerySection.swift | 1 - .../Gallery/Sections/TokensGallerySection.swift | 1 - .../shared/DesignSystem/Modifiers/HoverEffect.swift | 2 ++ .../DesignSystem/Modifiers/PanelBackground.swift | 2 ++ .../DesignSystem/Tokens/TypographyTokens.swift | 12 ++++++++++-- 13 files changed, 14 insertions(+), 12 deletions(-) diff --git a/clients/shared/DesignSystem/Gallery/ComponentGalleryView.swift b/clients/shared/DesignSystem/Gallery/ComponentGalleryView.swift index 86c933f0cbc..a17ac129531 100644 --- a/clients/shared/DesignSystem/Gallery/ComponentGalleryView.swift +++ b/clients/shared/DesignSystem/Gallery/ComponentGalleryView.swift @@ -1,4 +1,3 @@ -import VellumAssistantShared #if DEBUG import SwiftUI diff --git a/clients/shared/DesignSystem/Gallery/ComponentGalleryWindow.swift b/clients/shared/DesignSystem/Gallery/ComponentGalleryWindow.swift index 4f03cf77e5b..b01d2b5ba80 100644 --- a/clients/shared/DesignSystem/Gallery/ComponentGalleryWindow.swift +++ b/clients/shared/DesignSystem/Gallery/ComponentGalleryWindow.swift @@ -1,4 +1,3 @@ -import VellumAssistantShared #if DEBUG && os(macOS) import AppKit import SwiftUI diff --git a/clients/shared/DesignSystem/Gallery/Sections/ButtonsGallerySection.swift b/clients/shared/DesignSystem/Gallery/Sections/ButtonsGallerySection.swift index 5b084506772..4ab54351d9e 100644 --- a/clients/shared/DesignSystem/Gallery/Sections/ButtonsGallerySection.swift +++ b/clients/shared/DesignSystem/Gallery/Sections/ButtonsGallerySection.swift @@ -1,4 +1,3 @@ -import VellumAssistantShared #if DEBUG import SwiftUI diff --git a/clients/shared/DesignSystem/Gallery/Sections/DisplayGallerySection.swift b/clients/shared/DesignSystem/Gallery/Sections/DisplayGallerySection.swift index 5a44271e023..e594a2b30c2 100644 --- a/clients/shared/DesignSystem/Gallery/Sections/DisplayGallerySection.swift +++ b/clients/shared/DesignSystem/Gallery/Sections/DisplayGallerySection.swift @@ -1,4 +1,3 @@ -import VellumAssistantShared #if DEBUG import SwiftUI diff --git a/clients/shared/DesignSystem/Gallery/Sections/FeedbackGallerySection.swift b/clients/shared/DesignSystem/Gallery/Sections/FeedbackGallerySection.swift index f688383d9ab..d904dc9ccd6 100644 --- a/clients/shared/DesignSystem/Gallery/Sections/FeedbackGallerySection.swift +++ b/clients/shared/DesignSystem/Gallery/Sections/FeedbackGallerySection.swift @@ -1,4 +1,3 @@ -import VellumAssistantShared #if DEBUG import SwiftUI diff --git a/clients/shared/DesignSystem/Gallery/Sections/InputsGallerySection.swift b/clients/shared/DesignSystem/Gallery/Sections/InputsGallerySection.swift index 46da03af022..3e88715efda 100644 --- a/clients/shared/DesignSystem/Gallery/Sections/InputsGallerySection.swift +++ b/clients/shared/DesignSystem/Gallery/Sections/InputsGallerySection.swift @@ -1,4 +1,3 @@ -import VellumAssistantShared #if DEBUG import SwiftUI diff --git a/clients/shared/DesignSystem/Gallery/Sections/LayoutGallerySection.swift b/clients/shared/DesignSystem/Gallery/Sections/LayoutGallerySection.swift index 9f86223dfea..c602fcd29fd 100644 --- a/clients/shared/DesignSystem/Gallery/Sections/LayoutGallerySection.swift +++ b/clients/shared/DesignSystem/Gallery/Sections/LayoutGallerySection.swift @@ -1,4 +1,3 @@ -import VellumAssistantShared #if DEBUG import SwiftUI diff --git a/clients/shared/DesignSystem/Gallery/Sections/ModifiersGallerySection.swift b/clients/shared/DesignSystem/Gallery/Sections/ModifiersGallerySection.swift index a6ffe0c3b4f..d7c32eaaa34 100644 --- a/clients/shared/DesignSystem/Gallery/Sections/ModifiersGallerySection.swift +++ b/clients/shared/DesignSystem/Gallery/Sections/ModifiersGallerySection.swift @@ -1,4 +1,3 @@ -import VellumAssistantShared #if DEBUG import SwiftUI diff --git a/clients/shared/DesignSystem/Gallery/Sections/NavigationGallerySection.swift b/clients/shared/DesignSystem/Gallery/Sections/NavigationGallerySection.swift index 12fe269b421..7ec1b0cc9c3 100644 --- a/clients/shared/DesignSystem/Gallery/Sections/NavigationGallerySection.swift +++ b/clients/shared/DesignSystem/Gallery/Sections/NavigationGallerySection.swift @@ -1,4 +1,3 @@ -import VellumAssistantShared #if DEBUG import SwiftUI diff --git a/clients/shared/DesignSystem/Gallery/Sections/TokensGallerySection.swift b/clients/shared/DesignSystem/Gallery/Sections/TokensGallerySection.swift index b518fe0057b..cb7a45d8faa 100644 --- a/clients/shared/DesignSystem/Gallery/Sections/TokensGallerySection.swift +++ b/clients/shared/DesignSystem/Gallery/Sections/TokensGallerySection.swift @@ -1,4 +1,3 @@ -import VellumAssistantShared #if DEBUG import SwiftUI diff --git a/clients/shared/DesignSystem/Modifiers/HoverEffect.swift b/clients/shared/DesignSystem/Modifiers/HoverEffect.swift index 2ca4a8c69f1..6cd13c19440 100644 --- a/clients/shared/DesignSystem/Modifiers/HoverEffect.swift +++ b/clients/shared/DesignSystem/Modifiers/HoverEffect.swift @@ -3,6 +3,8 @@ import SwiftUI public struct HoverEffectModifier: ViewModifier { @State private var isHovered = false + public init() {} + public func body(content: Content) -> some View { content .background(isHovered ? VColor.surfaceBorder.opacity(0.5) : .clear) diff --git a/clients/shared/DesignSystem/Modifiers/PanelBackground.swift b/clients/shared/DesignSystem/Modifiers/PanelBackground.swift index cb7f28e6528..630571cb182 100644 --- a/clients/shared/DesignSystem/Modifiers/PanelBackground.swift +++ b/clients/shared/DesignSystem/Modifiers/PanelBackground.swift @@ -1,6 +1,8 @@ import SwiftUI public struct PanelBackgroundModifier: ViewModifier { + public init() {} + public func body(content: Content) -> some View { content .frame(maxWidth: .infinity, maxHeight: .infinity) diff --git a/clients/shared/DesignSystem/Tokens/TypographyTokens.swift b/clients/shared/DesignSystem/Tokens/TypographyTokens.swift index a55d36d068f..0fee360ad78 100644 --- a/clients/shared/DesignSystem/Tokens/TypographyTokens.swift +++ b/clients/shared/DesignSystem/Tokens/TypographyTokens.swift @@ -26,8 +26,16 @@ public enum VFont { ]) return Font(NSFont(descriptor: descriptor, size: size) ?? nsFont) #elseif os(iOS) - // iOS: Use custom font without stylistic alternates (not as widely supported) - return Font.custom(name, size: size) + guard let uiFont = UIFont(name: name, size: size) else { + return Font.custom(name, size: size) + } + let descriptor = uiFont.fontDescriptor.addingAttributes([ + .featureSettings: [[ + UIFontDescriptor.FeatureKey.type: kStylisticAlternativesType, + UIFontDescriptor.FeatureKey.selector: kStylisticAltFiveOnSelector, + ]] + ]) + return Font(UIFont(descriptor: descriptor, size: size)) #endif } // MARK: - Onboarding (Silkscreen pixel font) From be1a4d079b06b60ed04a45594bdb6bf287047667 Mon Sep 17 00:00:00 2001 From: Ashlee Radka Date: Sat, 14 Feb 2026 04:42:09 -0500 Subject: [PATCH 5/7] Make ComponentGalleryWindow.close() public for API consistency All other methods (init, show) are public, so close() should be too. Co-Authored-By: Claude Sonnet 4.5 --- .../shared/DesignSystem/Gallery/ComponentGalleryWindow.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/shared/DesignSystem/Gallery/ComponentGalleryWindow.swift b/clients/shared/DesignSystem/Gallery/ComponentGalleryWindow.swift index b01d2b5ba80..a1054ad3cf2 100644 --- a/clients/shared/DesignSystem/Gallery/ComponentGalleryWindow.swift +++ b/clients/shared/DesignSystem/Gallery/ComponentGalleryWindow.swift @@ -40,7 +40,7 @@ public final class ComponentGalleryWindow { self.window = window } - func close() { + public func close() { window?.close() window = nil } From 4672e22f3d6f5c7821c30388d0480ddad1b4f7b6 Mon Sep 17 00:00:00 2001 From: Ashlee Radka Date: Sat, 14 Feb 2026 13:49:03 -0500 Subject: [PATCH 6/7] Fix iOS UIFontDescriptor property names for stylistic alternates Use correct iOS property names: - .featureIdentifier (for feature type, not .type) - .typeIdentifier (for feature selector, not .selector) The iOS naming is confusing because .typeIdentifier on iOS corresponds to .selectorIdentifier on macOS. This fix prevents iOS compilation failure. Addresses Devin review feedback. Co-Authored-By: Claude Sonnet 4.5 --- clients/shared/DesignSystem/Tokens/TypographyTokens.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clients/shared/DesignSystem/Tokens/TypographyTokens.swift b/clients/shared/DesignSystem/Tokens/TypographyTokens.swift index 0fee360ad78..ab9848492a5 100644 --- a/clients/shared/DesignSystem/Tokens/TypographyTokens.swift +++ b/clients/shared/DesignSystem/Tokens/TypographyTokens.swift @@ -31,8 +31,8 @@ public enum VFont { } let descriptor = uiFont.fontDescriptor.addingAttributes([ .featureSettings: [[ - UIFontDescriptor.FeatureKey.type: kStylisticAlternativesType, - UIFontDescriptor.FeatureKey.selector: kStylisticAltFiveOnSelector, + UIFontDescriptor.FeatureKey.featureIdentifier: kStylisticAlternativesType, + UIFontDescriptor.FeatureKey.typeIdentifier: kStylisticAltFiveOnSelector, ]] ]) return Font(UIFont(descriptor: descriptor, size: size)) From e1381a5e6b9f00eb5cb780f6b675e5368fe15e13 Mon Sep 17 00:00:00 2001 From: Ashlee Radka Date: Sat, 14 Feb 2026 13:56:39 -0500 Subject: [PATCH 7/7] Add platform fallback to dmMono() for future compatibility Add #else clause to handle unsupported platforms (visionOS, tvOS, watchOS). Without this, the function would have no return statement on those platforms, causing a compilation error. Fallback uses plain Font.custom() without stylistic alternates. Co-Authored-By: Claude Sonnet 4.5 --- clients/shared/DesignSystem/Tokens/TypographyTokens.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/clients/shared/DesignSystem/Tokens/TypographyTokens.swift b/clients/shared/DesignSystem/Tokens/TypographyTokens.swift index ab9848492a5..e2dac1e0fc7 100644 --- a/clients/shared/DesignSystem/Tokens/TypographyTokens.swift +++ b/clients/shared/DesignSystem/Tokens/TypographyTokens.swift @@ -36,6 +36,9 @@ public enum VFont { ]] ]) return Font(UIFont(descriptor: descriptor, size: size)) + #else + // Fallback for unsupported platforms (visionOS, tvOS, watchOS) + return Font.custom(name, size: size) #endif } // MARK: - Onboarding (Silkscreen pixel font)