diff --git a/web/src/components/MobileHeader.tsx b/web/src/components/MobileHeader.tsx index 8b5923a2e..273754b4b 100644 --- a/web/src/components/MobileHeader.tsx +++ b/web/src/components/MobileHeader.tsx @@ -25,7 +25,10 @@ const MobileHeader = (props: Props) => { )} > {!sm && } -
{children}
+
+
+ {children} +
); }; diff --git a/web/src/components/PagedMemoList/PagedMemoList.tsx b/web/src/components/PagedMemoList/PagedMemoList.tsx index bda7ab415..88f6d4590 100644 --- a/web/src/components/PagedMemoList/PagedMemoList.tsx +++ b/web/src/components/PagedMemoList/PagedMemoList.tsx @@ -2,6 +2,7 @@ import { useQueryClient } from "@tanstack/react-query"; import toast from "react-hot-toast"; import { ArchiveIcon, ArrowUpIcon, BookmarkPlusIcon, TrashIcon, XIcon } from "lucide-react"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { createPortal } from "react-dom"; import { matchPath } from "react-router-dom"; import { Button } from "@/components/ui/button"; import ConfirmDialog from "@/components/ConfirmDialog"; @@ -91,6 +92,7 @@ const PagedMemoList = (props: Props) => { const queryClient = useQueryClient(); const [isSelectionMode, setIsSelectionMode] = useState(false); const [selectedMemoNames, setSelectedMemoNames] = useState>(() => new Set()); + const [selectionBarContainer, setSelectionBarContainer] = useState(null); // Show memo editor only on the root route const showMemoEditor = Boolean(matchPath(Routes.ROOT, window.location.pathname)); @@ -175,6 +177,10 @@ const PagedMemoList = (props: Props) => { onFetchNext: fetchNextPage, }); + useEffect(() => { + setSelectionBarContainer(document.getElementById("memo-selection-actions")); + }, []); + useEffect(() => { if (!isSelectionMode || selectedMemoNames.size === 0) return; const memoNameSet = new Set(sortedMemoList.map((memo) => memo.name)); @@ -209,6 +215,7 @@ const PagedMemoList = (props: Props) => { const children = (
+ {/* Show skeleton loader during initial load */} {isLoading ? ( @@ -219,7 +226,6 @@ const PagedMemoList = (props: Props) => { renderer={props.renderer} prefixElement={ <> - {showMemoEditor ? ( ) : undefined} @@ -291,14 +297,14 @@ const BackToTop = () => { export default PagedMemoList; -const MemoSelectionBar = ({ memoList }: { memoList: Memo[] }) => { +const MemoSelectionBar = ({ memoList, container }: { memoList: Memo[]; container: HTMLElement | null }) => { const t = useTranslate(); const selection = useMemoSelection(); const { mutateAsync: updateMemo } = useUpdateMemo(); const { mutateAsync: deleteMemo } = useDeleteMemo(); const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); - if (!selection || !selection.isSelectionMode) { + if (!selection || !selection.isSelectionMode || !container) { return null; } @@ -353,9 +359,9 @@ const MemoSelectionBar = ({ memoList }: { memoList: Memo[] }) => { } }; - return ( -
- {t("memo.selected-count", { count: selectedCount })} + return createPortal( +
+ {t("memo.selected-count", { count: selectedCount })}
+
, + container, ); };