From c9f5adee72e3605de41625ef04d7d2c2fb2d90ed Mon Sep 17 00:00:00 2001 From: Tomas Dvorak Date: Fri, 18 Sep 2026 21:08:57 +0200 Subject: [PATCH] fix(fm): restore full breadcrumb chain when the bar regains space (#3288) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit maxHiding was only cleared when the path shortened — collapsing on window shrink was never undone on restore, leaving truncated crumbs. Record the chain's required scrollWidth at collapse time and reset via a dedicated ResizeObserver once clientWidth can fit it again. --- .../FileManager/TopBar/Breadcrumb.tsx | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/frontend/src/component/FileManager/TopBar/Breadcrumb.tsx b/frontend/src/component/FileManager/TopBar/Breadcrumb.tsx index 50e9663b..842584ef 100644 --- a/frontend/src/component/FileManager/TopBar/Breadcrumb.tsx +++ b/frontend/src/component/FileManager/TopBar/Breadcrumb.tsx @@ -69,7 +69,7 @@ const Breadcrumb = (props: BreadcrumbProps) => { const [anchorEl, setAnchorEl] = useState(null); const hiddenOpen = Boolean(anchorEl); const hiddenExpandButtonRef = useRef(); - const chainRef = useRef(null); + const chainRef = useRef(null); const openHiddenMenu = (e: React.MouseEvent) => { e.stopPropagation(); @@ -129,16 +129,39 @@ const Breadcrumb = (props: BreadcrumbProps) => { const isOverflow = useIsOverflow(chainRef, (_isOverflow) => {}); + // Width needed to render the full chain, captured before collapsing. + const requiredWidthRef = useRef(0); + useEffect(() => { if (isOverflow && !isMobile) { + requiredWidthRef.current = chainRef.current?.scrollWidth ?? requiredWidthRef.current; setMaxHiding(buttons.length - 1); } }, [isOverflow, isMobile]); + // Restore the full chain once the container can fit it again. A dedicated + // observer is needed: isOverflow stays false once the collapsed chain fits, + // so it cannot drive the restore itself (#3288). + useEffect(() => { + const el = chainRef.current; + if (!el || props.displayOnly) { + return; + } + const observer = new ResizeObserver(() => { + if (requiredWidthRef.current > 0 && el.clientWidth >= requiredWidthRef.current) { + requiredWidthRef.current = 0; + setMaxHiding(0); + } + }); + observer.observe(el); + return () => observer.disconnect(); + }, []); + // Cancel collapse when elements are less than previous useEffect(() => { const current = elements?.length ?? 0; if (previousElements.current > current) { + requiredWidthRef.current = 0; setTimeout(() => { setMaxHiding(0); }, theme.transitions.duration.standard);