fix: cap sidebar width responsively

This commit is contained in:
Kaede Akino committed 2026-08-27 05:54:58 +08:00
1 parent 0964535ddb
commit 69bc5e0bae
2 files changed
+35 -9

No files matched your search

+16 -4
View File
@@ -19,6 +19,9 @@ struct RootView: View {
/// split view's minimum sidebar width are rejected so the tab strip keeps
/// the user's last visible boundary.
@State private var pinnedTabStripWidth = Metrics.Sidebar.ideal
/// Drives the sidebar's responsive upper bound. Start at the default so the
/// first layout pass already has a sensible value before geometry reports.
@State private var layoutWidth = Metrics.Window.defaultWidth
/// `nonisolated` because geometry transforms are `Sendable` closures and
/// this coordinate-space name is immutable, not main-actor state.
@@ -45,6 +48,11 @@ struct RootView: View {
maxHeight: .infinity
)
.coordinateSpace(.named(Self.layoutSpace))
.onGeometryChange(for: CGFloat.self) {
$0.size.width
} action: {
layoutWidth = $0
}
.toolbarBackground(WindowChrome.background(for: colorScheme), for: .windowToolbar)
.toolbarBackground(.visible, for: .windowToolbar)
// ⌘T and every Connect entry land here. A sheet rather than a page,
@@ -123,8 +131,8 @@ struct RootView: View {
SidebarView(detailCatalog: .standard(store: app.hostLibrary))
.navigationSplitViewColumnWidth(
min: Metrics.Sidebar.min,
ideal: Metrics.Sidebar.ideal,
max: Metrics.Sidebar.max
ideal: min(Metrics.Sidebar.ideal, sidebarMaxWidth),
max: sidebarMaxWidth
)
} detail: {
VStack(spacing: 0) {
@@ -153,11 +161,15 @@ struct RootView: View {
VaultSidebarView()
.navigationSplitViewColumnWidth(
min: Metrics.Sidebar.min,
ideal: Metrics.Sidebar.ideal,
max: Metrics.Sidebar.max
ideal: min(Metrics.Sidebar.ideal, sidebarMaxWidth),
max: sidebarMaxWidth
)
}
private var sidebarMaxWidth: CGFloat {
Metrics.Window.sidebarMaxWidth(for: layoutWidth)
}
private func recordPinnedTabStripWidth(_ measuredDetailLeadingEdge: CGFloat) {
pinnedTabStripWidth = PinnedTopLevelTabSizing.resolvedStripWidth(
current: pinnedTabStripWidth,
+19 -5
View File
@@ -271,16 +271,30 @@ nonisolated enum Metrics {
static let detailMin: CGFloat = 320
static let detailMinHeight: CGFloat = 440
/// Space to the right of the navigation sidebar in Vault's complete
/// working layout: two dividers, the main surface, and an Edit/New
/// detail panel.
static let trailingContentMinWidth: CGFloat = 1
+ Metrics.VaultContent.min
+ 1
+ Metrics.VaultDetail.min
/// Vault's complete working layout sets the application floor: the
/// navigation sidebar, main surface, and an Edit/New detail panel, plus
/// the two dividers between them. Reserving the third column even while
/// it is closed prevents opening an editor inside an already-too-narrow
/// window and keeps every host form usable from the moment it appears.
static let minWidth: CGFloat = Metrics.Sidebar.min
+ 1
+ Metrics.VaultContent.min
+ 1
+ Metrics.VaultDetail.min
static let minWidth: CGFloat = Metrics.Sidebar.min + trailingContentMinWidth
/// The sidebar may use only width left after the complete Vault work
/// area has been reserved. It grows with the window, but never outside
/// its own usability bounds.
static func sidebarMaxWidth(for availableWidth: CGFloat) -> CGFloat {
min(
Metrics.Sidebar.max,
max(Metrics.Sidebar.min, availableWidth - trailingContentMinWidth)
)
}
/// Root content includes the pinned tab strip and its divider above the
/// detail floor. The macOS title bar is outside this measurement.