swiftui-colors-modifiers

SwiftUI Colors and Modifiers

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "swiftui-colors-modifiers" with this command: npx skills add bluewaves-creations/bluewaves-skills/bluewaves-creations-bluewaves-skills-swiftui-colors-modifiers

SwiftUI Colors and Modifiers

Comprehensive guide to modern SwiftUI color APIs, ShapeStyle, gradients, and creating reusable ViewModifiers for iOS 26.

Prerequisites

  • iOS 15+ for foregroundStyle (iOS 26 recommended)

  • Xcode 26+

Modern Color APIs

foregroundStyle (Recommended)

Replaces the deprecated foregroundColor(_:) :

// DEPRECATED Text("Hello") .foregroundColor(.blue)

// MODERN - Use foregroundStyle Text("Hello") .foregroundStyle(.blue)

// With gradients Text("Gradient Text") .foregroundStyle( LinearGradient( colors: [.blue, .purple], startPoint: .leading, endPoint: .trailing ) )

ShapeStyle Protocol

foregroundStyle accepts any ShapeStyle :

// Colors .foregroundStyle(.red) .foregroundStyle(Color.blue)

// Gradients .foregroundStyle(LinearGradient(...)) .foregroundStyle(RadialGradient(...)) .foregroundStyle(AngularGradient(...)) .foregroundStyle(MeshGradient(...))

// Materials .foregroundStyle(.ultraThinMaterial) .foregroundStyle(.regularMaterial)

// Hierarchical .foregroundStyle(.primary) .foregroundStyle(.secondary) .foregroundStyle(.tertiary)

Hierarchical Colors

Setting Hierarchy at Root

// Set all three levels at once ContentView() .foregroundStyle(.red, .orange, .yellow)

// Children use hierarchical levels struct ContentView: View { var body: some View { VStack { Text("Primary") // Red .foregroundStyle(.primary) Text("Secondary") // Orange .foregroundStyle(.secondary) Text("Tertiary") // Yellow .foregroundStyle(.tertiary) } } }

Available Levels

.foregroundStyle(.primary) // Level 1 - Most prominent .foregroundStyle(.secondary) // Level 2 .foregroundStyle(.tertiary) // Level 3 .foregroundStyle(.quaternary) // Level 4 .foregroundStyle(.quinary) // Level 5 - Least prominent

Note: Only first three can be customized via foregroundStyle(::_:) .

Practical Example

struct CardView: View { let title: String let subtitle: String let detail: String

var body: some View {
    VStack(alignment: .leading, spacing: 4) {
        Text(title)
            .font(.headline)
            .foregroundStyle(.primary)

        Text(subtitle)
            .font(.subheadline)
            .foregroundStyle(.secondary)

        Text(detail)
            .font(.caption)
            .foregroundStyle(.tertiary)
    }
}

}

Semantic Colors

System Colors

// Adaptive colors (change with Dark Mode) Color.primary // Black/White Color.secondary // Gray Color.accentColor // App's accent color

// UI element colors Color(uiColor: .systemBackground) Color(uiColor: .secondarySystemBackground) Color(uiColor: .tertiarySystemBackground) Color(uiColor: .label) Color(uiColor: .secondaryLabel)

Accent Color

Set in Asset Catalog or programmatically:

// In code Button("Action") { } .tint(.blue)

// App-wide in Assets.xcassets: // Create "AccentColor" color set

Tint Modifier

Override accent color for a hierarchy:

// tint affects interactive elements, not all foreground VStack { Button("Blue") { } // Uses blue tint Link("Website", destination: url) // Uses blue tint Text("Plain") // NOT affected by tint } .tint(.blue)

tint vs foregroundStyle:

  • tint : Affects buttons, links, controls

  • foregroundStyle : Affects all foreground content

Gradients

LinearGradient

LinearGradient( colors: [.blue, .purple], startPoint: .topLeading, endPoint: .bottomTrailing )

// With stops for control LinearGradient( stops: [ .init(color: .red, location: 0), .init(color: .orange, location: 0.3), .init(color: .yellow, location: 1) ], startPoint: .top, endPoint: .bottom )

// Usage Rectangle() .fill( LinearGradient( colors: [.blue, .cyan], startPoint: .leading, endPoint: .trailing ) )

RadialGradient

RadialGradient( colors: [.white, .blue], center: .center, startRadius: 0, endRadius: 200 )

// With offset center RadialGradient( colors: [.yellow, .orange, .red], center: .topLeading, startRadius: 50, endRadius: 300 )

AngularGradient

AngularGradient( colors: [.red, .yellow, .green, .blue, .purple, .red], center: .center )

// Conic gradient with angle AngularGradient( colors: [.blue, .purple], center: .center, startAngle: .degrees(0), endAngle: .degrees(180) )

MeshGradient (iOS 18+)

Complex multi-point gradients:

MeshGradient( width: 3, height: 3, points: [ // Row 0 [0.0, 0.0], [0.5, 0.0], [1.0, 0.0], // Row 1 [0.0, 0.5], [0.5, 0.5], [1.0, 0.5], // Row 2 [0.0, 1.0], [0.5, 1.0], [1.0, 1.0] ], colors: [ .red, .orange, .yellow, .green, .blue, .purple, .pink, .cyan, .mint ] )

// Animated mesh struct AnimatedMesh: View { @State private var offset: CGFloat = 0

var body: some View {
    MeshGradient(
        width: 3,
        height: 3,
        points: [
            [0.0, 0.0], [0.5, 0.0], [1.0, 0.0],
            [0.0, 0.5], [0.5 + offset, 0.5], [1.0, 0.5],
            [0.0, 1.0], [0.5, 1.0], [1.0, 1.0]
        ],
        colors: [
            .blue, .cyan, .teal,
            .purple, .indigo, .blue,
            .pink, .orange, .yellow
        ],
        smoothsColors: true
    )
    .onAppear {
        withAnimation(.easeInOut(duration: 2).repeatForever()) {
            offset = 0.2
        }
    }
}

}

Asset Catalog Colors

Creating Color Sets

  • Open Assets.xcassets

  • Right-click → New Color Set

  • Configure for appearances:

  • Any Appearance

  • Light

  • Dark

  • High Contrast variants

Using Asset Colors

// By name Color("BrandPrimary") Color("BackgroundColor")

// With bundle Color("CustomColor", bundle: .module)

Organizing Colors

Assets.xcassets/ ├── Colors/ │ ├── Brand/ │ │ ├── BrandPrimary │ │ ├── BrandSecondary │ │ └── BrandAccent │ ├── UI/ │ │ ├── BackgroundPrimary │ │ ├── BackgroundSecondary │ │ └── SeparatorColor │ └── Text/ │ ├── TextPrimary │ ├── TextSecondary │ └── TextTertiary

Custom ShapeStyles (iOS 17+)

struct StripedStyle: ShapeStyle { var color1: Color var color2: Color var stripeWidth: CGFloat

func resolve(in environment: EnvironmentValues) -> some ShapeStyle {
    // Return a resolved style
    LinearGradient(
        stops: generateStripeStops(),
        startPoint: .leading,
        endPoint: .trailing
    )
}

private func generateStripeStops() -> [Gradient.Stop] {
    var stops: [Gradient.Stop] = []
    var position: CGFloat = 0

    while position < 1 {
        stops.append(.init(color: color1, location: position))
        stops.append(.init(color: color1, location: position + stripeWidth / 2))
        stops.append(.init(color: color2, location: position + stripeWidth / 2))
        stops.append(.init(color: color2, location: position + stripeWidth))
        position += stripeWidth
    }

    return stops
}

}

// Usage Rectangle() .fill(StripedStyle(color1: .blue, color2: .white, stripeWidth: 0.1))

Custom ViewModifiers

Basic Modifier

struct CardStyle: ViewModifier { func body(content: Content) -> some View { content .padding() .background(.regularMaterial) .clipShape(RoundedRectangle(cornerRadius: 12)) .shadow(radius: 4) } }

extension View { func cardStyle() -> some View { modifier(CardStyle()) } }

// Usage Text("Card Content") .cardStyle()

Configurable Modifier

struct RoundedStyle: ViewModifier { var cornerRadius: CGFloat var backgroundColor: Color var shadowRadius: CGFloat

func body(content: Content) -> some View {
    content
        .padding()
        .background(backgroundColor)
        .clipShape(RoundedRectangle(cornerRadius: cornerRadius))
        .shadow(radius: shadowRadius)
}

}

extension View { func rounded( cornerRadius: CGFloat = 12, backgroundColor: Color = .white, shadowRadius: CGFloat = 4 ) -> some View { modifier(RoundedStyle( cornerRadius: cornerRadius, backgroundColor: backgroundColor, shadowRadius: shadowRadius )) } }

// Usage Text("Custom") .rounded(cornerRadius: 20, backgroundColor: .blue)

Environment-Aware Modifier

struct AdaptiveCard: ViewModifier { @Environment(.colorScheme) var colorScheme

func body(content: Content) -> some View {
    content
        .padding()
        .background(colorScheme == .dark ? Color.gray.opacity(0.2) : Color.white)
        .clipShape(RoundedRectangle(cornerRadius: 12))
        .shadow(
            color: colorScheme == .dark ? .clear : .black.opacity(0.1),
            radius: 8
        )
}

}

Conditional Modifier

extension View { @ViewBuilder func if<Content: View>( _ condition: Bool, transform: (Self) -> Content ) -> some View { if condition { transform(self) } else { self } }

@ViewBuilder
func ifLet&#x3C;T, Content: View>(
    _ value: T?,
    transform: (Self, T) -> Content
) -> some View {
    if let value {
        transform(self, value)
    } else {
        self
    }
}

}

// Usage Text("Hello") .if(isHighlighted) { view in view.foregroundStyle(.yellow) } .ifLet(user) { view, user in view.badge(user.notificationCount) }

iOS 26 New Modifiers

Close Button Role

.toolbar { ToolbarItem(placement: .cancellationAction) { Button("Dismiss", role: .close) { dismiss() } // Renders as glass X button } }

Glass Button Styles

Button("Glass") { } .buttonStyle(.glass)

Button("Prominent") { } .buttonStyle(.glassProminent)

Custom Slider Ticks

Slider(value: $value, in: 0...100) { Text("Value") } minimumValueLabel: { Text("0") } maximumValueLabel: { Text("100") } .sliderStyle(.ticked(count: 10)) // iOS 26

Design System Example

// DesignSystem.swift enum DS { enum Colors { static let primary = Color("Primary") static let secondary = Color("Secondary") static let background = Color("Background") static let surface = Color("Surface") static let error = Color("Error") static let success = Color("Success") }

enum Spacing {
    static let xs: CGFloat = 4
    static let sm: CGFloat = 8
    static let md: CGFloat = 16
    static let lg: CGFloat = 24
    static let xl: CGFloat = 32
}

enum CornerRadius {
    static let sm: CGFloat = 4
    static let md: CGFloat = 8
    static let lg: CGFloat = 16
    static let xl: CGFloat = 24
}

}

// Modifiers using design system struct DSCard: ViewModifier { func body(content: Content) -> some View { content .padding(DS.Spacing.md) .background(DS.Colors.surface) .clipShape(RoundedRectangle(cornerRadius: DS.CornerRadius.lg)) } }

extension View { func dsCard() -> some View { modifier(DSCard()) } }

Best Practices

  • Use foregroundStyle - Not deprecated foregroundColor

  • Leverage Hierarchical Colors - .primary, .secondary, .tertiary

  • Asset Catalog for Themes - Organize colors properly

  • DRY with Modifiers - Create reusable ViewModifiers

  • Compose Modifiers - Build complex styles from simple ones

  • Environment Awareness - Respect colorScheme and accessibility

Official Resources

  • Color Documentation

  • ShapeStyle Documentation

  • ViewModifier Documentation

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

photographer-testino

No summary provided by upstream source.

Repository SourceNeeds Review
General

photographer-lindbergh

No summary provided by upstream source.

Repository SourceNeeds Review
General

photographer-lachapelle

No summary provided by upstream source.

Repository SourceNeeds Review
General

photographer-vonunwerth

No summary provided by upstream source.

Repository SourceNeeds Review