Layout and component patterns for SwiftUI apps targeting iOS 26+ with Swift 6.3. Covers stack and grid layouts, list patterns, scroll views, forms, controls, search, and overlays. Patterns are backward-compatible to iOS 17 unless noted.
Works with
AI-first code editor with Composer
Before installing skills in Cursor, ensure your development environment meets these requirements:
node --versionswiftui-layout-componentsExecute the skills CLI command in your project's root directory to begin installation:
Fetches swiftui-layout-components from dpearson2699/swift-ios-skills and configures it for Cursor.
The CLI shows a list of agents. Use arrow keys and space to select Cursor:
Confirm successful installation by checking the skill directory location:
Restart Cursor to activate swiftui-layout-components. Access via /swiftui-layout-components in your agent's command palette.
We perform automated surface-level scans (Gen AI Scanner, Socket, Snyk) during installation. These checks detect common vulnerabilities but do not guarantee complete security. Always review skill source code and verify the publisher's reputation before production use.
Skills execute code in your environment. Always review source, verify the publisher, and test in isolation before production.
Submit your Claude Code skill and start earning
Automate repetitive workflows and reduce manual effort
Example
Generate reports, summarize documents, draft communications
Save 3-5 hours per week on routine tasks
Learn new skills, understand complex topics, get expert guidance
Example
Explain concepts, provide examples, suggest learning resources
Accelerate learning and skill development by 2x
Enhance output quality through reviews, suggestions, and refinements
Example
Review drafts, suggest improvements, catch errors
Improve work quality by 30-40% with less effort
0
total installs
0
this week
372
GitHub stars
0
upvotes
Run in your terminal
0
installs
0
this week
372
stars
Layout and component patterns for SwiftUI apps targeting iOS 26+ with Swift 6.3. Covers stack and grid layouts, list patterns, scroll views, forms, controls, search, and overlays. Patterns are backward-compatible to iOS 17 unless noted.
Use VStack, HStack, and ZStack for small, fixed-size content. They render all children immediately.
VStack(alignment: .leading, spacing: 8) {
Text(title).font(.headline)
Text(subtitle).font(.subheadline).foregroundStyle(.secondary)
}
Use LazyVStack and LazyHStack inside ScrollView for large or dynamic collections. They create child views on demand as they scroll into view.
ScrollView {
LazyVStack(spacing: 12) {
ForEach(items) { item in
ItemRow(item: item)
}
}
.padding(.horizontal)
}
When to use which:
Use LazyVGrid for icon pickers, media galleries, and dense visual selections. Use .adaptive columns for layouts that scale across device sizes, or .flexible columns for a fixed column count.
// Adaptive grid -- columns adjust to fit
let columns = [GridItem(.adaptive(minimum: 120, maximum: 1024))]
LazyVGrid(columns: columns, spacing: 6) {
ForEach(items) { item in
ThumbnailView(item: item)
.aspectRatio(1, contentMode: .fit)
}
}
// Fixed 3-column grid
let columns = Array(repeating: GridItem(.flexible(minimum: 100), spacing: 4), count: 3)
LazyVGrid(columns: columns, spacing: 4) {
ForEach(items) { item in
ThumbnailView(item: item)
}
}
Use .aspectRatio for cell sizing. Never place GeometryReader inside lazy containers -- it forces eager measurement and defeats lazy loading. Use .onGeometryChange (iOS 18+) if you need to read dimensions.
See references/grids.md for full grid patterns and design choices.
Use List for feed-style content and settings rows where built-in row reuse, selection, and accessibility matter.
List {
Section("General") {
NavigationLink("Display") { DisplaySettingsView() }
NavigationLink("Haptics") { HapticsSettingsView() }
}
Section("Account") {
Button("Sign Out", role: .destructive) { }
}
}
.listStyle(.insetGrouped)
Key patterns:
.listStyle(.plain) for feed layouts, .insetGrouped for settings.scrollContentBackground(.hidden) + custom background for themed surfaces.listRowInsets(...) and .listRowSeparator(.hidden) for spacing and separator controlScrollViewReader for scroll-to-top or jump-to-id.refreshable { } for pull-to-refresh feeds.contentShape(Rectangle()) on rows that should be tappable end-to-endiOS 26: Apply .scrollEdgeEffectStyle(.soft, for: .top) for modern scroll edge effects.
See references/list.md for full list patterns including feed lists with scroll-to-top.
Use ScrollView with lazy stacks when you need custom layout, mixed content, or horizontal scrolling.
ScrollView(.horizontal, showsIndicators: false) {
LazyHStack(spacing: 8) {
ForEach(chips) { chip in
ChipView(chip: chip)
}
}
}
ScrollViewReader: Enables programmatic scrolling to specific items.
ScrollViewReader { proxy in
ScrollView {
LazyVStack {
ForEach(messages) { message in
MessageRow(message: message).id(message.id)
}
}
}
.onChange(of: messages.last?.id) { _, newValue in
if let id = newValue {
withAnimation { proxy.scrollTo(id, anchor: .bottom) }
}
}
}
safeAreaInset(edge:) pins content (input bars, toolbars) above the keyboard without affecting scroll layout.
iOS 26 additions:
.scrollEdgeEffectStyle(.soft, for: .top) -- fading edge effect.backgroundExtensionEffect() -- mirror/blur at safe area edges (use sparingly, one per screen).safeAreaBar(edge:) -- attach bar views that integrate with scroll effectsSee references/scrollview.md for full scroll patterns and iOS 26 edge effects.
Use Form for structured settings and input screens. Group related controls into Section blocks.
Form {
Section("Notifications") {
Toggle("Mentions", isOn: $prefs.mentions)
Toggle("Follows", isOn: $prefs.follows)
}
Section("Appearance") {
Picker("Theme", selection: $theme) {
ForEach(Theme.allCases, id: \.self) { Text($0.title).tag($0) }
}
Slider(value: $fontScale, in: 0.5...1.5, step: 0.1)
}
}
.formStyle(.grouped)
.scrollContentBackground(.hidden)
Use @FocusState to manage keyboard focus in input-heavy forms. Wrap in NavigationStack only when presented standalone or in a sheet.
| Control | Usage |
|---|