{"id":"f0ea460d-54c8-441f-bf4d-b4608fe202a3","shortId":"ZVvmvZ","kind":"skill","title":"swiftui-layout-components","tagline":"Build SwiftUI layouts using stacks, grids, lists, scroll views, forms, and controls. Covers VStack/HStack/ZStack, LazyVGrid/LazyHGrid, List with sections and swipe actions, ScrollView with ScrollPosition, Form with validation, Toggle/Picker/Slider, .searchable, and overlay patter","description":"# SwiftUI Layout & Components\n\nLayout 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.\n\n## Contents\n\n- [Layout Fundamentals](#layout-fundamentals)\n- [Grid Layouts](#grid-layouts)\n- [List Patterns](#list-patterns)\n- [ScrollView](#scrollview)\n- [Form and Controls](#form-and-controls)\n- [Searchable](#searchable)\n- [Overlay and Presentation](#overlay-and-presentation)\n- [Common Mistakes](#common-mistakes)\n- [Review Checklist](#review-checklist)\n- [References](#references)\n\n## Layout Fundamentals\n\n### Standard Stacks\n\nUse `VStack`, `HStack`, and `ZStack` for small, fixed-size content. They render all children immediately.\n\n```swift\nVStack(alignment: .leading) {\n    Text(title).font(.headline)\n    Text(subtitle).font(.subheadline).foregroundStyle(.secondary)\n}\n```\n\n### Lazy Stacks\n\nUse `LazyVStack` and `LazyHStack` inside `ScrollView` for large or dynamic collections. They create child views on demand as they scroll into view.\n\n```swift\nScrollView {\n    LazyVStack {\n        ForEach(items) { item in\n            ItemRow(item: item)\n        }\n    }\n    .padding(.horizontal)\n}\n```\n\n**When to use which:**\n- **Non-lazy stacks:** Small, fixed content (headers, toolbars, forms with few fields)\n- **Lazy stacks:** Large or unknown-size collections, feeds, chat messages\n\n## Grid Layouts\n\nUse `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.\n\n```swift\n// Adaptive grid -- columns adjust to fit\nlet columns = [GridItem(.adaptive(minimum: 120, maximum: 1024))]\n\nLazyVGrid(columns: columns) {\n    ForEach(items) { item in\n        ThumbnailView(item: item)\n            .aspectRatio(1, contentMode: .fit)\n    }\n}\n```\n\n```swift\n// Fixed 3-column grid\nlet columns = Array(repeating: GridItem(.flexible(minimum: 100), spacing: 4), count: 3)\n\nLazyVGrid(columns: columns, spacing: 4) {\n    ForEach(items) { item in\n        ThumbnailView(item: item)\n    }\n}\n```\n\nUse `.aspectRatio` for cell sizing. Never place `GeometryReader` inside lazy containers -- it forces eager measurement and defeats lazy loading. Use `.onGeometryChange` (iOS 16+) if you need to read dimensions.\n\nSee [references/grids.md](references/grids.md) for full grid patterns and design choices.\n\n## List Patterns\n\nUse `List` for feed-style content and settings rows where built-in row reuse, selection, and accessibility matter.\n\n```swift\nList {\n    Section(\"General\") {\n        NavigationLink(\"Display\") { DisplaySettingsView() }\n        NavigationLink(\"Haptics\") { HapticsSettingsView() }\n    }\n    Section(\"Account\") {\n        Button(\"Sign Out\", role: .destructive) { }\n    }\n}\n.listStyle(.insetGrouped)\n```\n\n**Key patterns:**\n- `.listStyle(.plain)` for feed layouts, `.insetGrouped` for settings\n- `.scrollContentBackground(.hidden)` + custom background for themed surfaces\n- `.listRowInsets(...)` and `.listRowSeparator(.hidden)` for spacing and separator control\n- Use `ScrollPosition` with `.scrollPosition($scrollPosition)` for scroll-to-top or jump-to-id\n- Use `.refreshable { }` for pull-to-refresh feeds\n- Use `.contentShape(Rectangle())` on rows that should be tappable end-to-end\n\n**iOS 26:** Apply `.scrollEdgeEffectStyle(.soft, for: .top)` for modern scroll edge effects.\n\nSee [references/list.md](references/list.md) for full list patterns including feed lists with scroll-to-top.\n\n## ScrollView\n\nUse `ScrollView` with lazy stacks when you need custom layout, mixed content, or horizontal scrolling.\n\n```swift\nScrollView(.horizontal, showsIndicators: false) {\n    LazyHStack {\n        ForEach(chips) { chip in\n            ChipView(chip: chip)\n        }\n    }\n}\n```\n\n**ScrollPosition:** Enables declarative, bidirectional scroll position tracking and programmatic scrolling.\n\n```swift\n@State private var scrollPosition = ScrollPosition(edge: .bottom)\n\nScrollView {\n    LazyVStack {\n        ForEach(messages) { message in\n            MessageRow(message: message)\n        }\n    }\n    .scrollTargetLayout()\n}\n.scrollPosition($scrollPosition)\n.onChange(of: messages.last?.id) {\n    withAnimation { scrollPosition.scrollTo(edge: .bottom) }\n}\n```\n\nSee [references/scrollview.md](references/scrollview.md) for full `ScrollPosition` patterns including scroll-to-id and user-scroll detection.\n\n**`safeAreaInset(edge:)`** pins content (input bars, toolbars) above the keyboard without affecting scroll layout.\n\n**iOS 26 additions:**\n- `.scrollEdgeEffectStyle(.soft, for: .top)` -- fading edge effect\n- `.backgroundExtensionEffect()` -- mirror/blur at safe area edges (use sparingly, one per screen)\n- `.safeAreaBar(edge:)` -- attach bar views that integrate with scroll effects\n\nSee [references/scrollview.md](references/scrollview.md) for full scroll patterns and iOS 26 edge effects.\n\n## Form and Controls\n\n### Form\n\nUse `Form` for structured settings and input screens. Group related controls into `Section` blocks.\n\n```swift\nForm {\n    Section(\"Notifications\") {\n        Toggle(\"Mentions\", isOn: $prefs.mentions)\n        Toggle(\"Follows\", isOn: $prefs.follows)\n    }\n    Section(\"Appearance\") {\n        Picker(\"Theme\", selection: $theme) {\n            ForEach(Theme.allCases, id: \\.self) { Text($0.title).tag($0) }\n        }\n        Slider(value: $fontScale, in: 0.5...1.5, step: 0.1)\n    }\n}\n.formStyle(.grouped)\n.scrollContentBackground(.hidden)\n```\n\nUse `@FocusState` to manage keyboard focus in input-heavy forms. Wrap in `NavigationStack` only when presented standalone or in a sheet.\n\n### Controls\n\n| Control | Usage |\n|---------|-------|\n| `Toggle` | Boolean preferences |\n| `Picker` | Discrete choices; `.segmented` for 2-4 options |\n| `Slider` | Numeric ranges with visible value label |\n| `DatePicker` | Date/time selection |\n| `TextField` | Text input with `.keyboardType`, `.textInputAutocapitalization` |\n\nBind controls directly to `@State`, `@Binding`, or `@AppStorage`. Group related controls in `Form` sections. Use `.disabled(...)` to reflect locked or inherited settings. Use `Label` inside toggles to combine icon + text when it adds clarity.\n\n```swift\n// Toggle sections\nForm {\n  Section(\"Notifications\") {\n    Toggle(\"Mentions\", isOn: $preferences.notificationsMentionsEnabled)\n    Toggle(\"Follows\", isOn: $preferences.notificationsFollowsEnabled)\n  }\n}\n\n// Slider with value text\nSection(\"Font Size\") {\n  Slider(value: $fontSizeScale, in: 0.5...1.5, step: 0.1)\n  Text(\"Scale: \\(String(format: \"%.1f\", fontSizeScale))\")\n}\n\n// Picker for enums\nPicker(\"Default Visibility\", selection: $visibility) {\n  ForEach(Visibility.allCases, id: \\.self) { option in\n    Text(option.title).tag(option)\n  }\n}\n```\n\nAvoid `.pickerStyle(.segmented)` for large sets; use menu or inline styles. Don't hide labels for sliders; always show context.\n\nSee [references/form.md](references/form.md) for full form examples.\n\n## Searchable\n\nAdd native search UI with `.searchable`. Use `.searchScopes` for multiple modes and `.task(id:)` for debounced async results.\n\n```swift\n@MainActor\nstruct ExploreView: View {\n  @State private var searchQuery = \"\"\n  @State private var searchScope: SearchScope = .all\n  @State private var isSearching = false\n  @State private var results: [SearchResult] = []\n\n  var body: some View {\n    List {\n      if isSearching {\n        ProgressView()\n      } else {\n        ForEach(results) { result in\n          SearchRow(result: result)\n        }\n      }\n    }\n    .searchable(\n      text: $searchQuery,\n      placement: .navigationBarDrawer(displayMode: .always),\n      prompt: Text(\"Search\")\n    )\n    .searchScopes($searchScope) {\n      ForEach(SearchScope.allCases, id: \\.self) { scope in\n        Text(scope.title)\n      }\n    }\n    .task(id: searchQuery) {\n      await runSearch()\n    }\n  }\n\n  private func runSearch() async {\n    guard !searchQuery.isEmpty else {\n      results = []\n      return\n    }\n    isSearching = true\n    defer { isSearching = false }\n    try? await Task.sleep(for: .milliseconds(250))\n    results = await fetchResults(query: searchQuery, scope: searchScope)\n  }\n}\n```\n\nShow a placeholder when search is empty. Debounce input to avoid overfetching. Keep search state local to the view. Avoid running searches for empty strings.\n\n## Overlay and Presentation\n\nUse `.overlay(alignment:)` for transient UI (toasts, banners) without affecting layout.\n\n```swift\nstruct AppRootView: View {\n  @State private var toast: Toast?\n\n  var body: some View {\n    content\n      .overlay(alignment: .top) {\n        if let toast {\n          ToastView(toast: toast)\n            .transition(.move(edge: .top).combined(with: .opacity))\n            .onAppear {\n              Task {\n                try? await Task.sleep(for: .seconds(2))\n                withAnimation { self.toast = nil }\n              }\n            }\n        }\n      }\n  }\n}\n```\n\nPrefer overlays for transient UI rather than embedding in layout stacks. Use transitions and short auto-dismiss timers. Keep overlays aligned to a clear edge (`.top` or `.bottom`). Avoid overlays that block all interaction unless explicitly needed. Don't stack many overlays; use a queue or replace the current toast.\n\n**fullScreenCover:** Use `.fullScreenCover(item:)` for immersive presentations that cover the entire screen (media viewers, onboarding flows).\n\n## Common Mistakes\n\n1. Using non-lazy stacks for large collections -- causes all children to render immediately\n2. Placing `GeometryReader` inside lazy containers -- defeats lazy loading\n3. Using array indices as `ForEach` IDs -- causes incorrect diffing and UI bugs\n4. Nesting scroll views of the same axis -- causes gesture conflicts\n5. Heavy custom layouts inside `List` rows -- use `ScrollView` + `LazyVStack` instead\n6. Missing `.contentShape(Rectangle())` on tappable rows -- tap area is text-only\n7. Hard-coding frame dimensions for sheets -- use `.presentationSizing` instead\n8. Running searches on empty strings -- always guard against empty queries\n9. Mixing `List` and `ScrollView` in the same hierarchy -- gesture conflicts\n10. Using `.pickerStyle(.segmented)` for large option sets -- use menu or inline styles\n11. Hard-coding `spacing:` on stacks and grids by default -- omit to get platform-adaptive spacing; only specify for intentional tight (0–4pt) or wide gaps\n\n## Review Checklist\n\n- [ ] `LazyVStack`/`LazyHStack` used for large or dynamic collections\n- [ ] Stable `Identifiable` IDs on all `ForEach` items (not array indices)\n- [ ] No `GeometryReader` inside lazy containers\n- [ ] `List` style matches context (`.plain` for feeds, `.insetGrouped` for settings)\n- [ ] `Form` used for structured input screens (not custom stacks)\n- [ ] `.searchable` debounces input with `.task(id:)`\n- [ ] `.refreshable` added where data source supports pull-to-refresh\n- [ ] Overlays use transitions and auto-dismiss timers\n- [ ] `.contentShape(Rectangle())` on tappable rows\n- [ ] `@FocusState` manages keyboard focus in forms\n- [ ] Stack/grid `spacing:` omitted unless a specific value is required\n\n## References\n\n- Grid patterns: [references/grids.md](references/grids.md)\n- List and section patterns: [references/list.md](references/list.md)\n- ScrollView and lazy stacks: [references/scrollview.md](references/scrollview.md)\n- Form patterns: [references/form.md](references/form.md)\n- Architecture and state management: see `swiftui-patterns` skill\n- Navigation patterns: see `swiftui-navigation` skill","tags":["swiftui","layout","components","swift","ios","skills","dpearson2699","accessibility","agent-skills","ai-coding","apple","claude-code"],"capabilities":["skill","source-dpearson2699","skill-swiftui-layout-components","topic-accessibility","topic-agent-skills","topic-ai-coding","topic-apple","topic-claude-code","topic-codex-skills","topic-cursor-skills","topic-ios","topic-ios-development","topic-liquid-glass","topic-localization","topic-mapkit"],"categories":["swift-ios-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/dpearson2699/swift-ios-skills/swiftui-layout-components","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add dpearson2699/swift-ios-skills","source_repo":"https://github.com/dpearson2699/swift-ios-skills","install_from":"skills.sh"}},"qualityScore":"0.700","qualityRationale":"deterministic score 0.70 from registry signals: · indexed on github topic:agent-skills · 599 github stars · SKILL.md body (11,547 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T18:53:45.688Z","embedding":null,"createdAt":"2026-04-18T20:33:50.985Z","updatedAt":"2026-05-18T18:53:45.688Z","lastSeenAt":"2026-05-18T18:53:45.688Z","tsv":"'-4':710 '0':663,1244 '0.1':671,790 '0.5':668,787 '0.title':661 '1':278,1103 '1.5':669,788 '10':1208 '100':293 '1024':266 '11':1221 '120':264 '16':332 '17':74 '1f':795 '2':709,1030,1118 '250':946 '26':49,453,578,617 '3':283,297,1127 '4':295,302,1140 '4pt':1245 '5':1151 '6':1162 '6.3':52 '7':1175 '8':1186 '9':1197 'access':369 'account':382 'across':241 'action':25 'ad':1300 'adapt':235,253,262,1237 'add':760,843 'addit':579 'adjust':256 'affect':574,991 'align':145,984,1008,1055 'alway':832,908,1192 'app':46 'appear':651 'appli':454 'approotview':995 'appstorag':735 'architectur':1358 'area':591,1170 'array':288,1129,1267 'aspectratio':277,311 'async':859,930 'attach':600 'auto':1050,1314 'auto-dismiss':1049,1313 'avoid':815,964,973,1063 'await':925,942,948,1026 'axi':1147 'background':403 'backgroundextensioneffect':587 'backward':70 'backward-compat':69 'banner':989 'bar':568,601 'bidirect':511 'bind':728,733 'block':637,1066 'bodi':887,1003 'boolean':702 'bottom':525,545,1062 'bug':1139 'build':5 'built':363 'built-in':362 'button':383 'caus':1112,1134,1148 'cell':313 'chat':219 'checklist':117,120,1250 'child':172 'children':141,1114 'chip':502,503,506,507 'chipview':505 'choic':348,706 'clariti':761 'clear':1058 'code':1178,1224 'collect':169,217,1111,1258 'column':236,246,250,255,260,268,269,284,287,299,300 'combin':755,1020 'common':111,114,1101 'common-mistak':113 'compat':71 'compon':4,39,42 'conflict':1150,1207 'contain':320,1123,1273 'content':77,137,203,357,491,566,1006 'contentmod':279 'contentshap':440,1164,1317 'context':834,1277 'control':16,63,97,101,415,622,634,698,699,729,738 'count':251,296 'cover':17,53,1093 'creat':171 'current':1083 'custom':402,488,1153,1291 'data':1302 'date/time':720 'datepick':719 'debounc':858,961,1294 'declar':510 'default':801,1231 'defeat':326,1124 'defer':938 'demand':175 'dens':231 'design':347 'destruct':387 'detect':562 'devic':242 'dif':1136 'dimens':338,1180 'direct':730 'disabl':743 'discret':705 'dismiss':1051,1315 'display':376 'displaymod':907 'displaysettingsview':377 'dynam':168,1257 'eager':323 'edg':462,524,544,564,585,592,599,618,1018,1059 'effect':463,586,607,619 'els':894,933 'embed':1041 'empti':960,977,1190,1195 'enabl':509 'end':449,451 'end-to-end':448 'entir':1095 'enum':799 'exampl':841 'explicit':1070 'exploreview':864 'fade':584 'fals':499,880,940 'feed':218,355,395,438,472,1280 'feed-styl':354 'fetchresult':949 'field':209 'fit':258,280 'fix':135,202,249,282 'fixed-s':134 'flexibl':245,291 'flow':1100 'focus':681,1325 'focusst':677,1322 'follow':647,773 'font':149,153,781 'fontscal':666 'fontsizescal':785,796 'forc':322 'foreach':184,270,303,501,528,656,805,895,914,1132,1264 'foregroundstyl':155 'form':14,29,62,95,99,206,620,623,625,639,686,740,765,840,1284,1327,1354 'form-and-control':98 'format':794 'formstyl':672 'frame':1179 'full':343,468,550,612,839 'fullscreencov':1085,1087 'func':928 'fundament':79,82,124 'galleri':229 'gap':1248 'general':374 'geometryread':317,1120,1270 'gestur':1149,1206 'get':1234 'grid':10,56,83,86,221,254,285,344,1229,1338 'grid-layout':85 'griditem':261,290 'group':632,673,736 'guard':931,1193 'haptic':379 'hapticssettingsview':380 'hard':1177,1223 'hard-cod':1176,1222 'header':204 'headlin':150 'heavi':685,1152 'hidden':401,410,675 'hide':828 'hierarchi':1205 'horizont':192,493,497 'hstack':129 'icon':226,756 'id':430,541,557,658,807,856,916,923,1133,1261,1298 'identifi':1260 'immedi':142,1117 'immers':1090 'includ':471,553 'incorrect':1135 'indic':1130,1268 'inherit':748 'inlin':824,1219 'input':567,630,684,724,962,1288,1295 'input-heavi':683 'insetgroup':389,397,1281 'insid':163,318,752,1121,1155,1271 'instead':1161,1185 'integr':604 'intent':1242 'interact':1068 'io':48,73,331,452,577,616 'ison':644,648,770,774 'issearch':879,892,936,939 'item':185,186,189,190,271,272,275,276,304,305,308,309,1088,1265 'itemrow':188 'jump':428 'jump-to-id':427 'keep':966,1053 'key':390 'keyboard':572,680,1324 'keyboardtyp':726 'label':718,751,829 'larg':166,212,819,1110,1213,1255 'layout':3,7,38,40,57,78,81,84,87,123,222,238,396,489,576,992,1043,1154 'layout-fundament':80 'lazi':157,199,210,319,327,483,1107,1122,1125,1272,1350 'lazyhstack':162,500,1252 'lazyvgrid':224,267,298 'lazyvgrid/lazyhgrid':19 'lazyvstack':160,183,527,1160,1251 'lead':146 'let':259,286,1011 'list':11,20,58,88,91,349,352,372,469,473,890,1156,1199,1274,1342 'list-pattern':90 'listrowinset':407 'listrowsepar':409 'liststyl':388,392 'load':328,1126 'local':969 'lock':746 'mainactor':862 'manag':679,1323,1361 'mani':1075 'match':1276 'matter':370 'maximum':265 'measur':324 'media':228,1097 'mention':643,769 'menu':822,1217 'messag':220,529,530,533,534 'messagerow':532 'messages.last':540 'millisecond':945 'minimum':263,292 'mirror/blur':588 'miss':1163 'mistak':112,115,1102 'mix':490,1198 'mode':853 'modern':460 'move':1017 'multipl':852 'nativ':844 'navig':1367,1372 'navigationbardraw':906 'navigationlink':375,378 'navigationstack':689 'need':335,487,1071 'nest':1141 'never':315 'nil':1033 'non':198,1106 'non-lazi':197,1105 'note':76 'notif':641,767 'numer':713 'omit':1232,1330 'onappear':1023 'onboard':1099 'onchang':538 'one':595 'ongeometrychang':330 'opac':1022 'option':711,809,814,1214 'option.title':812 'overfetch':965 'overlay':35,66,104,108,979,983,1007,1035,1054,1064,1076,1309 'overlay-and-present':107 'pad':191 'patter':36 'pattern':43,59,67,89,92,345,350,391,470,552,614,1339,1345,1355,1365,1368 'per':596 'picker':227,652,704,797,800 'pickerstyl':816,1210 'pin':565 'place':316,1119 'placehold':956 'placement':905 'plain':393,1278 'platform':1236 'platform-adapt':1235 'posit':513 'prefer':703,1034 'preferences.notificationsfollowsenabled':775 'preferences.notificationsmentionsenabled':771 'prefs.follows':649 'prefs.mentions':645 'present':106,110,692,981,1091 'presentations':1184 'privat':520,867,871,877,882,927,998 'programmat':516 'progressview':893 'prompt':909 'pull':435,1306 'pull-to-refresh':434,1305 'queri':950,1196 'queue':1079 'rang':714 'rather':1039 'read':337 'rectangl':441,1165,1318 'refer':121,122,1337 'references/form.md':836,837,1356,1357 'references/grids.md':340,341,1340,1341 'references/list.md':465,466,1346,1347 'references/scrollview.md':547,548,609,610,1352,1353 'reflect':745 'refresh':432,437,1299,1308 'relat':633,737 'render':139,1116 'repeat':289 'replac':1081 'requir':1336 'result':860,884,896,897,900,901,934,947 'return':935 'reus':366 'review':116,119,1249 'review-checklist':118 'role':386 'row':360,365,443,1157,1168,1321 'run':974,1187 'runsearch':926,929 'safe':590 'safeareabar':598 'safeareainset':563 'scale':240,792 'scope':918,952 'scope.title':921 'screen':597,631,1096,1289 'scroll':12,60,178,423,461,476,494,512,517,555,561,575,606,613,1142 'scroll-to-id':554 'scroll-to-top':422,475 'scrollcontentbackground':400,674 'scrolledgeeffectstyl':455,580 'scrollposit':28,417,419,420,508,522,523,536,537,551 'scrollposition.scrollto':543 'scrolltargetlayout':535 'scrollview':26,93,94,164,182,479,481,496,526,1159,1201,1348 'search':64,845,911,958,967,975,1188 'searchabl':33,102,103,842,848,902,1293 'searchqueri':869,904,924,951 'searchquery.isempty':932 'searchresult':885 'searchrow':899 'searchscop':850,873,874,912,913,953 'searchscope.allcases':915 'second':1029 'secondari':156 'section':22,373,381,636,640,650,741,764,766,780,1344 'see':339,464,546,608,835,1362,1369 'segment':707,817,1211 'select':233,367,654,721,803 'self':659,808,917 'self.toast':1032 'separ':414 'set':359,399,628,749,820,1215,1283 'sheet':697,1182 'short':1048 'show':833,954 'showsind':498 'sign':384 'size':136,216,243,314,782 'skill':1366,1373 'skill-swiftui-layout-components' 'slider':664,712,776,783,831 'small':133,201 'soft':456,581 'sourc':1303 'source-dpearson2699' 'space':294,301,412,1225,1238,1329 'spare':594 'specif':1333 'specifi':1240 'stabl':1259 'stack':9,54,126,158,200,211,484,1044,1074,1108,1227,1292,1351 'stack/grid':1328 'standalon':693 'standard':125 'state':519,732,866,870,876,881,968,997,1360 'step':670,789 'string':793,978,1191 'struct':863,994 'structur':627,1287 'style':356,825,1220,1275 'subheadlin':154 'subtitl':152 'support':1304 'surfac':406 'swift':51,143,181,252,281,371,495,518,638,762,861,993 'swiftui':2,6,37,45,1364,1371 'swiftui-layout-compon':1 'swiftui-navig':1370 'swiftui-pattern':1363 'swipe':24 'tag':662,813 'tap':1169 'tappabl':447,1167,1320 'target':47 'task':855,922,1024,1297 'task.sleep':943,1027 'text':147,151,660,723,757,779,791,811,903,910,920,1173 'text-on':1172 'textfield':722 'textinputautocapit':727 'theme':405,653,655 'theme.allcases':657 'thumbnailview':274,307 'tight':1243 'timer':1052,1316 'titl':148 'toast':988,1000,1001,1012,1014,1015,1084 'toastview':1013 'toggl':642,646,701,753,763,768,772 'toggle/picker/slider':32 'toolbar':205,569 'top':425,458,478,583,1009,1019,1060 'topic-accessibility' 'topic-agent-skills' 'topic-ai-coding' 'topic-apple' 'topic-claude-code' 'topic-codex-skills' 'topic-cursor-skills' 'topic-ios' 'topic-ios-development' 'topic-liquid-glass' 'topic-localization' 'topic-mapkit' 'track':514 'transient':986,1037 'transit':1016,1046,1311 'tri':941,1025 'true':937 'ui':846,987,1038,1138 'unknown':215 'unknown-s':214 'unless':75,1069,1331 'usag':700 'use':8,127,159,195,223,234,310,329,351,416,431,439,480,593,624,676,742,750,821,849,982,1045,1077,1086,1104,1128,1158,1183,1209,1216,1253,1285,1310 'user':560 'user-scrol':559 'valid':31 'valu':665,717,778,784,1334 'var':521,868,872,878,883,886,999,1002 'view':13,61,173,180,602,865,889,972,996,1005,1143 'viewer':1098 'visibility.allcases':806 'visibl':716,802,804 'visual':232 'vstack':128,144 'vstack/hstack/zstack':18 'wide':1247 'withanim':542,1031 'without':573,990 'wrap':687 'zstack':131","prices":[{"id":"faaa9250-28c3-4a4b-a3ff-8ae1c38e4b48","listingId":"f0ea460d-54c8-441f-bf4d-b4608fe202a3","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"dpearson2699","category":"swift-ios-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T20:33:50.985Z"}],"sources":[{"listingId":"f0ea460d-54c8-441f-bf4d-b4608fe202a3","source":"github","sourceId":"dpearson2699/swift-ios-skills/swiftui-layout-components","sourceUrl":"https://github.com/dpearson2699/swift-ios-skills/tree/main/skills/swiftui-layout-components","isPrimary":false,"firstSeenAt":"2026-04-18T22:01:24.641Z","lastSeenAt":"2026-05-18T18:53:45.688Z"},{"listingId":"f0ea460d-54c8-441f-bf4d-b4608fe202a3","source":"skills_sh","sourceId":"dpearson2699/swift-ios-skills/swiftui-layout-components","sourceUrl":"https://skills.sh/dpearson2699/swift-ios-skills/swiftui-layout-components","isPrimary":true,"firstSeenAt":"2026-04-18T20:33:50.985Z","lastSeenAt":"2026-05-07T22:40:32.747Z"}],"details":{"listingId":"f0ea460d-54c8-441f-bf4d-b4608fe202a3","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"dpearson2699","slug":"swiftui-layout-components","github":{"repo":"dpearson2699/swift-ios-skills","stars":599,"topics":["accessibility","agent-skills","ai-coding","apple","claude-code","codex-skills","cursor-skills","ios","ios-development","liquid-glass","localization","mapkit","networking","storekit","swift","swift-concurrency","swiftdata","swiftui","widgetkit","xcode"],"license":"other","html_url":"https://github.com/dpearson2699/swift-ios-skills","pushed_at":"2026-04-26T21:04:17Z","description":"Agent Skills for iOS 26+, Swift 6.3, SwiftUI, and modern Apple frameworks","skill_md_sha":"ae37dcfe7bdeebb74bf68a34d89f4327e621646d","skill_md_path":"skills/swiftui-layout-components/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/dpearson2699/swift-ios-skills/tree/main/skills/swiftui-layout-components"},"layout":"multi","source":"github","category":"swift-ios-skills","frontmatter":{"name":"swiftui-layout-components","description":"Build SwiftUI layouts using stacks, grids, lists, scroll views, forms, and controls. Covers VStack/HStack/ZStack, LazyVGrid/LazyHGrid, List with sections and swipe actions, ScrollView with ScrollPosition, Form with validation, Toggle/Picker/Slider, .searchable, and overlay patterns. Use when building data-driven layouts, collection views, settings screens, search interfaces, or transient overlay UI."},"skills_sh_url":"https://skills.sh/dpearson2699/swift-ios-skills/swiftui-layout-components"},"updatedAt":"2026-05-18T18:53:45.688Z"}}