TechnologiesSwiftUIControls and Style Configurations

DisclosureGroupStyleConfiguration struct

iOSmacOStvOSwatchOSvisionOS✓ renders

The properties of a disclosure group instance.

How it works

A DisclosureGroupStyleConfiguration is the bundle of properties SwiftUI hands to a custom disclosure group style when it draws each disclosure group. When you conform a type to DisclosureGroupStyle, the framework calls your makeBody(configuration:) with one of these values, giving you the group's label, its hidden content, and its current expansion state without exposing the underlying view types. Reach for it whenever the built-in disclosure appearance isn't enough and you want to design the header, the chevron, and the reveal animation yourself while letting SwiftUI keep ownership of the data.

  1. Receive the configuration in makeBody(configuration:)

    A DisclosureGroupStyle has one requirement, makeBody(configuration:), and its parameter is a DisclosureGroupStyleConfiguration (surfaced through the Configuration type alias). SwiftUI invokes it once per disclosure group and expects you to return some View. In CardDisclosureStyle, func makeBody(configuration: Configuration) -> some View is where the whole custom layout is assembled.

  2. Place the header with configuration.label

    The label property is a type-erased view holding whatever title the disclosure group was given. You position and decorate it but never construct it. The example drops configuration.label into an HStack and styles it with .font(.headline), so the group's title renders inside your own header chrome.

  3. Read and flip the state with configuration.isExpanded

    isExpanded is a Bool binding that reflects whether the group is open and lets you change it. Reading it drives conditional UI; writing it toggles the group. Here configuration.isExpanded chooses between "chevron.down" and "chevron.right" for the indicator, and the button's action calls configuration.isExpanded.toggle() inside withAnimation to expand or collapse on tap.

  4. Reveal the body with configuration.content

    The content property is the type-erased collapsible payload of the group. You decide when and how it appears. The example shows configuration.content only when configuration.isExpanded is true and insets it with .padding(.leading, 8), so the hidden rows slide in beneath the header you built.

  5. Attach the style with disclosureGroupStyle(_:)

    A custom style does nothing until you apply it to a DisclosureGroup with the disclosureGroupStyle(_:) modifier, which propagates to disclosure groups in that view subtree. In the example .disclosureGroupStyle(CardDisclosureStyle()) is what routes the "Wi-Fi Networks" group through the configuration-driven body above.

Try it — In makeBody, change Image(systemName: configuration.isExpanded ? "chevron.down" : "chevron.right") to swap a fixed Image(systemName: "plus") for "minus" and watch the indicator track configuration.isExpanded as you tap the header.

Example & preview

Press Run live & edit to compile it in your browser — then edit the Swift on the left and the preview re-renders live.

DisclosureGroupStyleConfiguration.swift
struct DisclosureGroupStyleConfigurationDemo: View {
    struct CardDisclosureStyle: DisclosureGroupStyle {
        func makeBody(configuration: Configuration) -> some View {
            VStack(alignment: .leading, spacing: 8) {
                Button {
                    withAnimation { configuration.isExpanded.toggle() }
                } label: {
                    HStack {
                        configuration.label
                            .font(.headline)
                        Spacer()
                        Image(systemName: configuration.isExpanded ? "chevron.down" : "chevron.right")
                    }
                }
                .buttonStyle(.plain)
                if configuration.isExpanded {
                    configuration.content
                        .padding(.leading, 8)
                }
            }
        }
    }

    @State private var expanded = true

    var body: some View {
        DisclosureGroup("Wi-Fi Networks", isExpanded: $expanded) {
            Text("Home")
            Text("Office")
            Text("Cafe Guest")
        }
        .disclosureGroupStyle(CardDisclosureStyle())
        .padding()
    }
}
Live preview
Wi-Fi Networks Home Office Cafe Guest
Wi-Fi Networks Home Office Cafe Guest
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →