From swiftui
Quick reference for choosing and implementing iOS-native SwiftUI components, layouts, forms, lists, tabs, sheets, alerts, and toolbars.
How this skill is triggered — by the user, by Claude, or both
Slash command
/swiftui:beepus-maximus-swiftui-componentsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Quick reference for iOS 26+ SwiftUI components with HIG-compliant values, common aliases, and concrete best practices. Use this to pick the right component and implement it correctly the first time.
Quick reference for iOS 26+ SwiftUI components with HIG-compliant values, common aliases, and concrete best practices. Use this to pick the right component and implement it correctly the first time.
references/components.md for the full 50+ reference| User says | Maps to |
|---|---|
| popup, modal, bottom sheet, drawer | Sheet / FullScreenCover |
| dialog, confirmation, destructive action | Alert / ConfirmationDialog |
| list, table view, rows, cells | List / Form |
| tabs, tab bar, bottom nav | TabView |
| sidebar, split view, master-detail, two-column | NavigationSplitView |
| nav, navigation, drill-down, push | NavigationStack |
| grid, collection view, tiles, mosaic | LazyVGrid / LazyHGrid / Grid |
| dropdown, select, segmented, wheel | Picker |
| menu, long press menu, right-click | Menu / ContextMenu |
| toolbar, nav bar buttons, top bar | ToolbarItem |
| search, search bar, filter | .searchable modifier |
| empty state, no results, placeholder | ContentUnavailableView |
| loading, spinner, progress bar | ProgressView |
| toggle, switch, checkbox | Toggle |
| slider, range | Slider |
| date, time, calendar | DatePicker |
| text field, input, type text | TextField / TextEditor |
| image from URL, remote image | AsyncImage |
| photo library, camera roll | PhotosPicker |
| expandable, collapsible, accordion | DisclosureGroup |
| share, share sheet | ShareLink |
| inspector, detail panel, side panel | Inspector |
Also known as: table view, rows, cells, UITableView When to use: Displaying scrollable collections of similar items with standard row layout. Key rules:
Section for grouped content; always provide headers for accessibility.listStyle(.insetGrouped) for settings-like screens, .plain for data-heavy screens.swipeActions for row actions, not custom gesture hacks
Common mistake: Wrapping List in ScrollView — List already scrolls. Double-nesting causes broken layout.Also known as: settings, preferences, input form When to use: Collecting user input in a structured settings-like layout. Key rules:
Section with descriptive headers and footersAlso known as: nav, navigation, drill-down, push, UINavigationController When to use: Linear navigation flows where users push/pop views. Key rules:
navigationDestination(for:) — never NavigationLink(destination:)@State private var path = NavigationPath() for programmatic navigation.navigationTitle() and .navigationBarTitleDisplayMode(.inline) or .large explicitly
Common mistake: Putting NavigationStack inside a child view instead of at the root of a tab.Also known as: sidebar, split view, master-detail, two-column, three-column When to use: Multi-column layouts — sidebar + detail on iPad, collapses to stack on iPhone. Key rules:
.navigationSplitViewColumnWidth(min:ideal:max:) for column sizingAlso known as: tabs, tab bar, bottom nav, UITabBarController When to use: Top-level app sections (max 5 visible tabs). Key rules:
Tab("Title", systemImage:) syntax with SF Symbols.badge() for notification counts.toolbar(.hidden, for: .tabBar) when it should stay visible.Also known as: modal, bottom sheet, popup, drawer, half-sheet When to use: Presenting focused tasks, creation flows, or supplementary content. Key rules:
.presentationDetents([.medium, .large]) for resizable sheets.presentationDetents([.fraction(0.4)]) or .height(300).presentationDragIndicator(.visible) when sheet is resizable@Environment(\.dismiss) private var dismiss.fullScreenCover when .sheet with detents would be less disruptive.Also known as: dialog, popup, warning, error dialog When to use: Critical information requiring acknowledgment, or simple yes/no decisions. Key rules:
.destructive role, place on the left.cancel role, system positions it automaticallyAlso known as: action sheet, confirmation, destructive action prompt When to use: Confirming destructive actions or choosing from 3+ options. Key rules:
.cancel role button (system provides one, but be explicit).destructive role for dangerous actions — it renders red automaticallyAlso known as: dropdown menu, overflow menu, more menu, ellipsis menu When to use: Exposing secondary actions from a button tap. Key rules:
Label("Title", systemImage:) for menu items with iconsMenu("Title") { } primaryAction: { } to give the button a default tapAlso known as: long-press menu, right-click menu, peek menu When to use: Surfacing secondary actions on long-press of content. Key rules:
contextMenu { } modifier on the target viewcontextMenu { } preview: { } for rich previewsAlso known as: scroll container, scrollable area When to use: Custom scrollable layouts that aren't List-shaped. Key rules:
.scrollTargetBehavior(.viewAligned) for paging/snappingScrollViewReader + .scrollTo(id:) for programmatic scrollingLazyVStack(pinnedViews: [.sectionHeaders]) for sticky headers.horizontal, .vertical, or [.horizontal, .vertical]
Common mistake: Using ScrollView + ForEach for simple lists — use List instead for free cell recycling.Also known as: grid, collection view, tiles, mosaic When to use: Two-dimensional grid layouts with vertical scrolling. Key rules:
[GridItem]: .fixed(size), .flexible(min:max:), .adaptive(minimum:).adaptive(minimum: 150) for responsive column countLazyHGrid for horizontal grids with row definitions
Common mistake: Using Grid (fixed, non-lazy) when content count is dynamic — use LazyVGrid.Also known as: horizontal grid, horizontal collection When to use: Horizontal scrolling grids (e.g., category rows). Key rules:
[GridItem], wrap in ScrollView(.horizontal)Also known as: tap target, CTA, action button When to use: Any tappable action trigger. Key rules:
.buttonStyle(.borderedProminent) for primary CTA, .bordered for secondaryrole: .destructive for delete/remove actionscontrolSize: .large for prominent actions, .small for inline.disabled(condition) — never hide buttons that might exist
Common mistake: Custom button styles without 44pt minimum hit area.Also known as: switch, checkbox, on/off When to use: Binary on/off settings. Key rules:
.toggleStyle(.switch) explicitly outside Form if needed.toggleStyle(.checkbox) (macOS) — iOS uses switchAlso known as: dropdown, select, segmented control, wheel, menu picker When to use: Selecting one option from a predefined set. Key rules:
.pickerStyle(.segmented) for 2-4 visible options inline.pickerStyle(.menu) for compact dropdown.pickerStyle(.wheel) only for very specific cases (time-like selection).wheel style for short option lists — use .menu or .segmented.Also known as: range slider, scrubber When to use: Selecting a value within a continuous range. Key rules:
in: range and step: for discrete valuesminimumValueLabel and maximumValueLabel for range contextAlso known as: date selector, calendar picker, time picker When to use: Selecting dates, times, or date-time combinations. Key rules:
displayedComponents: to show .date, .hourAndMinute, or both.datePickerStyle(.graphical) for full calendar viewin: range for valid date ranges
Common mistake: Allowing unbounded date ranges when business logic requires constraints.Also known as: empty state, no results, placeholder, zero state When to use: When a view has no content to display (empty list, no search results, error). Key rules:
ContentUnavailableView.search for empty search results (built-in)Also known as: loading, spinner, progress bar, activity indicator When to use: Indicating loading or operation progress. Key rules:
ProgressView() — spinning indicatorProgressView(value: 0.5) — progress bar, value 0.0-1.0.progressViewStyle(.circular) or .linear explicitly when neededProgressView("Loading data...")
Common mistake: Showing a spinner for < 200ms operations — use task with a delay threshold.For the complete 50+ component reference including Navigation, Presentation, Content, Controls, Feedback, Menus, Media, and Search categories with full code examples, decision tables, and anti-patterns, read references/components.md.
When multiple components could work, here are the fastest correct choices:
| Situation | Shortest Path |
|---|---|
| "I need a settings screen" | Form with Section, Toggle, Picker |
| "I need a data list" | List with .insetGrouped, swipeActions |
| "I need a grid of items" | ScrollView + LazyVGrid with .adaptive(minimum:) |
| "I need to collect input" | Sheet with Form inside |
| "I need to show detail" | navigationDestination(for:) push |
| "I need to confirm delete" | ConfirmationDialog with .destructive role |
| "I need empty state" | ContentUnavailableView with icon + description + action |
| "I need tabs" | TabView with NavigationStack per tab |
| Rule | Value |
|---|---|
| Minimum touch target | 44x44pt |
| Spacing scale | 4, 8, 12, 16, 24, 32 pt |
| Corner radius style | .continuous (never .circular) |
| Animation for controls | .spring(duration: 0.3, bounce: 0) |
| Animation for content | .spring(duration: 0.35, bounce: 0.1) |
| List row minimum height | 44pt |
| List row with subtitle | 60pt typical |
| Tab bar max visible items | 5 |
| Deployment target | iOS 26+ only — no @available checks, no deprecated APIs |
| NavigationView | BANNED — use NavigationStack or NavigationSplitView |
| NavigationLink(destination:) | BANNED — use navigationDestination(for:) |
.presentationDetents behave differently on iPad (sheets are popovers by default). Test on both..pickerStyle(.menu) it overrides this, which may not be what you want.npx claudepluginhub 4eleven7/claude-skills --plugin swiftuiCreates bite-sized, testable implementation plans from specs or requirements, with file structure and task decomposition. Activates before coding multi-step tasks.