Section(isExpanded:) bug on macOS?

Running into a problem on macOS 14.0/SwiftUI. In the code below, the first Section(isExpanded:) component works (expands) while the second doesn't. The one that works is the one where the Bool controlling expansion is referenced by another component. The one that doesn't is where the Bool controlling expansion isn't referenced.

Anybody know what's happening in this case or have a workaround (other than the one used in this example)?

    @ObservedObject var foo: Foo

    @State private var isExpanded_1 = true
    @State private var isExpanded_2 = true
    
    var body: some View {
        VStack {
            // This section's expansion works because isExpanded_1 is referenced by another component (Text).
            Text("isSummaryExpanded = \(isExpanded_1.description)")
            Section(isExpanded: $isExpanded_1) {
                Text("Working section")
            }
            header: {
                SummaryHeader(isSummaryExpanded: $isExpanded_1)
            }

            // This section's expansion doesn't work because isExpanded_2 isn't referenced anywhere else.
            Section(isExpanded: $isExpanded_2) {
                Text("Broken section")
            }
            header: {
                SummaryHeader(isSummaryExpanded: $isExpanded_2)
            }
            Spacer()
        }
    }
}

Hi @Belazeebub ,

I see you are using this in a VStack, is there a reason you're not using List? Adding the sidebar style to List should make this work correctly. This code should work perfectly on macOS 14, please let me know if you are seeing different behavior:

struct ContentView: View {
    @State private var isExpanded_1 = true
    @State private var isExpanded_2 = true
    
    var body: some View {
        List {
            Section("Section 1", isExpanded: $isExpanded_1) {
                Text("Working section")
            }
            Section("Section 2", isExpanded: $isExpanded_2) {
                Text("Broken section")
            }
        }
        .listStyle(.sidebar)
    }
}

I used a VStack because I usually associate a List with a homogeneous set of values a.o.t. a VStack which seems to be a more heterogeneous grouping. (I'm still newish to SwiftUI so I try to keep things simple for my own sake.) I tried using a List per your suggestion but retaining the header: and, interestingly, the "toggling" of both isExpanded bools now work but the Section bodies don't collapse. Also, the second Section looks to be "graphically subordinate" with relation to the first Section (i.e. the first Section's header divider is drawn all the way to the left edge of the containing view but the second Section's divider is drawn indented - go figure).

        List {
            Section(isExpanded: $isExpanded_1) {
                Text("Working section")
            }
            header: {
                SummaryHeader(isSummaryExpanded: $isExpanded_1)
            }

            Section(isExpanded: $isExpanded_2) {
                Text("Broken section")
            }
            header: {
                SummaryHeader(isSummaryExpanded: $isExpanded_2)
            }
            Spacer()
        }

FWIW, I want/need to use header: because it contains the disclosure chevron that toggles the isExpanded bool. FWIW#2, I'm using this instead of a DisclosureGroup because DisclosureGroups seem to have their own set of problems.

Hmm, the reply won't fit in 500 characters so I have to reply out-of-line.

FWIW, I'm not seeing a disclosure chevron with .listStyle(.sidebar).

Here's the code for SummaryHeader and Expander:

struct Expander: View {
    @Binding var isExpanded: Bool
    
    var body: some View {
        Button {
            isExpanded.toggle()
        } label: {
            Image(systemName: (isExpanded) ? "chevron.down" : "chevron.right")
        }
        .buttonStyle(PlainButtonStyle())
        .padding(EdgeInsets(top: 6, leading: 6, bottom: 0, trailing: 6))
        .accessibilityLabel(Text((isExpanded) ? "Show" : "Hide"))
    }
}

struct SummaryHeader: View {
    @Binding var isSummaryExpanded: Bool
    
    var body: some View {
        HStack {
            Expander(isExpanded: $isSummaryExpanded)
            Text("Summary")
                .font(.headline)
            Text(isSummaryExpanded ? "expanded" : "collapsed")
            Spacer()
        }
    }
}

FWIW, here's what I see when I use List {}.listStyle(.sidebar):

It's a little hard to see, I've attached a photo of it with me hovering over the section title which shows the chevron all the way on the right side of the list. I'll take a look at the code you posted, you're saying you'd expect another part to also collapse?

Here's an interesting little gotcha. If I initialize the expansion bools to FALSE, like so:

    @State private var isExpanded_1 = false
    @State private var isExpanded_2 = false

then the Sections don't expand although the chevrons toggle.

By the way, what OS version are you running?

Section(isExpanded:) bug on macOS?
 
 
Q