;
+ onSidebarDropdownToggle: (value: boolean) => void;
+ onSidebarPanelPositionChange: (position: { left: number; top: number; width: number } | null) => void;
+};
+
+function WorkspaceMenuStateSync(props: WorkspaceMenuStateSyncProps) {
+ const { open, variant, sidebarPanelButtonRef, onSidebarDropdownToggle, onSidebarPanelPositionChange } = props;
+
+ const updateSidebarPanelMenuPosition = useCallback(() => {
+ if (variant !== "sidebar-panel" || !sidebarPanelButtonRef.current || typeof window === "undefined") return;
+
+ const rect = sidebarPanelButtonRef.current.getBoundingClientRect();
+ const width = 480;
+ const viewportPadding = 16;
+
+ onSidebarPanelPositionChange({
+ left: Math.min(rect.left, window.innerWidth - width - viewportPadding),
+ top: rect.bottom + 8,
+ width,
+ });
+ }, [onSidebarPanelPositionChange, sidebarPanelButtonRef, variant]);
+
+ useEffect(() => {
+ onSidebarDropdownToggle(open);
+ }, [onSidebarDropdownToggle, open]);
+
+ useLayoutEffect(() => {
+ if (!open || variant !== "sidebar-panel") {
+ onSidebarPanelPositionChange(null);
+ return;
+ }
+
+ updateSidebarPanelMenuPosition();
+
+ const handlePositionUpdate = () => updateSidebarPanelMenuPosition();
+ window.addEventListener("resize", handlePositionUpdate);
+ window.addEventListener("scroll", handlePositionUpdate, true);
+
+ return () => {
+ window.removeEventListener("resize", handlePositionUpdate);
+ window.removeEventListener("scroll", handlePositionUpdate, true);
+ };
+ }, [onSidebarPanelPositionChange, open, updateSidebarPanelMenuPosition, variant]);
+
+ return null;
+}
+
export const WorkspaceMenuRoot = observer(function WorkspaceMenuRoot(props: WorkspaceMenuRootProps) {
const { variant } = props;
// store hooks
@@ -48,7 +98,6 @@ export const WorkspaceMenuRoot = observer(function WorkspaceMenuRoot(props: Work
// translation
const { t } = useTranslation();
// local state
- const [isWorkspaceMenuOpen, setIsWorkspaceMenuOpen] = useState(false);
const [sidebarPanelMenuPosition, setSidebarPanelMenuPosition] = useState<{
left: number;
top: number;
@@ -77,40 +126,6 @@ export const WorkspaceMenuRoot = observer(function WorkspaceMenuRoot(props: Work
const workspacesList = orderWorkspacesList(Object.values(workspaces ?? {}));
// TODO: fix workspaces list scroll
- const updateSidebarPanelMenuPosition = useCallback(() => {
- if (variant !== "sidebar-panel" || !sidebarPanelButtonRef.current || typeof window === "undefined") return;
-
- const rect = sidebarPanelButtonRef.current.getBoundingClientRect();
- const width = 480;
- const viewportPadding = 16;
-
- setSidebarPanelMenuPosition({
- left: Math.min(rect.left, window.innerWidth - width - viewportPadding),
- top: rect.bottom + 8,
- width,
- });
- }, [variant]);
-
- // Toggle sidebar dropdown state when either menu is open
- useEffect(() => {
- toggleAnySidebarDropdown(isWorkspaceMenuOpen);
- }, [isWorkspaceMenuOpen, toggleAnySidebarDropdown]);
-
- useLayoutEffect(() => {
- if (!isWorkspaceMenuOpen || variant !== "sidebar-panel") return;
-
- updateSidebarPanelMenuPosition();
-
- const handlePositionUpdate = () => updateSidebarPanelMenuPosition();
- window.addEventListener("resize", handlePositionUpdate);
- window.addEventListener("scroll", handlePositionUpdate, true);
-
- return () => {
- window.removeEventListener("resize", handlePositionUpdate);
- window.removeEventListener("scroll", handlePositionUpdate, true);
- };
- }, [isWorkspaceMenuOpen, updateSidebarPanelMenuPosition, variant]);
-
return (