Просмотр исходного кода

Remove resize listener and use sm breakpoint for width

satof3 1 месяц назад
Родитель
Сommit
6f7b52914a

+ 19 - 30
apps/app/src/client/components/PageHeader/PageHeader.tsx

@@ -1,6 +1,7 @@
-import { type JSX, useCallback, useEffect, useRef, useState } from 'react';
+import { type JSX, useCallback, useRef } from 'react';
 
 import { useCurrentPageData } from '~/states/page';
+import { useDeviceLargerThanSm } from '~/states/ui/device';
 import { usePageControlsX } from '~/states/ui/page';
 
 import { PagePathHeader } from './PagePathHeader';
@@ -13,48 +14,36 @@ const moduleClass = styles['page-header'] ?? '';
 export const PageHeader = (): JSX.Element => {
   const currentPage = useCurrentPageData();
   const pageControlsX = usePageControlsX();
+  const [isLargerThanSm] = useDeviceLargerThanSm();
   const pageHeaderRef = useRef<HTMLDivElement>(null);
 
-  const [maxWidth, setMaxWidth] = useState<number>(300);
-
   const calcMaxWidth = useCallback(() => {
     if (pageHeaderRef.current == null) {
       return;
     }
 
-    // For mobile screens (< 576px), use full screen width
-    if (window.innerWidth < 576) {
-      const maxWidth =
-        window.innerWidth - pageHeaderRef.current.getBoundingClientRect().x;
-      setMaxWidth(maxWidth);
-      return;
-    }
-
-    if (pageControlsX == null) {
-      return;
-    }
-
-    // PageControls.x - PageHeader.x
-    const maxWidth =
-      pageControlsX - pageHeaderRef.current.getBoundingClientRect().x;
-
-    setMaxWidth(maxWidth);
-  }, [pageControlsX]);
+    const pageHeaderX = pageHeaderRef.current.getBoundingClientRect().x;
+    const maxWidth = !isLargerThanSm
+      ? window.innerWidth - pageHeaderX
+      : pageControlsX != null
+        ? pageControlsX - pageHeaderX
+        : 300;
 
-  useEffect(() => {
-    calcMaxWidth();
-
-    // Recalculate on window resize
-    window.addEventListener('resize', calcMaxWidth);
-    return () => {
-      window.removeEventListener('resize', calcMaxWidth);
-    };
-  }, [calcMaxWidth]);
+    // Update the style directly if needed, or use state management
+    // setMaxWidth(maxWidth);
+  }, [isLargerThanSm, pageControlsX]);
 
   if (currentPage == null) {
     return <></>;
   }
 
+  const pageHeaderX = pageHeaderRef.current?.getBoundingClientRect().x ?? 0;
+  const maxWidth = !isLargerThanSm
+    ? window.innerWidth - pageHeaderX
+    : pageControlsX != null
+      ? pageControlsX - pageHeaderX
+      : 300;
+
   return (
     <div className={`${moduleClass} w-100`} ref={pageHeaderRef}>
       <PagePathHeader

+ 23 - 0
apps/app/src/states/ui/device.ts

@@ -10,6 +10,7 @@ import { atom, useAtom } from 'jotai';
 export const isDeviceLargerThanXlAtom = atom(false);
 export const isDeviceLargerThanLgAtom = atom(false);
 export const isDeviceLargerThanMdAtom = atom(false);
+export const isDeviceLargerThanSmAtom = atom(false);
 export const isMobileAtom = atom(false);
 
 export const useDeviceLargerThanXl = () => {
@@ -78,6 +79,28 @@ export const useDeviceLargerThanMd = () => {
   return [isLargerThanMd, setIsLargerThanMd] as const;
 };
 
+export const useDeviceLargerThanSm = () => {
+  const [isLargerThanSm, setIsLargerThanSm] = useAtom(isDeviceLargerThanSmAtom);
+
+  useEffect(() => {
+    const smOrAboveHandler = function (this: MediaQueryList): void {
+      // xs -> sm: matches will be true
+      // sm -> xs: matches will be false
+      setIsLargerThanSm(this.matches);
+    };
+    const mql = addBreakpointListener(Breakpoint.SM, smOrAboveHandler);
+
+    // initialize
+    setIsLargerThanSm(mql.matches);
+
+    return () => {
+      cleanupBreakpointListener(mql, smOrAboveHandler);
+    };
+  }, [setIsLargerThanSm]);
+
+  return [isLargerThanSm, setIsLargerThanSm] as const;
+};
+
 export const useIsMobile = () => {
   const [isMobile, setIsMobile] = useAtom(isMobileAtom);