The Info tab fills in — the board's vital statistics in two honest registers

Model facts off the live snapshot (Lanes, Cards with the trash's freight as a
quiet tail, Attachments — the welcome-count live-only rule) and disk facts off
one background whole-folder walk (File, Files, Size, Created, Modified — .git
and .trash included, so the rows agree with Finder's Get Info), with a Reveal
in Finder link as the door to the folder the rows describe.

Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
2026-08-07 13:58:15 -04:00
parent c21c53be9c
commit 5779da2b6c
4 changed files with 386 additions and 22 deletions
+18 -21
View File
@@ -6,9 +6,10 @@ import SwiftUI
///
/// **Restructuring in progress (2026-08-07): the popover is going tabbed.** The symbol/name header
/// stays at the top; below it sit three tabs **Info**, **Background**, **Git** each a settings
/// surface for one aspect of board configuration, each deliberately *empty* today: their contents
/// are to be settled one per dedicated design session. The former body the embedded style editor
/// and the mode-aware git section is unrendered for the interim but parked in this file (see the
/// surface for one aspect of board configuration, each settled in its own dedicated design session.
/// **Info is settled** (same day `BoardInfoTabView`, the metrics dossier); Background and Git
/// remain deliberately empty until theirs. The former body the embedded style editor and the
/// mode-aware git section is unrendered for the interim but parked in this file (see the
/// "Parked" marks below), because its pure seams (`BoardGitSection`, the posture notes,
/// `BoardSettingsAvailability`'s caller) are settled design and will rehome into the tabs as those
/// sessions rule.
@@ -256,9 +257,9 @@ func boardInfoTitlebarAccessory(
// MARK: - Tabs
/// The popover's three aspects, one tab each (03-board-ui.md § Board popover, the 2026-08-07 tab
/// restructure): **Info**, **Background**, **Git**. All three are placeholders empty on purpose
/// until each gets its dedicated design session; the enum exists now so the popover's shape is the
/// tabs' from day one and each session only has to fill its case in.
/// restructure): **Info**, **Background**, **Git**. Info is settled (`BoardInfoTabView`);
/// Background and Git are placeholders empty on purpose until each gets its dedicated design
/// session, which then only has to fill its case in.
enum BoardInfoTab: String, CaseIterable, Identifiable {
case info = "Info"
@@ -374,22 +375,18 @@ struct BoardInfoView: View {
.padding(.horizontal, inset)
.padding(.top, inset)
// Each tab's surface empty today, on purpose: the contents are each their own design
// session's to settle (the file-top note). The switch is already the shape those
// sessions will fill in, and the fixed placeholder height is exactly that a
// placeholder, so the popover reads as a surface awaiting content rather than a
// collapsed sliver; it goes the moment any tab has real content to size itself by.
Group {
switch tab {
case .info:
EmptyView()
case .background:
EmptyView()
case .git:
EmptyView()
}
// The selected tab's surface. Info is settled (2026-08-07 `BoardInfoTabView`);
// Background and Git stay placeholders until their own sessions, holding a fixed
// height so an empty tab reads as a surface awaiting content rather than a collapsed
// sliver `Color.clear`, because an `EmptyView` inside a frame renders nothing at all.
switch tab {
case .info:
BoardInfoTabView(store: store, inset: inset)
case .background:
Color.clear.frame(height: 120)
case .git:
Color.clear.frame(height: 120)
}
.frame(maxWidth: .infinity, minHeight: 120)
}
// The style editor's popover width, taken from the editor rather than restated: the embed
// below must lay out here exactly as it does at its other two anchors, and that number is