mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-27 16:26:16 +08:00
feat(toolbar): auto-compact AppSwitcher based on available width
Replace hardcoded app count threshold with ResizeObserver-based detection. Uses a two-layer layout (overflow-hidden outer + shrink-0 inner) to avoid the compact/normal oscillation problem.
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
import { useEffect, useRef, useState, type RefObject } from "react";
|
||||
|
||||
/**
|
||||
* Detects whether the container's children overflow the available width
|
||||
* and returns a `compact` flag for the AppSwitcher.
|
||||
*
|
||||
* Uses ResizeObserver on a flex-constrained container. The container
|
||||
* must have `flex-1 min-w-0 overflow-hidden` so its width is determined
|
||||
* by the parent layout, not its own content — avoiding the oscillation
|
||||
* problem when toggling compact mode.
|
||||
*/
|
||||
export function useAutoCompact(
|
||||
containerRef: RefObject<HTMLDivElement | null>,
|
||||
): boolean {
|
||||
const [compact, setCompact] = useState(false);
|
||||
const normalWidthRef = useRef(0);
|
||||
|
||||
useEffect(() => {
|
||||
const el = containerRef.current;
|
||||
if (!el) return;
|
||||
|
||||
const ro = new ResizeObserver(() => {
|
||||
if (!compact) {
|
||||
// Cache the total content width in normal mode
|
||||
normalWidthRef.current = el.scrollWidth;
|
||||
// Overflow detected → switch to compact
|
||||
if (el.scrollWidth > el.clientWidth + 1) {
|
||||
setCompact(true);
|
||||
}
|
||||
} else if (normalWidthRef.current > 0) {
|
||||
// In compact mode: only recover to normal if
|
||||
// available space >= what normal mode needed
|
||||
if (el.clientWidth >= normalWidthRef.current) {
|
||||
setCompact(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
ro.observe(el);
|
||||
return () => ro.disconnect();
|
||||
}, [compact]);
|
||||
|
||||
return compact;
|
||||
}
|
||||
Reference in New Issue
Block a user