SwiftUI macOS Target List with Section Row Spacing
SwiftUI macOS Target List with Section Row Spacing
I am trying to build a macOS (14.6) app that uses a combination of List(_:selection:rowContent:)
and Section(isExpanded:content:header:)
, and while it "works", it looks like garbage. When using .plain
, there are list row/section seperators, and even when using .listRowSeparator(.hidden)
or .listSectionSeparator(.hidden)
, there is always one separator that is still visible between the first item and the remaining items.
When I try to use .listStyle(.sidebar)
, it adds its own disclosure indicator, but on the right side of the list row. It's tolerable, though I'd prefer the indicator on the left and not to auto-hide when not being hovered.
The kicker is that regardless of the .listStyle()
used, there seems to be spacing/padding between the sections that cannot be removed. In Apple's infinite wisdom, they added .listRowSpacing()
, but decided macOS shouldn't get to use it.
I am still new to all of this, and would really appreciate any advice on how I can style my UI the way I need it to be. I am using SwiftUI, but if there is another method (maybe UIKit or somthing?), I'm open to suggestion.
Here is my playground code used to generate the screenshots:
import SwiftUI import PlaygroundSupport struct Content: Hashable, Identifiable { var id: Self { self } var header: String var contents: [String] } struct ContentView: View { var contents: [Content] = [ Content(header: "My Section 1", contents: ["Hello", "world"]), Content(header: "My Section 2", contents: ["Foo", "bar"]), Content(header: "My Section 3", contents: ["Help", "Me"]), ] @State private var expanded: Set<Content> = [] @State private var selected: String? var body: some View { NavigationSplitView { List(contents, selection: $selected) { content in Section(isExpanded: Binding<Bool>( get: { return expanded.contains(content) }, set: { expanding in if expanding { expanded.insert(content) } else { expanded.remove(content) } } ), content: { ForEach(content.contents, id: \.self) { data in Text(data) .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading) .border(Color.orange) } }, header: { Text(content.header) .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading) .onTapGesture { if expanded.contains(content) { expanded.remove(content) } else { expanded.insert(content) } } }) .listRowInsets(EdgeInsets( top: 0, leading: -2, bottom: 0, trailing: -14 )) } } detail: { ContentUnavailableView { Label("No selection made", systemImage: "tray") } } .border(Color.gray) } } // Present the view in Playground PlaygroundPage.current.setLiveView(ContentView())
Edit: 3 hours later... I was able to remove the spacing from the section content's items by using listRowInsets(_ insets:)
and removing some of the padding I put in the code. But, I still do not know how to affect the section headers. I've updated the code above, and here's a new screenshot: