The board popover goes tabbed — Info, Background, Git, three empty rooms awaiting their own sessions
The symbol/name header keeps the top; below it a segmented tab bar replaces the styling embed and the git section, both parked in-file — their seams are settled, test-pinned design, and the tab sessions rehome surfaces, not rulings. Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
@@ -53,6 +53,8 @@ One **style editor** component — a background palette grid and a curated symbo
|
|||||||
|
|
||||||
## Board popover
|
## Board popover
|
||||||
|
|
||||||
|
**Restructure 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 the settings surface for one aspect of board configuration, each to be designed in its own dedicated session (all three are empty placeholders until then). The bullets below describe the popover's pre-tab content; what of it rehomes into which tab — and where the embedded style editor lands — is those sessions' to settle. The rulings inside the bullets (rename semantics, the git postures, the popover/sheet split) stand; only their placement is in motion.
|
||||||
|
|
||||||
The window-title widget opens the **board popover** — the one board-level surface, hosting:
|
The window-title widget opens the **board popover** — the one board-level surface, hosting:
|
||||||
|
|
||||||
- **Board rename** (settled: this function stays in-app, unlike the pathfinder which dropped it with the inspector). Rename edits the board's frontmatter `title` only — the folder is never renamed by the app; the Finder document name is Finder's to change (01-storage-format.md's board-naming rule). A foreign rename landing while the popover is open resyncs the field from the snapshot only while the field is unfocused — a focused field keeps the user's keystrokes, the dirty-buffer courtesy applied here (settled).
|
- **Board rename** (settled: this function stays in-app, unlike the pathfinder which dropped it with the inspector). Rename edits the board's frontmatter `title` only — the folder is never renamed by the app; the Finder document name is Finder's to change (01-storage-format.md's board-naming rule). A foreign rename landing while the popover is open resyncs the field from the snapshot only while the field is unfocused — a focused field keeps the user's keystrokes, the dirty-buffer courtesy applied here (settled).
|
||||||
|
|||||||
@@ -4,11 +4,14 @@ import SwiftUI
|
|||||||
/// **The board popover** — "the one board-level surface" (03-board-ui.md § Board popover), and the
|
/// **The board popover** — "the one board-level surface" (03-board-ui.md § Board popover), and the
|
||||||
/// widget in the window's titlebar that opens it.
|
/// widget in the window's titlebar that opens it.
|
||||||
///
|
///
|
||||||
/// Two sections, in the design's own order: the board rename and the embedded style editor aimed at
|
/// **Restructuring in progress (2026-08-07): the popover is going tabbed.** The symbol/name header
|
||||||
/// the board. A third, contextual note joins them only on a board that carries an inert `.git` — see
|
/// stays at the top; below it sit three tabs — **Info**, **Background**, **Git** — each a settings
|
||||||
/// `BoardGitNote` for the wording and why base's posture there is a quiet signpost rather than a
|
/// surface for one aspect of board configuration, each deliberately *empty* today: their contents
|
||||||
/// standing section (12-editions.md § Base and `.git`, ruled 2026-07-27, superseding the earlier
|
/// are to be settled one per dedicated design session. The former body — the embedded style editor
|
||||||
/// reserved-slot placeholder this file once carried).
|
/// 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.
|
||||||
///
|
///
|
||||||
/// ### One home, deliberately
|
/// ### One home, deliberately
|
||||||
///
|
///
|
||||||
@@ -250,14 +253,30 @@ func boardInfoTitlebarAccessory(
|
|||||||
return controller
|
return controller
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
enum BoardInfoTab: String, CaseIterable, Identifiable {
|
||||||
|
|
||||||
|
case info = "Info"
|
||||||
|
case background = "Background"
|
||||||
|
case git = "Git"
|
||||||
|
|
||||||
|
var id: Self { self }
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - The popover's content
|
// MARK: - The popover's content
|
||||||
|
|
||||||
/// Two sections and, on a `.git`-bearing board, a contextual note — one view (03-board-ui.md §
|
/// The symbol/name header, then the tab bar, then the selected tab's surface — one view
|
||||||
/// Board popover; 12-editions.md § Base and `.git`).
|
/// (03-board-ui.md § Board popover).
|
||||||
///
|
///
|
||||||
/// Width is the style editor's — 268 points, the number that keeps the Style… popover narrow enough
|
/// Width is the style editor's — the number that keeps the Style… popover narrow enough to sit
|
||||||
/// to sit beside a card — so the embedded editor lays out here exactly as it does at its other two
|
/// beside a card — kept through the restructure so the popover's footprint doesn't wander while the
|
||||||
/// anchors rather than being stretched by a container with its own opinion.
|
/// tabs are placeholders; whether the tabbed surface wants its own width is each tab session's
|
||||||
|
/// question to raise.
|
||||||
struct BoardInfoView: View {
|
struct BoardInfoView: View {
|
||||||
|
|
||||||
let store: BoardStore
|
let store: BoardStore
|
||||||
@@ -272,6 +291,12 @@ struct BoardInfoView: View {
|
|||||||
/// handed the widget's binding to put it down.
|
/// handed the widget's binding to put it down.
|
||||||
@Environment(\.dismiss) private var dismiss
|
@Environment(\.dismiss) private var dismiss
|
||||||
|
|
||||||
|
/// The selected tab. `@State` on the popover's content, which `BoardInfoWidget` hands `.popover`
|
||||||
|
/// fresh on every open — so the selection resets to Info per open. Whether the popover should
|
||||||
|
/// instead remember its last tab is a question for the tab sessions, once the tabs have content
|
||||||
|
/// worth returning to.
|
||||||
|
@State private var tab: BoardInfoTab = .info
|
||||||
|
|
||||||
/// Whether this board carries a `.git` — checked once, off disk, when the view is built (which
|
/// Whether this board carries a `.git` — checked once, off disk, when the view is built (which
|
||||||
/// is every time the popover opens, since `BoardInfoWidget` hands `.popover` a fresh instance).
|
/// is every time the popover opens, since `BoardInfoWidget` hands `.popover` a fresh instance).
|
||||||
/// See `BoardGitNote.hasGitDirectory(at:)` for why a live-updating fact isn't needed here.
|
/// See `BoardGitNote.hasGitDirectory(at:)` for why a live-updating fact isn't needed here.
|
||||||
@@ -335,25 +360,36 @@ struct BoardInfoView: View {
|
|||||||
|
|
||||||
Divider()
|
Divider()
|
||||||
|
|
||||||
VStack(alignment: .leading, spacing: 0) {
|
// The tab bar: a segmented control rather than a `TabView`, because the popover is a
|
||||||
sectionHeader("Styling")
|
// compact settings surface and the segmented idiom is the macOS shape for switching
|
||||||
.padding(.horizontal, inset)
|
// between a handful of peer panes inside one. The label is hidden visually but stays
|
||||||
.padding(.top, inset)
|
// the control's accessibility name.
|
||||||
// Always the board, whatever is selected. The ⌥⌘S anchor is the selection-aware one
|
Picker("Board configuration", selection: $tab) {
|
||||||
// ("nothing selected = the board"); this embed is the surface that exists *because*
|
ForEach(BoardInfoTab.allCases) { tab in
|
||||||
// the board is a style target, so it can have no other target (§ Styling ▸
|
Text(tab.rawValue)
|
||||||
// Controls: "the board popover's target is the board itself").
|
}
|
||||||
// No symbol section — the inline `SymbolPicker` beside the rename field above is
|
|
||||||
// the board glyph's one surface in this popover.
|
|
||||||
StyleEditorView(store: store, recents: recents, target: .board, showsSymbols: false)
|
|
||||||
}
|
}
|
||||||
|
.pickerStyle(.segmented)
|
||||||
|
.labelsHidden()
|
||||||
|
.padding(.horizontal, inset)
|
||||||
|
.padding(.top, inset)
|
||||||
|
|
||||||
// Contextual, not standing (12-editions.md, settled 2026-07-27): an ordinary free-tier
|
// Each tab's surface — empty today, on purpose: the contents are each their own design
|
||||||
// board adds nothing here at all — no header, no divider, no placeholder — and the
|
// session's to settle (the file-top note). The switch is already the shape those
|
||||||
// popover ends at Styling, complete in itself. What a Pro board adds instead is the
|
// sessions will fill in, and the fixed placeholder height is exactly that — a
|
||||||
// mode-aware git section (03-board-ui.md ▸ Board popover), which is a *section*, header
|
// placeholder, so the popover reads as a surface awaiting content rather than a
|
||||||
// and all, because under Pro git is a feature of the board rather than a signpost.
|
// collapsed sliver; it goes the moment any tab has real content to size itself by.
|
||||||
gitSection
|
Group {
|
||||||
|
switch tab {
|
||||||
|
case .info:
|
||||||
|
EmptyView()
|
||||||
|
case .background:
|
||||||
|
EmptyView()
|
||||||
|
case .git:
|
||||||
|
EmptyView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.frame(maxWidth: .infinity, minHeight: 120)
|
||||||
}
|
}
|
||||||
// The style editor's popover width, taken from the editor rather than restated: the embed
|
// 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
|
// below must lay out here exactly as it does at its other two anchors, and that number is
|
||||||
@@ -361,6 +397,15 @@ struct BoardInfoView: View {
|
|||||||
.frame(width: StyleEditorLayout.popover(bodyPointSize: CardWindowMetrics.bodyPointSize).width)
|
.frame(width: StyleEditorLayout.popover(bodyPointSize: CardWindowMetrics.bodyPointSize).width)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: Parked pending the tab sessions (2026-08-07)
|
||||||
|
//
|
||||||
|
// Nothing below this mark renders today. The style-editor embed left the body with the tab
|
||||||
|
// restructure (its Background-tab fate is that session's), and the git section — postures,
|
||||||
|
// notes, and the Board Settings… row — waits here for the Git tab's session. Parked rather
|
||||||
|
// than deleted because every seam it hangs on is settled, test-pinned design
|
||||||
|
// (`BoardGitSectionTests`, `BoardSettingsAvailabilityTests`), and the tab sessions rehome
|
||||||
|
// surfaces, not rulings.
|
||||||
|
|
||||||
/// The popover's closing section, whichever of the six postures this board is in — see
|
/// The popover's closing section, whichever of the six postures this board is in — see
|
||||||
/// `BoardGitSection`.
|
/// `BoardGitSection`.
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
|
|||||||
Reference in New Issue
Block a user