AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Layout

skill-abdullah4ai-apple-developer-toolkit-layout · by Abdullah4AI

Layout patterns: VStack/HStack/ZStack composition, view structure, subview extraction, GeometryReader alternatives, safe area handling. Use when arranging views, building screen layouts, or structuring view hierarchies. Triggers: VStack, HStack, ZStack, LazyVStack, Grid, Spacer, padding, frame, GeometryReader.

No reviews yet
0 installs
20 views
0.0% view→install

Install

$ agentstack add skill-abdullah4ai-apple-developer-toolkit-layout

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets Used
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-abdullah4ai-apple-developer-toolkit-layout)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
2mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Layout? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

SwiftUI Layout & View Structure Reference

Comprehensive guide to stack layouts, view composition, subview extraction, and layout best practices.

Relative Layout Over Constants

// Good - relative to actual layout
GeometryReader { geometry in
    VStack {
        HeaderView()
            .frame(height: geometry.size.height * 0.2)
        ContentView()
    }
}

// Avoid - magic numbers that don't adapt
VStack {
    HeaderView()
        .frame(height: 150)  // Doesn't adapt to different screens
    ContentView()
}

Context-Agnostic Views

Views should work in any context. Never assume presentation style or screen size.

// Good - adapts to given space
struct ProfileCard: View {
    let user: User

    var body: some View {
        VStack {
            Image(user.avatar)
                .resizable()
                .aspectRatio(contentMode: .fit)
            Text(user.name)
            Spacer()
        }
        .padding()
    }
}

// Avoid - assumes full screen
Image(user.avatar)
    .frame(width: UIScreen.main.bounds.width)  // Wrong!

Own Your Container

Custom views should own static containers but not lazy/repeatable ones.

// Good - owns static container
struct HeaderView: View {
    var body: some View {
        HStack {
            Image(systemName: "star")
            Text("Title")
            Spacer()
        }
    }
}

View Structure Principles

SwiftUI's diffing algorithm compares view hierarchies to determine what needs updating.

Prefer Modifiers Over Conditional Views

// Good - same view, different states
SomeView()
    .opacity(isVisible ? 1 : 0)

// Avoid - creates/destroys view identity
if isVisible {
    SomeView()
}

Use conditionals when you truly have different views:

// Correct - fundamentally different views
if isLoggedIn {
    DashboardView()
} else {
    LoginView()
}

Extract Subviews, Not Computed Properties

The Problem with @ViewBuilder Functions

// BAD - re-executes complexSection() on every tap
struct ParentView: View {
    @State private var count = 0

    var body: some View {
        VStack {
            Button("Tap: \(count)") { count += 1 }
            complexSection()  // Re-executes every tap!
        }
    }

    @ViewBuilder
    func complexSection() -> some View {
        ForEach(0..: View {
    let content: () -> Content
    var body: some View {
        VStack { Text("Header"); content() }
    }
}

// GOOD - view can be compared
struct MyContainer: View {
    @ViewBuilder let content: Content
    var body: some View {
        VStack { Text("Header"); content }
    }
}

ZStack vs overlay/background

Use ZStack to compose multiple peer views that should be layered together.

Prefer overlay / background when decorating a primary view.

// GOOD - decoration in overlay
Button("Continue") { }
.overlay(alignment: .trailing) {
    Image(systemName: "lock.fill")
        .padding(.trailing, 8)
}

// GOOD - background shape takes parent size
HStack(spacing: 12) {
    Image(systemName: "tray")
    Text("Inbox")
}
.background {
    Capsule()
        .strokeBorder(.blue, lineWidth: 2)
}

Layout Performance

Avoid Layout Thrash

// Bad - deep nesting, excessive layout passes
VStack { HStack { VStack { HStack { Text("Deep") } } } }

// Good - flatter hierarchy
VStack { Text("Shallow"); Text("Structure") }

Minimize GeometryReader (use iOS 17+ alternatives)

// Good - single geometry reader or containerRelativeFrame
containerRelativeFrame(.horizontal) { width, _ in
    width * 0.8
}

Gate Frequent Geometry Updates

// Good - gate by threshold
.onPreferenceChange(ViewSizeKey.self) { size in
    let difference = abs(size.width - currentSize.width)
    if difference > 10 { currentSize = size }
}

View Logic and Testability

// Good - logic in testable model (iOS 17+)
@Observable
@MainActor
final class LoginViewModel {
    var email = ""
    var password = ""
    var isValid: Bool {
        !email.isEmpty && password.count >= 8
    }

    func login() async throws { }
}

struct LoginView: View {
    @State private var viewModel = LoginViewModel()

    var body: some View {
        Form {
            TextField("Email", text: $viewModel.email)
            SecureField("Password", text: $viewModel.password)
            Button("Login") {
                Task { try? await viewModel.login() }
            }
            .disabled(!viewModel.isValid)
        }
    }
}

Action Handlers

// Good - action references method
struct PublishView: View {
    @State private var viewModel = PublishViewModel()

    var body: some View {
        Button("Publish Project", action: viewModel.handlePublish)
    }
}

iPad-Specific Patterns

Size Classes

Use @Environment(\.horizontalSizeClass) for layout decisions — never device checks:

@Environment(\.horizontalSizeClass) private var horizontalSizeClass

| Context | horizontalSizeClass | |---|---| | iPad full-screen (any orientation) | .regular | | iPad Split View (narrow) | .compact | | iPad Split View (wide) | .regular |

Critical: iPad in Split View can report .compact — always use size classes, never UIDevice.current.

Adaptive Layout Switching

@Environment(\.horizontalSizeClass) private var sizeClass

var body: some View {
    let layout = sizeClass == .compact
        ? AnyLayout(VStackLayout(spacing: 16))
        : AnyLayout(HStackLayout(spacing: 24))
    layout {
        ContentBlockA()
        ContentBlockB()
    }
}

Adaptive Grids

Always use GridItem(.adaptive(minimum:maximum:)) — automatically adjusts columns:

LazyVGrid(
    columns: [GridItem(.adaptive(minimum: 160, maximum: 320))],
    spacing: 16
) {
    ForEach(items) { item in CardView(item: item) }
}
.padding()

Readability on Wide Screens

Constrain text content width on iPad to maintain readability:

ScrollView {
    content
        .frame(maxWidth: 700)
        .frame(maxWidth: .infinity)
}

Form Layout

Forms should not stretch full-width on iPad:

@Environment(\.horizontalSizeClass) private var sizeClass

Form {
    Section("General") { /* ... */ }
}
.formStyle(.grouped)
.frame(maxWidth: sizeClass == .regular ? 600 : .infinity)

ViewThatFits (component-level)

Use when a component should pick the best layout for available space:

ViewThatFits {
    HStack(spacing: 16) { icon; title; subtitle; actionButton }
    VStack(alignment: .leading, spacing: 8) {
        HStack { icon; title }; subtitle; actionButton
    }
}

Relative Sizing

Prefer containerRelativeFrame over GeometryReader:

Image("photo")
    .containerRelativeFrame(.horizontal, count: 3, span: 1, spacing: 16)

iPad Layout Rules

  1. NEVER use UIDevice.current, UIScreen.main.bounds, or #if targetEnvironment for layout
  2. NEVER hardcode frame widths or column counts
  3. ALWAYS use GridItem(.adaptive(minimum:)) for grids
  4. ALWAYS constrain text to ~700pt max width on wide screens
  5. ALWAYS use .leading/.trailing — never .left/.right
  6. Use @ScaledMetric for custom dimensions that respect Dynamic Type

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.