From c7ef4b159afb0766daed73118fb72030544f4c5d Mon Sep 17 00:00:00 2001 From: npub13fn4ahfnvaa2qwylvegdgeajqs0mph6v4qsw4jcqnw4mjh3hzh2quuucm5 <8a675edd33677aa0389f6650d467b2041fb0df4ca820eacb009babb95e3715d4@sprout-oss.stage.blox.sqprod.co> Date: Tue, 7 Jul 2026 16:29:40 +0100 Subject: [PATCH] =?UTF-8?q?fix(desktop):=20keep=20sidebar=20section=20acti?= =?UTF-8?q?ons=20visible=20while=20=E2=8B=AE=20menu=20is=20open?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Section header controls (the ⋮ actions menu, the quick + create button, and the collapse chevron) are only revealed on group-hover of the section. Opening the ⋮ popover moves the pointer off the header, ending hover and fading all three controls to opacity-0 — so an open menu appears to belong to an empty section. Each section now sets data-section-actions-open while its ⋮ menu is open and the reveal classes gain a group-data-[section-actions-open=true] variant, keeping the controls visible for the whole section (Channels, Forums, Starred, custom sections, and Direct messages) until the menu closes. Signed-off-by: npub13fn4ahfnvaa2qwylvegdgeajqs0mph6v4qsw4jcqnw4mjh3hzh2quuucm5 <8a675edd33677aa0389f6650d467b2041fb0df4ca820eacb009babb95e3715d4@sprout-oss.stage.blox.sqprod.co> --- desktop/src/features/sidebar/ui/AppSidebar.tsx | 3 +++ .../features/sidebar/ui/CustomChannelSection.tsx | 14 +++++++++++--- desktop/src/features/sidebar/ui/SidebarSection.tsx | 9 +++++++-- .../features/sidebar/ui/sidebarSectionStyles.ts | 2 +- 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/desktop/src/features/sidebar/ui/AppSidebar.tsx b/desktop/src/features/sidebar/ui/AppSidebar.tsx index ba148c606fb..ddfd18d0cfa 100644 --- a/desktop/src/features/sidebar/ui/AppSidebar.tsx +++ b/desktop/src/features/sidebar/ui/AppSidebar.tsx @@ -240,6 +240,7 @@ export function AppSidebar({ const [isNewDmOpenInternal, setIsNewDmOpenInternal] = React.useState(false); const isNewDmOpen = isNewDmOpenProp ?? isNewDmOpenInternal; const setIsNewDmOpen = onNewDmOpenChange ?? setIsNewDmOpenInternal; + const [dmActionsMenuOpen, setDmActionsMenuOpen] = React.useState(false); const scrollRef = React.useRef(null); useSidebarScrollLock(scrollRef); @@ -760,6 +761,7 @@ export function AppSidebar({ setIsNewDmOpen(true)} sortMode={sortModeFor("dms")} onSortModeChange={(mode) => setSortModeFor("dms", mode)} @@ -783,6 +785,7 @@ export function AppSidebar({ selectedChannelId={selectedChannelId} testId="dm-list" title="Direct messages" + sectionActionsOpen={dmActionsMenuOpen} unreadChannelCounts={unreadChannelCounts} unreadChannelIds={unreadChannelIds} mutedChannelIds={mutedChannelIds} diff --git a/desktop/src/features/sidebar/ui/CustomChannelSection.tsx b/desktop/src/features/sidebar/ui/CustomChannelSection.tsx index 2021f7eca18..5818c430ad9 100644 --- a/desktop/src/features/sidebar/ui/CustomChannelSection.tsx +++ b/desktop/src/features/sidebar/ui/CustomChannelSection.tsx @@ -10,7 +10,7 @@ import { Trash2, } from "lucide-react"; -import { useRef } from "react"; +import { useRef, useState } from "react"; import type * as React from "react"; import type { ChannelSortMode } from "@/features/sidebar/lib/channelSortPreference"; @@ -63,7 +63,7 @@ import { StatusEmoji } from "@/features/user-status/ui/StatusEmoji"; const SECTION_LABEL_BUTTON_CLASS = "group/section-label flex w-fit max-w-[calc(100%-3rem)] cursor-pointer appearance-none items-center gap-1 text-left transition-colors hover:text-sidebar-foreground focus-visible:text-sidebar-foreground"; const SECTION_LABEL_CHEVRON_CLASS = - "relative size-2.5 shrink-0 text-current opacity-0 transition-[color,opacity] group-hover/sidebar-section:opacity-100 group-hover/section-label:opacity-100 group-focus-within/sidebar-section:opacity-100 group-focus-visible/section-label:opacity-100"; + "relative size-2.5 shrink-0 text-current opacity-0 transition-[color,opacity] group-hover/sidebar-section:opacity-100 group-hover/section-label:opacity-100 group-focus-within/sidebar-section:opacity-100 group-focus-visible/section-label:opacity-100 group-data-[section-actions-open=true]/sidebar-section:opacity-100"; const SECTION_LABEL_CHEVRON_ICON_CLASS = "absolute left-1/2 top-1/2 size-2.5 -translate-x-1/2 -translate-y-1/2"; @@ -119,6 +119,7 @@ export function SectionActionsMenu({ sectionLabel, testId, visibilityClassName = SECTION_ACTION_VISIBILITY_CLASS, + onOpenChange, hasUnread, onMarkAllRead, onBrowse, @@ -139,6 +140,7 @@ export function SectionActionsMenu({ sectionLabel: string; testId?: string; visibilityClassName?: string; + onOpenChange?: (open: boolean) => void; hasUnread?: boolean; onMarkAllRead?: () => void; onBrowse?: () => void; @@ -161,7 +163,7 @@ export function SectionActionsMenu({ const showSort = Boolean(sortMode && onSortModeChange); return ( - +