fix(desktop): search card floats above scrim, sidebar dims separately

- Header card pulled OUT of ReadingColumn into outer Box layer 3
  (rendered after scrim, so it floats visually above it)
- Feed content in layer 1 with spacer for header height
- Scrim in layer 2 covers only feed content
- Sidebar gets its own scrim overlay via Box wrapper in Main.kt
- Search card stays sharp/visible while everything else dims

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
nrobi144
2026-05-29 07:02:50 +03:00
co-authored by Claude Opus 4.6
parent c8e9a4fa6a
commit bec8fd81ea
2 changed files with 89 additions and 75 deletions
@@ -1380,56 +1380,68 @@ fun MainContent(
}
}
MainSidebar(
activeNpub = accountManager.currentAccount()?.npub,
allAccounts = allAccountsState,
localCache = localCache,
onSwitchAccount = { npub ->
scope.launch(Dispatchers.IO) {
accountManager.switchAccount(npub)
}
},
onAddAccount = { showAddAccountDialog = true },
onRemoveAccount = { npub ->
scope.launch(Dispatchers.IO) {
accountManager.removeAccountFromStorage(npub)
}
},
onAddColumn = onShowAppDrawer,
onOpenSettings = {
when (layoutMode) {
LayoutMode.DECK -> {
if (deckState.hasColumnOfType(DeckColumnType.Settings)) {
deckState.focusExistingColumn(DeckColumnType.Settings)
} else {
deckState.addColumn(DeckColumnType.Settings)
Box {
MainSidebar(
activeNpub = accountManager.currentAccount()?.npub,
allAccounts = allAccountsState,
localCache = localCache,
onSwitchAccount = { npub ->
scope.launch(Dispatchers.IO) {
accountManager.switchAccount(npub)
}
},
onAddAccount = { showAddAccountDialog = true },
onRemoveAccount = { npub ->
scope.launch(Dispatchers.IO) {
accountManager.removeAccountFromStorage(npub)
}
},
onAddColumn = onShowAppDrawer,
onOpenSettings = {
when (layoutMode) {
LayoutMode.DECK -> {
if (deckState.hasColumnOfType(DeckColumnType.Settings)) {
deckState.focusExistingColumn(DeckColumnType.Settings)
} else {
deckState.addColumn(DeckColumnType.Settings)
}
}
LayoutMode.SINGLE_PANE -> {
singlePaneState.navigate(DeckColumnType.Settings)
}
}
LayoutMode.SINGLE_PANE -> {
singlePaneState.navigate(DeckColumnType.Settings)
}
}
},
onNavigate = { type ->
when (layoutMode) {
LayoutMode.DECK -> {
if (deckState.hasColumnOfType(type)) {
deckState.focusExistingColumn(type)
} else {
deckState.addColumn(type)
},
onNavigate = { type ->
when (layoutMode) {
LayoutMode.DECK -> {
if (deckState.hasColumnOfType(type)) {
deckState.focusExistingColumn(type)
} else {
deckState.addColumn(type)
}
}
LayoutMode.SINGLE_PANE -> {
singlePaneState.navigate(type)
}
}
LayoutMode.SINGLE_PANE -> {
singlePaneState.navigate(type)
}
}
},
activeColumnType = activeColumnType,
onShowImportFollowListDialog = onShowImportFollowListDialog,
signerConnectionState = signerConnectionState,
lastPingTimeSec = lastPingTimeSec,
torStatus = torStatus,
)
},
activeColumnType = activeColumnType,
onShowImportFollowListDialog = onShowImportFollowListDialog,
signerConnectionState = signerConnectionState,
lastPingTimeSec = lastPingTimeSec,
torStatus = torStatus,
)
// Dim sidebar when feed search is active
if (com.vitorpamplona.amethyst.desktop.ui.theme.LocalFeedSearchActive.current.value) {
Box(
modifier =
Modifier
.matchParentSize()
.background(Color.Black.copy(alpha = 0.3f)),
)
}
}
VerticalDivider()
@@ -581,35 +581,10 @@ fun FeedScreen(
}
Box(modifier = Modifier.fillMaxSize()) {
// Layer 1: Feed content (scrollable, behind scrim)
ReadingColumn {
// Header: pinned feed tabs + search pill (or expanded search card)
FeedTabsHeader(
feedMode = feedMode,
activeFeedId = activeFeedId,
searchExpanded = searchActive,
onSearchExpandedChange = onSearchActiveChange,
onFeedModeChange = { mode ->
feedMode = mode
activeFeedId = null
activeFeedSource = null
if (mode != FeedMode.CUSTOM) {
DesktopPreferences.feedMode = mode
}
},
onNavigateToFeed = { feed ->
val source = feed.source
if (source is com.vitorpamplona.amethyst.commons.feeds.custom.FeedSource.Filter) {
activeFeedId = feed.id
activeFeedSource = source
feedMode = FeedMode.CUSTOM
}
},
onOpenFeedsDrawer = onOpenFeedsDrawer,
onCompose = onCompose,
onSearchClick = onSearchClick,
)
Spacer(Modifier.height(8.dp))
// Reserve space for the header card that floats above
Spacer(Modifier.height(60.dp))
// Feed content based on FeedState
when (val state = feedState) {
@@ -748,7 +723,7 @@ fun FeedScreen(
)
}
// Search scrim — dims feed content when search is expanded
// Layer 2: Search scrim — dims feed content when search is expanded
if (searchActive) {
Box(
modifier =
@@ -764,6 +739,33 @@ fun FeedScreen(
)
}
// Layer 3: Header card — rendered AFTER scrim so it floats above it
FeedTabsHeader(
feedMode = feedMode,
activeFeedId = activeFeedId,
searchExpanded = searchActive,
onSearchExpandedChange = onSearchActiveChange,
onFeedModeChange = { mode ->
feedMode = mode
activeFeedId = null
activeFeedSource = null
if (mode != FeedMode.CUSTOM) {
DesktopPreferences.feedMode = mode
}
},
onNavigateToFeed = { feed ->
val source = feed.source
if (source is com.vitorpamplona.amethyst.commons.feeds.custom.FeedSource.Filter) {
activeFeedId = feed.id
activeFeedSource = source
feedMode = FeedMode.CUSTOM
}
},
onOpenFeedsDrawer = onOpenFeedsDrawer,
onCompose = onCompose,
onSearchClick = onSearchClick,
)
// Lightbox overlay
lightboxState?.let { state ->
LightboxOverlay(