diff options
| author | Fuwn <[email protected]> | 2026-02-07 03:46:53 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2026-02-07 03:46:53 -0800 |
| commit | 6bbcebf6f8da631bf6d94bab2a5078896034e62f (patch) | |
| tree | d76b1a8c08a852168d582b2556bd90106370457f | |
| parent | fix: persist detail panel sizes with panelIds-keyed storage (diff) | |
| download | asa.news-6bbcebf6f8da631bf6d94bab2a5078896034e62f.tar.xz asa.news-6bbcebf6f8da631bf6d94bab2a5078896034e62f.zip | |
feat: derive sidebar min/default width from measured content
Measures the first sidebar nav item (all entries + unread badge)
after mount and uses its scrollWidth + padding as minSize. Default
is 1.4x the minimum for comfortable reading of feed titles.
| -rw-r--r-- | apps/web/app/reader/_components/reader-layout-shell.tsx | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/apps/web/app/reader/_components/reader-layout-shell.tsx b/apps/web/app/reader/_components/reader-layout-shell.tsx index 8c6db8b..0795780 100644 --- a/apps/web/app/reader/_components/reader-layout-shell.tsx +++ b/apps/web/app/reader/_components/reader-layout-shell.tsx @@ -1,6 +1,6 @@ "use client" -import { Suspense, useEffect, useState } from "react" +import { Suspense, useCallback, useEffect, useState } from "react" import { Group, Panel, Separator, useDefaultLayout } from "react-resizable-panels" import { useUserInterfaceStore } from "@/lib/stores/user-interface-store" import { classNames } from "@/lib/utilities" @@ -48,6 +48,17 @@ export function ReaderLayoutShell({ (state) => state.focusFollowsInteraction ) const isMobile = useIsMobile() + const [sidebarMinimumWidth, setSidebarMinimumWidth] = useState("150px") + const [sidebarDefaultWidth, setSidebarDefaultWidth] = useState("220px") + + const measureSidebarWidths = useCallback(() => { + const firstNavigationItem = document.querySelector("[data-sidebar-nav-item]") + if (!firstNavigationItem) return + const navigationContainerPadding = 16 + const measuredMinimumWidth = firstNavigationItem.scrollWidth + navigationContainerPadding + setSidebarMinimumWidth(`${measuredMinimumWidth}px`) + setSidebarDefaultWidth(`${Math.round(measuredMinimumWidth * 1.4)}px`) + }, []) const sidebarLayout = useDefaultLayout({ id: "asa-sidebar-layout", @@ -58,6 +69,12 @@ export function ReaderLayoutShell({ useKeyboardNavigation() useEffect(() => { + if (isSidebarCollapsed || isMobile) return + const timeoutIdentifier = setTimeout(measureSidebarWidths, 100) + return () => clearTimeout(timeoutIdentifier) + }, [isSidebarCollapsed, isMobile, measureSidebarWidths]) + + useEffect(() => { async function checkAssuranceLevel() { const supabaseClient = createSupabaseBrowserClient() const { data } = await supabaseClient.auth.mfa.getAuthenticatorAssuranceLevel() @@ -207,7 +224,7 @@ export function ReaderLayoutShell({ > {!isSidebarCollapsed && ( <> - <Panel id="sidebar" defaultSize="20%" minSize="15%" maxSize="35%"> + <Panel id="sidebar" defaultSize={sidebarDefaultWidth} minSize={sidebarMinimumWidth} maxSize="35%"> <aside data-panel-zone="sidebar" className={classNames( |