fix(desktop): share channel header backdrop

Render one channel header blur behind split columns so the backdrop blends across channel and auxiliary panes.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Thomas Petersen
2026-06-17 11:06:48 -04:00
parent 584ef13c7b
commit 92291b370b
6 changed files with 23 additions and 4 deletions

View File

@@ -598,7 +598,10 @@ export const ChannelPane = React.memo(function ChannelPane({
[agentSessionAgents, openAgentSessionPubkey],
);
return (
<div className="flex min-h-0 min-w-0 flex-1 flex-row overflow-hidden">
<div className="relative flex min-h-0 min-w-0 flex-1 flex-row overflow-hidden">
{!isSinglePanelView ? (
<div aria-hidden="true" className={channelChrome.backdrop} />
) : null}
{!isSinglePanelView ? (
<section
aria-label="Channel messages and composer"

View File

@@ -565,6 +565,8 @@ export function ChannelScreen({
resetKey: activeChannelId,
enabled: !isSinglePanelView,
});
const useSharedChannelHeaderBackdrop =
activeChannel?.channelType !== "forum" && !isSinglePanelView;
React.useEffect(() => {
setTopbarSearchHidden(isSinglePanelView);
return () => {
@@ -590,6 +592,7 @@ export function ChannelScreen({
onManageChannel={openChannelManagement}
onToggleMembers={() => setIsMembersSidebarOpen((prev) => !prev)}
showHeaderContent={!isSinglePanelView}
transparentChrome={useSharedChannelHeaderBackdrop}
/>
);

View File

@@ -26,6 +26,7 @@ type ChannelScreenHeaderProps = {
isAddBotOpen?: boolean;
isJoining?: boolean;
showHeaderContent?: boolean;
transparentChrome?: boolean;
onAddBotOpenChange?: (open: boolean) => void;
onJoinChannel?: () => Promise<void>;
onManageChannel: () => void;
@@ -46,6 +47,7 @@ export function ChannelScreenHeader({
isJoining = false,
onAddBotOpenChange,
showHeaderContent = true,
transparentChrome = false,
onJoinChannel,
onManageChannel,
onToggleMembers,
@@ -121,6 +123,7 @@ export function ChannelScreenHeader({
/>
}
title={activeChannelTitle}
transparentChrome={transparentChrome}
visibility={activeChannel?.visibility}
/>
);

View File

@@ -30,6 +30,7 @@ type ChatHeaderProps = {
mode?: "home" | "channel" | "agents" | "workflows" | "pulse" | "projects";
overlaysContent?: boolean;
statusBadge?: React.ReactNode;
transparentChrome?: boolean;
};
const HEADER_ICON_CLASS = "h-4 w-4 text-muted-foreground";
@@ -92,6 +93,7 @@ export function ChatHeader({
mode = "channel",
overlaysContent = false,
statusBadge,
transparentChrome = false,
}: ChatHeaderProps) {
const trimmedDescription = description?.trim() ?? "";
@@ -150,7 +152,9 @@ export function ChatHeader({
<div
ref={chromeWrapperRef}
className={cn(
"pointer-events-none relative z-30 bg-background/80 backdrop-blur-md supports-backdrop-filter:bg-background/70 dark:bg-background/70 dark:backdrop-blur-xl dark:supports-backdrop-filter:bg-background/55",
transparentChrome
? "pointer-events-none relative z-40"
: "pointer-events-none relative z-30 bg-background/80 backdrop-blur-md supports-backdrop-filter:bg-background/70 dark:bg-background/70 dark:backdrop-blur-xl dark:supports-backdrop-filter:bg-background/55",
topChromeInset.padding,
channelChrome.negativeMargin,
)}

View File

@@ -16,7 +16,7 @@ export function AuxiliaryPanelHeader({
return (
<div
className={cn(
"pointer-events-none relative z-30 bg-background/80 backdrop-blur-md after:absolute after:inset-x-0 after:bottom-0 after:h-px after:bg-border/35 after:content-[''] supports-backdrop-filter:bg-background/70 dark:bg-background/70 dark:backdrop-blur-xl dark:supports-backdrop-filter:bg-background/55",
"pointer-events-none relative z-40",
topChromeInset.padding,
channelChrome.negativeMargin,
className,

View File

@@ -42,7 +42,7 @@ export const insetHeaderOverlay = {
* dividers across the header area.
*/
backdrop:
"pointer-events-none absolute inset-x-0 top-0 z-30 h-(--buzz-inset-header-height,5rem) bg-background/80 backdrop-blur-md supports-backdrop-filter:bg-background/70 dark:bg-background/70 dark:backdrop-blur-xl dark:supports-backdrop-filter:bg-background/55",
"pointer-events-none absolute inset-x-0 top-0 z-30 h-(--buzz-inset-header-height,5rem) bg-background/90 backdrop-blur-md supports-backdrop-filter:bg-background/85 dark:bg-background/70 dark:backdrop-blur-xl dark:supports-backdrop-filter:bg-background/55",
} as const;
/** Tailwind class fragments for layout under the global top chrome. */
@@ -74,6 +74,12 @@ export const topChromeBackdrop = {
export const channelChrome = {
/** Padding-top that clears the measured channel header chrome. */
contentPadding: "pt-(--buzz-channel-content-top-padding,5.75rem)",
/**
* Single full-width backdrop strip behind channel and auxiliary headers so
* backdrop blur samples continuously across column boundaries.
*/
backdrop:
"pointer-events-none absolute inset-x-0 top-0 z-30 h-(--buzz-channel-content-top-padding,5.75rem) bg-background/90 backdrop-blur-md supports-backdrop-filter:bg-background/85 dark:bg-background/70 dark:backdrop-blur-xl dark:supports-backdrop-filter:bg-background/55",
/** Absolute/fixed top offset below the measured channel header chrome. */
top: "top-(--buzz-channel-content-top-padding,5.75rem)",
/** Height matching the measured channel header chrome. */