Add fourteen skills from Dimillian/Skills, integrate the merged Snowflake and WordPress updates into the maintainer sync, and refresh registry metadata, attributions, walkthrough notes, and the 8.9.0 release notes while keeping validation warnings within budget.
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.