fix(desktop): extend content under macOS title bar, not above it

Previous approach reserved a 28dp strip across the whole top of the
window for traffic lights — wasting the area right of the lights that
Slack / Notion / Safari-style apps reuse for app content.

Now the sidebar / NavigationRail extends to the top of the window
(their surfaceContainer covers the traffic lights on the left), and
the main content area (deck columns / single-pane content) also
extends to the top since it's to the right of the lights.

- DeckSidebar: top padding now 8dp + titleBarInsetTop so icons clear
  the traffic lights.
- SinglePaneLayout's NavigationRail: uses its `header` slot to hold a
  Spacer of titleBarInsetTop, same effect.
- Removed the full-width title bar strip from MainContent.
- SinglePaneLayout NavigationRail container color switched from
  surfaceVariant to surfaceContainer to match the deck sidebar and
  the Material 3 sidebar convention.

https://claude.ai/code/session_01NufduPfZvYQVYwLkbCjCUo
This commit is contained in:
Claude
2026-04-24 13:38:21 +00:00
parent 78a13a82c6
commit 7a9806e936
3 changed files with 7 additions and 15 deletions
@@ -1117,19 +1117,6 @@ fun MainContent(
) {
Box(Modifier.fillMaxSize()) {
Column(Modifier.fillMaxSize()) {
// macOS: reserve a title bar strip so deck/sidebar content doesn't
// underlap the traffic lights. The strip is colored to match the
// sidebar so the whole top edge reads as one continuous toolbar.
if (!isImmersive &&
com.vitorpamplona.amethyst.desktop.platform.PlatformInfo.isMacOS
) {
Box(
Modifier
.fillMaxWidth()
.height(com.vitorpamplona.amethyst.desktop.platform.titleBarInsetTop)
.background(MaterialTheme.colorScheme.surfaceContainer),
)
}
Row(Modifier.fillMaxSize().weight(1f)) {
when (layoutMode) {
LayoutMode.SINGLE_PANE -> {
@@ -43,6 +43,7 @@ import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.tor.TorServiceStatus
import com.vitorpamplona.amethyst.commons.ui.components.BunkerHeartbeatIndicator
import com.vitorpamplona.amethyst.desktop.platform.titleBarInsetTop
import com.vitorpamplona.amethyst.desktop.ui.tor.TorStatusIndicator
@Composable
@@ -60,7 +61,7 @@ fun DeckSidebar(
.width(56.dp)
.fillMaxHeight()
.background(MaterialTheme.colorScheme.surfaceContainer)
.padding(vertical = 8.dp),
.padding(top = 8.dp + titleBarInsetTop, bottom = 8.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Top,
) {
@@ -26,6 +26,7 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
@@ -53,6 +54,7 @@ import com.vitorpamplona.amethyst.desktop.account.AccountState
import com.vitorpamplona.amethyst.desktop.cache.DesktopLocalCache
import com.vitorpamplona.amethyst.desktop.network.DesktopRelayConnectionManager
import com.vitorpamplona.amethyst.desktop.network.Nip11Fetcher
import com.vitorpamplona.amethyst.desktop.platform.titleBarInsetTop
import com.vitorpamplona.amethyst.desktop.service.highlights.DesktopHighlightStore
import com.vitorpamplona.amethyst.desktop.subscriptions.DesktopRelaySubscriptionsCoordinator
import com.vitorpamplona.amethyst.desktop.ui.ZapFeedback
@@ -98,7 +100,9 @@ fun SinglePaneLayout(
if (!isImmersive) {
NavigationRail(
modifier = Modifier.width(80.dp).fillMaxHeight(),
containerColor = MaterialTheme.colorScheme.surfaceVariant,
containerColor = MaterialTheme.colorScheme.surfaceContainer,
// macOS: push rail items below the traffic lights.
header = { Spacer(Modifier.height(titleBarInsetTop)) },
) {
val pinnedScreens by pinnedNavBarState.pinnedScreens.collectAsState()
pinnedScreens.forEach { screenType ->