I'm currently working on creating an accordion view in SwiftUI, but I've encountered a problem: the default chevron that accompanies the DisclosureGroup appears translucent. I attempted to integrate it into a List, but this approach disrupts my design. Additionally, I tried setting the accent to clear and adding a custom image, but this resulted in misaligned chevron placement — it shifts to the left instead of remaining on the right. Has anyone else experienced this issue and found a solution or workaround?
Also, I should mention that my minimum deployment target is iOS 15.
import SwiftUI
struct ContentView: View {
@State private var isExpanded1 = false
@State private var isExpanded2 = false
@State private var isExpanded3 = false
@State private var isExpanded4 = false
var body: some View {
VStack(alignment: .trailing, spacing: 0) {
// Accordion Section 1
DisclosureGroup(
isExpanded: $isExpanded1,
content: {
Text("Details for Services") // Test content for section 1
},
label: {
accordionLabel(number: "1", title: "Services", isExpanded: isExpanded1)
}
)
.padding(16)
.frame(width: 360, alignment: .top)
.background(Color.white)
// Accordion Section 2
DisclosureGroup(
isExpanded: $isExpanded2,
content: {
Text("Information on Terms") // Test content for section 2
},
label: {
accordionLabel(number: "2", title: "Terms", isExpanded: isExpanded2)
}
)
.padding(16)
.frame(width: 360, alignment: .top)
.background(Color.white)
// Accordion Section 3
DisclosureGroup(
isExpanded: $isExpanded3,
content: {
Text("Payment Options and Details") // Test content for section 3
},
label: {
accordionLabel(number: "3", title: "Payment", isExpanded: isExpanded3)
}
)
.padding(16)
.frame(width: 360, alignment: .top)
.background(Color.white)
// Accordion Section 4
DisclosureGroup(
isExpanded: $isExpanded4,
content: {
Text("Signature Procedures and Guidelines") // Test content for section 4
},
label: {
accordionLabel(number: "4", title: "Signatures", isExpanded: isExpanded4)
}
)
.padding(16)
.frame(width: 360, alignment: .top)
.background(Color.white)
}
}
@ViewBuilder
private func accordionLabel(number: String, title: String, isExpanded: Bool) -> some View {
HStack {
HStack(spacing: 8) {
VStack {
Text(number)
.font(Font.custom("Inter", size: 16).weight(.bold))
.multilineTextAlignment(.center)
.foregroundColor(Color.gray)
}
.frame(width: 24, height: 24, alignment: .center)
.cornerRadius(40)
.overlay(
RoundedRectangle(cornerRadius: 40)
.inset(by: 0.5)
.stroke(Color.gray, lineWidth: 1)
)
Text(title)
.font(Font.custom("Inter", size: 16).weight(.bold))
.foregroundColor(Color.black)
}
Spacer()
// Image(systemName: "chevron.down")
// .rotationEffect(.degrees(isExpanded ? 180 : 0))
// .foregroundColor(.primary)
// .frame(width: 24, height: 24, alignment: .center)
}
}
}
The chevron, like most system controls, will adopt the
tintcolour. You can't alter the opacity afaik, but you can darken it by changing the tint colour.To force it to black you can do:
You can also apply it to the whole view hierarchy to set it for all items at once.
If this isn't sufficient you'll need to create your own custom version of the
DisclosureGroupby using a customDisclosuregroupStyleand applying it to the view hierarchy. Using SF Symbols for the chevron will then allow you full font control over its presentation, so you can make it as large, bold or opaque as your design requires. This will also allow you to condense all your modifiers into one place.You may want to play with the animation to get your desired effect.
You can then apply to your whole view hierarchy and it will configure all the disclosure groups.
In the example note that the
VStackhas been replaced with aListas this provides a far better animation when the group is expanded (this also requires your frame modifier to be removed).[Also, as an aside, look to create an array containing the content for each group and iterate through that, rather than writing each entry out in ints entirety]