Files
honeyDueKMP/iosApp/iosApp/Design/DesignSystem.swift
Trey t a2de0f3454 Migrate iOS app to system colors and improve UI/UX
- Remove AppColors struct, migrate to iOS system colors throughout
- Redesign ContractorFormSheet to use native SwiftUI Form components
- Add color-coded icons to contractor form sections
- Improve dark mode contrast for task cards
- Add background colors to document detail fields
- Fix text alignment issues in ContractorDetailView
- Make task completion lists expandable/collapsible by default
- Clear app badge on launch and when app becomes active
- Update button styling with proper gradients and shadows
- Improve form field focus states and accessibility

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-13 22:22:52 -06:00

147 lines
4.3 KiB
Swift

import SwiftUI
// MARK: - Design System
// Modern, sleek design system for MyCrib with Light and Dark mode support
struct AppSpacing {
static let xxs: CGFloat = 4
static let xs: CGFloat = 8
static let sm: CGFloat = 12
static let md: CGFloat = 16
static let lg: CGFloat = 24
static let xl: CGFloat = 32
static let xxl: CGFloat = 48
static let xxxl: CGFloat = 64
}
struct AppRadius {
static let xs: CGFloat = 4
static let sm: CGFloat = 8
static let md: CGFloat = 12
static let lg: CGFloat = 16
static let xl: CGFloat = 20
static let xxl: CGFloat = 24
static let full: CGFloat = 9999
}
struct AppShadow {
static let sm = Shadow(color: .black.opacity(0.05), radius: 2, y: 1)
static let md = Shadow(color: .black.opacity(0.1), radius: 4, y: 2)
static let lg = Shadow(color: .black.opacity(0.1), radius: 8, y: 4)
static let xl = Shadow(color: .black.opacity(0.15), radius: 16, y: 8)
struct Shadow {
let color: Color
let radius: CGFloat
let x: CGFloat
let y: CGFloat
init(color: Color, radius: CGFloat, x: CGFloat = 0, y: CGFloat) {
self.color = color
self.radius = radius
self.x = x
self.y = y
}
}
}
// MARK: - View Modifiers
struct CardStyle: ViewModifier {
var shadow: AppShadow.Shadow = AppShadow.md
var padding: CGFloat = AppSpacing.md
func body(content: Content) -> some View {
content
.background(Color(.secondarySystemGroupedBackground))
.cornerRadius(AppRadius.lg)
.shadow(color: shadow.color, radius: shadow.radius, x: shadow.x, y: shadow.y)
}
}
struct PrimaryButtonStyle: ButtonStyle {
var isLoading: Bool = false
func makeBody(configuration: Configuration) -> some View {
configuration.label
.font(.headline)
.foregroundColor(.white)
.frame(maxWidth: .infinity)
.frame(height: 56)
.background(
configuration.isPressed ? .blue : .blue
)
.cornerRadius(AppRadius.md)
.scaleEffect(configuration.isPressed ? 0.98 : 1.0)
.animation(.easeInOut(duration: 0.1), value: configuration.isPressed)
}
}
struct SecondaryButtonStyle: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.font(.headline)
.foregroundColor(.blue)
.frame(maxWidth: .infinity)
.frame(height: 56)
.background(Color(.tertiarySystemGroupedBackground))
.cornerRadius(AppRadius.md)
.scaleEffect(configuration.isPressed ? 0.98 : 1.0)
.animation(.easeInOut(duration: 0.1), value: configuration.isPressed)
}
}
struct TextFieldStyle: ViewModifier {
func body(content: Content) -> some View {
content
.padding(AppSpacing.md)
.background(Color(.tertiarySystemGroupedBackground))
.cornerRadius(AppRadius.md)
.overlay(
RoundedRectangle(cornerRadius: AppRadius.md)
.stroke(Color(.opaqueSeparator), lineWidth: 1)
)
}
}
// MARK: - View Extensions
extension View {
func cardStyle(shadow: AppShadow.Shadow = AppShadow.md) -> some View {
modifier(CardStyle(shadow: shadow))
}
func textFieldStyle() -> some View {
modifier(TextFieldStyle())
}
}
// MARK: - Color Extension for Hex Support
extension Color {
init?(hex: String) {
let hex = hex.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
var int: UInt64 = 0
Scanner(string: hex).scanHexInt64(&int)
let a, r, g, b: UInt64
switch hex.count {
case 3: // RGB (12-bit)
(a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17)
case 6: // RGB (24-bit)
(a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF)
case 8: // ARGB (32-bit)
(a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF)
default:
return nil
}
self.init(
.sRGB,
red: Double(r) / 255,
green: Double(g) / 255,
blue: Double(b) / 255,
opacity: Double(a) / 255
)
}
}