Disclosures
A Disclosure represents a single expandable section of content, commonly used to build accordions, FAQs, and progressive disclosure interfaces.
At its simplest, a disclosure consists of a label and some hidden content:
Disclosure("What is Raptor?") {
Text("Raptor is a Swift static site generator.")
}
.border(.secondaryBackground)
.padding()
.cornerRadius(8)
Control whether it starts open with isExpanded, or customize the indicator with disclosureLabelIndicator(_:):
Disclosure("Getting Started", isExpanded: true) {
Text("This section is open by default.")
}
.disclosureLabelIndicator(.chevron)
Custom Labels
For more control over the label content, provide a custom label:
Disclosure {
SettingsView()
} label: {
InlineText("Advanced Settings")
.fontWeight(.bold)
}
This is useful for incorporating icons, formatted text, or composite labels.
Coordinated Disclosure Groups (Accordions)
Group disclosures so that opening one closes the others, creating classic accordion behavior.
Use the matchedTransitionEffect(id:) modifier:
Disclosure("General", isExpanded: true) {
Text("General settings")
}
.matchedTransitionEffect(id: "settings")
Disclosure("Account") {
Text("Account settings")
}
.matchedTransitionEffect(id: "settings")
Styling Disclosure Labels
Disclosure labels are styled using the DisclosureLabelStyle protocol, which responds to different interaction states:
.closed— Default resting state.opened— When content is visible.hovered— Pointer hover state.focused— Keyboard focus state
Creating a Custom DisclosureLabelStyle
Define how the label looks in each interaction phase:
struct MyDisclosureStyle: DisclosureLabelStyle {
func style(content: Content, phase: Phase) -> Content {
switch phase {
case .hovered:
content
.background(.pink)
case .opened:
content
.background(.red)
case .closed:
content
.cornerRadius(8)
.disclosureLabelIndicator(.ellipsis)
}
}
}
Then apply it:
Disclosure {
Text("Raptor is a Swift static site generator.")
.padding(.horizontal, 25)
.padding(.top, 15)
} label: {
InlineText("What is Raptor?")
.fontWeight(.medium)
.padding(.horizontal, 25)
.padding(.vertical, 15)
}
.disclosureLabelStyle(MyDisclosureStyle())
Note: When animating disclosures, use padding instead of margins on the content section. Margins can cause height measurements to change during animation, leading to hitches. Padding produces stable height calculations and smooth transitions.