skip to Main Content

When attempting to replicate the behaviour of Finder and SF Symbols in a macOS application using SwiftUI, I encountered difficulties with DisclosureGroup.

Here is my current code:

import SwiftUI

struct SidebarView: View {
    @State private var companiesExpanded = false
    
    var body: some View {
        VStack{
            DisclosureGroup(isExpanded: $companiesExpanded) {
                NavigationLink(destination: CompaniesLibraryView()) {
                    Label("Water", systemImage: "drop")
                }
                NavigationLink(destination: CompaniesLibraryView()) {
                    Label("Sewage", systemImage: "toilet")
                }
                NavigationLink(destination: CompaniesLibraryView()) {
                    Label("Electricity", systemImage: "bolt")
                }
            } label: {
                Text("Companies")
                    .font(.subheadline)
                    .fontWeight(.semibold)
            }
        }
    }
}

In this code, I attempted to use the DisclosureGroup to create collapsible sections in the sidebar, similar to what is seen in Finder and SF Symbols. However, the result is not the same. The DisclosureGroup does collapse the items, but it lacks the visual appearance and behaviour of Finder’s sidebar.

I would greatly appreciate any help to achieve the desired behaviour. Thank you in advance for your assistance.

Finder collapse items (Goal):
enter image description here

SF Symbols (Goal):
enter image description here

My App (Actual):
enter image description here

2

Answers


  1. Here’s a proposal to fix some of the issues.

    • align Label left with a .frame(..), .infinity will make all Labels take the space of the whole sidebar.

    • Label color .primary

    • give a little padding for the label

    • label color .secondary

    • stabilize the animation with a Spacer at the bottom

        import SwiftUI
      
        struct SidebarView: View {
        @State private var companiesExpanded = true
      
        var body: some View {
            VStack {
                DisclosureGroup(isExpanded: $companiesExpanded) {
                    NavigationLink(destination: CompaniesLibraryView()) {
                        Label("Water", systemImage: "drop")
                            .foregroundColor(.primary)
                            .frame(maxWidth: .infinity, alignment: .leading)
                    }
                    NavigationLink(destination: CompaniesLibraryView()) {
                        Label("Sewage", systemImage: "star")
                            .foregroundColor(.primary)
                            .frame(maxWidth: .infinity, alignment: .leading)
                    }
                    NavigationLink(destination: CompaniesLibraryView()) {
                        Label("Electricity", systemImage: "bolt")
                            .foregroundColor(.primary)
                            .frame(maxWidth: .infinity, alignment: .leading)
                    }
                } label: {
                    Text("Companies")
                        .font(.subheadline)
                        .fontWeight(.semibold)
                        .foregroundColor(.secondary)
                        .padding(5)
                }
            }
            Spacer()
        }
        }
      

    You can have more control with a custom DisclosureGroupStyle.

    For example:
    How to make a custom DisclosureGroup (drop down) in SwiftUI?

    Login or Signup to reply.
  2. By adding .frame with alignment: .top to the DisclosureGroup(), the DisclosureGroup() will always be pushed to the top and won’t be centred again after closing.

    struct SidebarView: View {
        @State private var companiesExpanded = false
        
        var body: some View {
            VStack{
                DisclosureGroup(isExpanded: $companiesExpanded) {
                    NavigationLink(destination: CompaniesLibraryView()) {
                        Label("Water", systemImage: "drop")
                    }
                    NavigationLink(destination: CompaniesLibraryView()) {
                        Label("Sewage", systemImage: "toilet")
                    }
                    NavigationLink(destination: CompaniesLibraryView()) {
                        Label("Electricity", systemImage: "bolt")
                    }
                } label: {
                    Text("Companies")
                        .font(.subheadline)
                        .fontWeight(.semibold)
                }
                .frame(height: 100, alignment: .top) // Push DisclosureGroup() to the top
                .background(.gray) // To see frame
            }
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search