mirror of
https://github.com/Dimillian/Skills.git
synced 2026-03-25 08:55:54 +00:00
Introduces the 'swiftui-ui-patterns' skill to docs/skills.json, providing best practices and example-driven guidance for building SwiftUI views and components. Adds SKILL.md and a comprehensive set of reference files covering TabView, NavigationStack, sheets, forms, controls, grids, overlays, haptics, focus handling, media, matched transitions, split views, and more.
2.7 KiB
2.7 KiB
List and Section
Intent
Use List for feed-style content and settings-style rows where built-in row reuse, selection, and accessibility matter.
Core patterns
- Prefer
Listfor long, vertically scrolling content with repeated rows. - Use
Sectionheaders to group related rows. - Pair with
ScrollViewReaderwhen you need scroll-to-top or jump-to-id. - Use
.listStyle(.plain)for modern feed layouts. - Use
.listStyle(.grouped)for multi-section discovery/search pages where section grouping helps. - Apply
.scrollContentBackground(.hidden)+ a custom background when you need a themed surface. - Use
.listRowInsets(...)and.listRowSeparator(.hidden)to tune row spacing and separators. - Use
.environment(\\.defaultMinListRowHeight, ...)to control dense list layouts.
Example: feed list with scroll-to-top
@MainActor
struct TimelineListView: View {
@Environment(\.selectedTabScrollToTop) private var selectedTabScrollToTop
@State private var scrollToId: String?
var body: some View {
ScrollViewReader { proxy in
List {
ForEach(items) { item in
TimelineRow(item: item)
.id(item.id)
.listRowInsets(.init(top: 12, leading: 16, bottom: 6, trailing: 16))
.listRowSeparator(.hidden)
}
}
.listStyle(.plain)
.environment(\\.defaultMinListRowHeight, 1)
.onChange(of: scrollToId) { _, newValue in
if let newValue {
proxy.scrollTo(newValue, anchor: .top)
scrollToId = nil
}
}
.onChange(of: selectedTabScrollToTop) { _, newValue in
if newValue == 0 {
withAnimation {
proxy.scrollTo(ScrollToView.Constants.scrollToTop, anchor: .top)
}
}
}
}
}
}
Example: settings-style list
@MainActor
struct SettingsView: View {
var body: some View {
List {
Section("General") {
NavigationLink("Display") { DisplaySettingsView() }
NavigationLink("Haptics") { HapticsSettingsView() }
}
Section("Account") {
Button("Sign Out", role: .destructive) {}
}
}
.listStyle(.insetGrouped)
}
}
Design choices to keep
- Use
Listfor dynamic feeds, settings, and any UI where row semantics help. - Use stable IDs for rows to keep animations and scroll positioning reliable.
- Prefer
.contentShape(Rectangle())on rows that should be tappable end-to-end. - Use
.refreshablefor pull-to-refresh feeds when the data source supports it.
Pitfalls
- Avoid heavy custom layouts inside a
Listrow; useScrollView+LazyVStackinstead. - Be careful mixing
Listand nestedScrollView; it can cause gesture conflicts.