diff --git a/src/equicordplugins/collapsibleUi/index.tsx b/src/equicordplugins/collapsibleUi/index.tsx index 2369c0c93..f6df1c273 100644 --- a/src/equicordplugins/collapsibleUi/index.tsx +++ b/src/equicordplugins/collapsibleUi/index.tsx @@ -20,8 +20,8 @@ import managedStyle from "./style.css?managed"; const cl = classNameFactory("vc-collapsible-ui-"); const panelDependentSurfaces: Record = { - guildBar: ["guildBar", "userArea"], - channelList: ["channelList", "base", "sidebar", "userArea"], + guildBar: ["guildBar", "sidebar", "userArea"], + channelList: ["channelList", "base", "sidebar"], membersList: ["membersList"], chatButtons: [], titleBar: ["titleBar"], @@ -37,6 +37,7 @@ const DETACHED_USER_AREA_DEFAULT_OFFSET_Y = 88; let providerUnsubs: Array<() => void> = []; let channelListExpandedByInteraction = false; +let guildBarExpandedByInteraction = false; let headerBarExpandedByInteraction = false; let headerBarPointerTrackerEnabled = false; let userAreaDragState: { offsetX: number; offsetY: number; width: number; height: number; } | undefined; @@ -84,7 +85,17 @@ function setChannelListExpandedByInteraction(expanded: boolean) { notifySurfaceClassesChanged("sidebar"); } +function setGuildBarExpandedByInteraction(expanded: boolean) { + if (guildBarExpandedByInteraction === expanded) return; + guildBarExpandedByInteraction = expanded; + notifySurfaceClassesChanged("guildBar"); +} + function syncPanelCollapsedState(panelId: PanelId, collapsed: boolean) { + if (panelId === "guildBar") { + guildBarExpandedByInteraction = false; + } + if (panelId === "channelList") { channelListExpandedByInteraction = false; } @@ -187,7 +198,17 @@ function eventWithin(element: HTMLElement | null, event: ReactFocusEvent | ReactMouseEvent) { + return event.target instanceof Element && !!event.target.closest(".vc-betterFolders-sidebar"); +} + function handleSidebarEnter(event: ReactFocusEvent | ReactMouseEvent) { + if (isPanelCollapsed("guildBar")) { + setGuildBarExpandedByInteraction(eventWithinBetterFolders(event)); + } + if (eventWithin(userAreaElement, event)) { setChannelListExpandedByInteraction(false); return; @@ -199,6 +220,10 @@ function handleSidebarEnter(event: ReactFocusEvent | ReactMouseEven } function handleSidebarLeave(event: ReactFocusEvent | ReactMouseEvent) { + if (!(event.relatedTarget instanceof Element && event.relatedTarget.closest(".vc-betterFolders-sidebar"))) { + setGuildBarExpandedByInteraction(false); + } + if (nodeWithin(userAreaElement, event.relatedTarget)) { setChannelListExpandedByInteraction(false); return; @@ -446,7 +471,14 @@ export default definePlugin({ } as SurfaceProvidedProps); providerUnsubs = [ - addSurfacePropsProvider("guildBar", () => panelAttr(panelRegistry.guildBar.classId, isPanelCollapsed("guildBar"))), + addSurfacePropsProvider("guildBar", () => { + const collapsed = isPanelCollapsed("guildBar"); + const attrs: SurfaceProvidedProps = panelAttr(panelRegistry.guildBar.classId, collapsed); + if (collapsed && guildBarExpandedByInteraction) { + attrs["data-vc-collapsible-ui-guild-bar-interaction-expanded"] = ""; + } + return attrs; + }), addSurfacePropsProvider("channelList", () => { const attrs: SurfaceProvidedProps = panelAttr(panelRegistry.channelList.classId, isPanelCollapsed("channelList")); attrs.ref = setChannelListElement; @@ -471,7 +503,6 @@ export default definePlugin({ }), addSurfacePropsProvider("userArea", () => { const uaCollapsed = isPanelCollapsed("userArea"); - const clCollapsed = isPanelCollapsed("channelList"); const gbCollapsed = isPanelCollapsed("guildBar"); const userAreaDetached = shouldDetachUserArea(); const attrs: SurfaceProvidedProps = panelAttr(panelRegistry.userArea.classId, uaCollapsed); @@ -486,9 +517,6 @@ export default definePlugin({ }; attrs.onMouseDownCapture = startDetachedUserAreaDrag; } - if (!userAreaDetached && clCollapsed) { - attrs["data-vc-collapsible-ui-user-area-channel-list-collapsed"] = ""; - } if (!userAreaDetached && gbCollapsed) { attrs["data-vc-collapsible-ui-user-area-guild-bar-collapsed"] = ""; } @@ -512,6 +540,7 @@ export default definePlugin({ "data-vc-collapsible-ui-sidebar": "", [`data-vc-collapsible-ui-sidebar-channel-list-${collapsed ? "collapsed" : "expanded"}`]: "", ...(collapsed && channelListExpandedByInteraction ? { "data-vc-collapsible-ui-sidebar-channel-list-expanded": "" } : {}), + ...(isPanelCollapsed("guildBar") ? { "data-vc-collapsible-ui-sidebar-guild-bar-collapsed": "" } : {}), ...(userAreaDetached ? { "data-vc-collapsible-ui-sidebar-user-area-detached": "" } : {}), onFocusCapture: handleSidebarEnter, onBlurCapture: handleSidebarLeave, @@ -536,6 +565,7 @@ export default definePlugin({ channelListElement = null; userAreaElement = null; channelListExpandedByInteraction = false; + guildBarExpandedByInteraction = false; headerBarExpandedByInteraction = false; surfaceCssPxCache.clear(); }, diff --git a/src/equicordplugins/collapsibleUi/style.css b/src/equicordplugins/collapsibleUi/style.css index 6b269959f..70788da19 100644 --- a/src/equicordplugins/collapsibleUi/style.css +++ b/src/equicordplugins/collapsibleUi/style.css @@ -23,10 +23,22 @@ [data-vc-collapsible-ui-base-channel-list-collapsed] { /* stylelint-disable-next-line value-keyword-case */ - grid-template-columns: [start] min-content [guildsEnd] min-content [sidebarEnd] var(--vc-cui-peek-size) [channelsEnd] 1fr [end] !important; + grid-template-columns: [start] min-content [guildsEnd] var(--vc-cui-peek-size) [channelsEnd] 1fr [end] !important; } [data-vc-collapsible-ui-base-channel-list-collapsed][data-vc-collapsible-ui-base-channel-list-interaction-expanded] { + /* stylelint-disable-next-line value-keyword-case */ + grid-template-columns: [start] min-content [guildsEnd] var(--custom-guild-sidebar-width, 312px) [channelsEnd] 1fr [end] !important; +} + +/* BetterFolders redefines the base grid with an extra folder column, so the + collapsed templates must keep its [sidebarEnd] track to stay in sync. */ +[data-vc-collapsible-ui-base-channel-list-collapsed].vc-betterFolders-sidebar-grid { + /* stylelint-disable-next-line value-keyword-case */ + grid-template-columns: [start] min-content [guildsEnd] min-content [sidebarEnd] var(--vc-cui-peek-size) [channelsEnd] 1fr [end] !important; +} + +[data-vc-collapsible-ui-base-channel-list-collapsed][data-vc-collapsible-ui-base-channel-list-interaction-expanded].vc-betterFolders-sidebar-grid { /* stylelint-disable-next-line value-keyword-case */ grid-template-columns: [start] min-content [guildsEnd] min-content [sidebarEnd] var(--custom-guild-sidebar-width, 312px) [channelsEnd] 1fr [end] !important; } @@ -67,8 +79,8 @@ transition-delay: var(--vc-cui-fade-delay); } -[data-vc-collapsible-ui-guild-bar-collapsed]:not(.vc-betterFolders-sidebar *):is(:hover, :focus-within), -[data-vc-collapsible-ui-base]:has(.vc-betterFolders-sidebar:is(:hover, :focus-within)) [data-vc-collapsible-ui-guild-bar-collapsed]:not(.vc-betterFolders-sidebar *) { +[data-vc-collapsible-ui-guild-bar-collapsed]:not(.vc-betterFolders-sidebar *):hover, +[data-vc-collapsible-ui-guild-bar-collapsed][data-vc-collapsible-ui-guild-bar-interaction-expanded]:not(.vc-betterFolders-sidebar *) { width: var(--vc-cui-guild-bar-expanded-width) !important; min-width: var(--vc-cui-guild-bar-expanded-width) !important; max-width: var(--vc-cui-guild-bar-expanded-width) !important; @@ -80,7 +92,7 @@ /* BetterFolders renders a duplicate guilds nav inside its folder sidebar. The collapse rules above exempt that duplicate; collapse the sidebar wrapper in sync with the real guild bar instead. */ -[data-vc-collapsible-ui-base]:has([data-vc-collapsible-ui-guild-bar-collapsed]) .vc-betterFolders-sidebar { +[data-vc-collapsible-ui-sidebar-guild-bar-collapsed] .vc-betterFolders-sidebar { width: 0 !important; min-width: 0 !important; opacity: 0.01; @@ -89,8 +101,8 @@ transition-delay: var(--vc-cui-fade-delay); } -[data-vc-collapsible-ui-base]:has([data-vc-collapsible-ui-guild-bar-collapsed]:is(:hover, :focus-within)) .vc-betterFolders-sidebar, -[data-vc-collapsible-ui-base]:has([data-vc-collapsible-ui-guild-bar-collapsed]) .vc-betterFolders-sidebar:is(:hover, :focus-within) { +[data-vc-collapsible-ui-guild-bar-collapsed]:hover ~ .vc-betterFolders-sidebar, +[data-vc-collapsible-ui-sidebar-guild-bar-collapsed] .vc-betterFolders-sidebar:hover { width: auto !important; opacity: 1; transition-delay: 0ms; @@ -279,6 +291,12 @@ max-width: var(--vc-cui-peek-size) !important; } +[data-vc-collapsible-ui-sidebar-channel-list-collapsed]:not([data-vc-collapsible-ui-sidebar-user-area-detached]) [data-vc-collapsible-ui-user-area-collapsed]:is(:hover, :focus-within) { + width: var(--custom-guild-sidebar-width, 312px) !important; + min-width: var(--vc-cui-channel-list-min-width) !important; + max-width: var(--vc-cui-channel-list-max-width) !important; +} + [data-vc-collapsible-ui-sidebar-channel-list-expanded]:not([data-vc-collapsible-ui-sidebar-user-area-detached]) [data-vc-collapsible-ui-user-area] { /* Anchor both edges instead of forcing a width: the guild bar column is min-content and theme-dependent, so a fixed width leaves a right-side