fix(desktop): sidebar sections never overlap — two-mode CSS scroll + collapse/cap groups (#43147)
* fix(desktop): prevent sidebar section overlap Use a shared sidebar section scroller only on short windows so sections do not overlap, while preserving per-section scrolling on taller layouts. * fix(desktop): measure section stack for compact sidebar mode Window-height media query kept big windows in compact mode whenever the OS chrome ate into 830px; observe the section stack element instead so compact only engages when the stack is actually short. * refactor(desktop): drive sidebar compact mode with CSS, not JS Replace the matchMedia hook with a `short` (max-height: 830px) Tailwind variant so the per-section scrollers flatten into one shared scroll stack on short windows purely in CSS. Taller windows keep their per-group scrollers and recents virtualization unchanged. * refactor(desktop): pure-CSS two-mode sidebar scroll + collapse/cap groups Drop the JS-measured compaction in favour of a single `compact` height variant (max-height: 768px): - tall: every section is its own capped, independent scroller; Sessions is the lone flex-1 scroller. - short: sections flatten and the stack scrolls as one. Every section is now `shrink-0`, so nothing is squeezed below its content and bled onto a sibling — the root cause of the header overlap (flexbox implied min-size). Sessions keeps its virtualized scroller in short mode only when it's the long list. Non-session groups (messaging, cron) collapse by default — expanded ids persist per platform — and render 3 rows, revealing 10 more on demand. Extract the shared SidebarLoadMoreRow. Stress harness seeds 50 recents to mirror the real first page. * chore(desktop): trim sidebar comments, unify "compact" naming Self-review polish: condense the over-long mode comments, use "compact" consistently (matching the variant) instead of mixing "short", and drop a no-op useCallback around revealMoreMessaging. * chore(desktop): drop dev sidebar stress harness from the PR Remove stress-probe.ts and its main.tsx import — it was a throwaway testing aid, not something to ship.
This commit is contained in:
@@ -23,6 +23,7 @@ export const SIDEBAR_SESSIONS_PAGE_SIZE = 50
|
||||
const SIDEBAR_PINNED_STORAGE_KEY = 'hermes.desktop.pinnedSessions'
|
||||
const SIDEBAR_AGENTS_GROUPED_STORAGE_KEY = 'hermes.desktop.agentsGroupedByWorkspace'
|
||||
const SIDEBAR_CRON_OPEN_STORAGE_KEY = 'hermes.desktop.sidebarCronOpen'
|
||||
const SIDEBAR_MESSAGING_OPEN_STORAGE_KEY = 'hermes.desktop.sidebarMessagingOpen'
|
||||
const SIDEBAR_SESSION_ORDER_STORAGE_KEY = 'hermes.desktop.sessionOrder'
|
||||
const SIDEBAR_WORKSPACE_ORDER_STORAGE_KEY = 'hermes.desktop.workspaceOrder'
|
||||
const PANES_FLIPPED_STORAGE_KEY = 'hermes.desktop.panesFlipped'
|
||||
@@ -68,6 +69,10 @@ export const $sidebarRecentsOpen = atom(true)
|
||||
// default (it only renders at all when cron sessions exist) so the
|
||||
// scheduler's `[IMPORTANT: …]` first-message previews don't spam recents.
|
||||
export const $sidebarCronOpen = atom(storedBoolean(SIDEBAR_CRON_OPEN_STORAGE_KEY, false))
|
||||
// Messaging platform sections collapse by default (they can be numerous and
|
||||
// tall). We persist the ids the user has *explicitly expanded*, so the default
|
||||
// stays collapsed unless they've opened a platform before.
|
||||
export const $sidebarMessagingOpenIds = atom<string[]>(storedStringArray(SIDEBAR_MESSAGING_OPEN_STORAGE_KEY))
|
||||
export const $sidebarAgentsGrouped = atom(storedBoolean(SIDEBAR_AGENTS_GROUPED_STORAGE_KEY, false))
|
||||
// When true, the sessions sidebar moves to the right and the file browser +
|
||||
// preview rail move to the left — a mirror of the default layout.
|
||||
@@ -77,6 +82,7 @@ export const $sessionsLimit = atom(SIDEBAR_SESSIONS_PAGE_SIZE)
|
||||
|
||||
$pinnedSessionIds.subscribe(ids => persistStringArray(SIDEBAR_PINNED_STORAGE_KEY, [...ids]))
|
||||
$sidebarCronOpen.subscribe(open => persistBoolean(SIDEBAR_CRON_OPEN_STORAGE_KEY, open))
|
||||
$sidebarMessagingOpenIds.subscribe(ids => persistStringArray(SIDEBAR_MESSAGING_OPEN_STORAGE_KEY, [...ids]))
|
||||
$sidebarSessionOrderIds.subscribe(ids => persistStringArray(SIDEBAR_SESSION_ORDER_STORAGE_KEY, [...ids]))
|
||||
$sidebarWorkspaceOrderIds.subscribe(ids => persistStringArray(SIDEBAR_WORKSPACE_ORDER_STORAGE_KEY, [...ids]))
|
||||
$sidebarAgentsGrouped.subscribe(grouped => persistBoolean(SIDEBAR_AGENTS_GROUPED_STORAGE_KEY, grouped))
|
||||
@@ -139,6 +145,14 @@ export function setSidebarCronOpen(open: boolean) {
|
||||
$sidebarCronOpen.set(open)
|
||||
}
|
||||
|
||||
export function toggleSidebarMessagingOpen(sourceId: string) {
|
||||
const current = $sidebarMessagingOpenIds.get()
|
||||
|
||||
$sidebarMessagingOpenIds.set(
|
||||
current.includes(sourceId) ? current.filter(id => id !== sourceId) : [...current, sourceId]
|
||||
)
|
||||
}
|
||||
|
||||
export function setSidebarAgentsGrouped(grouped: boolean) {
|
||||
$sidebarAgentsGrouped.set(grouped)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user