diff --git a/Sources/StorybookKit/Primitives/Book.swift b/Sources/StorybookKit/Primitives/Book.swift index 96faee8..9a78cfc 100644 --- a/Sources/StorybookKit/Primitives/Book.swift +++ b/Sources/StorybookKit/Primitives/Book.swift @@ -35,6 +35,8 @@ public struct Book: BookView, Identifiable { public let title: String public let contents: [Node] + + @State private var isExpandedAll: Bool = false public init( title: String, @@ -78,23 +80,34 @@ public struct Book: BookView, Identifiable { } public var body: some View { - ForEach(contents) { node in - - NodeOutlineGroup(node, children: \.children) { content in - switch content { - case .folder(let folder): - - HStack { - Image.init(systemName: "folder.fill") - Text(folder.title) + Section { + ForEach(contents) { node in + NodeOutlineGroup(expandsAll: isExpandedAll, node, children: \.children) { content in + switch content { + case .folder(let folder): + + HStack { + Image.init(systemName: "folder.fill") + Text(folder.title) + } + + case .page(let page): + page } - - case .page(let page): - page } + + } + } header: { + HStack { + Text(title) + Spacer() + Button("Expand All") { + isExpandedAll.toggle() + } + .font(.caption) } - } + } func allPages() -> [BookPage] { @@ -261,31 +274,52 @@ private struct NodeOutlineGroup: View where Node: Identifiable, C let node: Node let childKeyPath: KeyPath - @State var isExpanded: Bool = true + let expandsAll: Bool + + @State var isExpanded: Bool let content: (Node) -> Content init( + expandsAll: Bool, _ node: Node, children childKeyPath: KeyPath, @ViewBuilder content: @escaping (Node) -> Content ) { + self._isExpanded = .init(wrappedValue: expandsAll) + self.expandsAll = expandsAll self.node = node self.childKeyPath = childKeyPath self.content = content } var body: some View { - if node[keyPath: childKeyPath] != nil { - DisclosureGroup( - isExpanded: $isExpanded, - content: { - ForEach(node[keyPath: childKeyPath]!) { childNode in - NodeOutlineGroup(childNode, children: childKeyPath, content: content) + Group { + if node[keyPath: childKeyPath] != nil { + DisclosureGroup( + isExpanded: $isExpanded, + content: { + ForEach(node[keyPath: childKeyPath]!) { childNode in + NodeOutlineGroup( + expandsAll: expandsAll, + childNode, + children: childKeyPath, + content: content + ) + } + }, + label: { + content(node) } - }, - label: { content(node) }) - } else { - content(node) + ) + + } else { + content(node) + } + } + .onChange(of: expandsAll) { value in + withAnimation(.default) { + isExpanded = value + } } } } diff --git a/Sources/StorybookKit/Primitives/BookPage.swift b/Sources/StorybookKit/Primitives/BookPage.swift index 2d4d9d3..0febc0e 100644 --- a/Sources/StorybookKit/Primitives/BookPage.swift +++ b/Sources/StorybookKit/Primitives/BookPage.swift @@ -98,8 +98,13 @@ public struct BookPage: BookView, Identifiable { }) } label: { LinkLabel(title: title, fileID: fileID, line: line) + .contextMenu(menuItems: { + Text(title) + }) { + destination + } } - + } } diff --git a/Sources/StorybookKit/Storybook.swift b/Sources/StorybookKit/Storybook.swift index 81da8f4..b91247e 100644 --- a/Sources/StorybookKit/Storybook.swift +++ b/Sources/StorybookKit/Storybook.swift @@ -10,10 +10,10 @@ public struct Storybook: View { public var body: some View { StorybookDisplayRootView( bookStore: .init( - book: .init(title: "Storybook") { + book: Book.init(title: "Contents") { if let nodes = Book.allBookPreviews() { - Book(title: "#Preview macro") { + Book(title: "#Preview") { nodes } } diff --git a/Sources/StorybookKit/StorybookDisplayRootView.swift b/Sources/StorybookKit/StorybookDisplayRootView.swift index c8b7087..c0489d7 100644 --- a/Sources/StorybookKit/StorybookDisplayRootView.swift +++ b/Sources/StorybookKit/StorybookDisplayRootView.swift @@ -86,11 +86,7 @@ struct BookContainer: View { Text("History") } - Section { - store.book - } header: { - Text("Contents") - } + store.book } .navigationTitle(store.title)