mirror of https://github.com/usememos/memos.git
refactor: update root layout
This commit is contained in:
parent
505fee1abb
commit
2ed3e34636
|
|
@ -18,7 +18,7 @@
|
|||
}
|
||||
</script>
|
||||
</head>
|
||||
<body class="text-base w-full min-h-[100svh] bg-zinc-100 dark:bg-zinc-900">
|
||||
<body class="text-base w-full min-h-[100svh] bg-zinc-50 dark:bg-zinc-900">
|
||||
<div id="root" class="relative w-full min-h-full"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
<!-- memos.metadata.body -->
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import StatisticsView from "@/components/StatisticsView";
|
|||
import useCurrentUser from "@/hooks/useCurrentUser";
|
||||
import { useMemoList, useUserStatsStore } from "@/store/v1";
|
||||
import { cn } from "@/utils";
|
||||
import MemoFilters from "../MemoFilters";
|
||||
import ShortcutsSection from "./ShortcutsSection";
|
||||
import TagsSection from "./TagsSection";
|
||||
|
||||
|
|
@ -25,13 +26,9 @@ const HomeSidebar = (props: Props) => {
|
|||
);
|
||||
|
||||
return (
|
||||
<aside
|
||||
className={cn(
|
||||
"relative w-full h-auto max-h-screen overflow-auto hide-scrollbar flex flex-col justify-start items-start",
|
||||
props.className,
|
||||
)}
|
||||
>
|
||||
<aside className={cn("relative w-full h-full overflow-auto hide-scrollbar flex flex-col justify-start items-start", props.className)}>
|
||||
<SearchBar />
|
||||
<MemoFilters />
|
||||
<StatisticsView />
|
||||
<ShortcutsSection />
|
||||
<TagsSection />
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
import { isEqual } from "lodash-es";
|
||||
import { CalendarIcon, CheckCircleIcon, CodeIcon, EyeIcon, FilterIcon, HashIcon, LinkIcon, SearchIcon, XIcon } from "lucide-react";
|
||||
import { CalendarIcon, CheckCircleIcon, CodeIcon, EyeIcon, HashIcon, LinkIcon, SearchIcon, XIcon } from "lucide-react";
|
||||
import { useEffect, useRef } from "react";
|
||||
import { useSearchParams } from "react-router-dom";
|
||||
import { FilterFactor, getMemoFilterKey, MemoFilter, parseFilterQuery, stringifyFilters, useMemoFilterStore } from "@/store/v1";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
|
||||
const MemoFilters = () => {
|
||||
const t = useTranslate();
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
const memoFilterStore = useMemoFilterStore();
|
||||
const filters = memoFilterStore.filters;
|
||||
|
|
@ -74,26 +72,20 @@ const MemoFilters = () => {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="w-full mb-2 flex flex-row justify-start items-start gap-2">
|
||||
<span className="flex flex-row items-center gap-0.5 text-gray-500 text-sm leading-7 border border-transparent">
|
||||
<FilterIcon className="w-4 h-auto opacity-60 inline" />
|
||||
{t("memo.filters")}
|
||||
</span>
|
||||
<div className="flex flex-row justify-start items-center flex-wrap gap-x-2 gap-y-1 leading-7 h-7">
|
||||
{filters.map((filter) => (
|
||||
<div
|
||||
key={getMemoFilterKey(filter)}
|
||||
className="w-auto h-full flex flex-row items-center gap-1 bg-white dark:bg-zinc-800 border dark:border-zinc-700 pl-1.5 pr-1 rounded-md hover:line-through cursor-pointer"
|
||||
onClick={() => memoFilterStore.removeFilter((f) => isEqual(f, filter))}
|
||||
>
|
||||
<FactorIcon className="w-4 h-auto text-gray-500 dark:text-gray-400 opacity-60" factor={filter.factor} />
|
||||
<span className="text-gray-500 dark:text-gray-400 text-sm max-w-32 truncate">{getFilterDisplayText(filter)}</span>
|
||||
<button className="text-gray-500 dark:text-gray-300 opacity-60 hover:opacity-100">
|
||||
<XIcon className="w-4 h-auto" />
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="w-full mt-3 flex flex-row justify-start items-center flex-wrap gap-x-2 gap-y-1">
|
||||
{filters.map((filter) => (
|
||||
<div
|
||||
key={getMemoFilterKey(filter)}
|
||||
className="w-auto leading-7 h-7 shrink-0 flex flex-row items-center gap-1 bg-white dark:bg-zinc-800 border dark:border-zinc-700 pl-1.5 pr-1 rounded-md hover:line-through cursor-pointer"
|
||||
onClick={() => memoFilterStore.removeFilter((f) => isEqual(f, filter))}
|
||||
>
|
||||
<FactorIcon className="w-4 h-auto text-gray-500 dark:text-gray-400 opacity-60" factor={filter.factor} />
|
||||
<span className="text-gray-500 dark:text-gray-400 text-sm max-w-32 truncate">{getFilterDisplayText(filter)}</span>
|
||||
<button className="text-gray-500 dark:text-gray-300 opacity-60 hover:opacity-100">
|
||||
<XIcon className="w-4 h-auto" />
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ const MobileHeader = (props: Props) => {
|
|||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"sticky top-0 pt-3 pb-2 sm:pt-2 px-4 sm:px-6 sm:mb-1 bg-zinc-100 dark:bg-zinc-900 bg-opacity-80 backdrop-blur-lg flex md:hidden flex-row justify-between items-center w-full h-auto flex-nowrap shrink-0 z-1",
|
||||
"sticky top-0 pt-3 pb-2 sm:pt-2 px-4 sm:px-6 sm:mb-1 bg-zinc-50 dark:bg-zinc-900 bg-opacity-80 backdrop-blur-lg flex md:hidden flex-row justify-between items-center w-full h-auto flex-nowrap shrink-0 z-1",
|
||||
offsetTop > 0 && "shadow-md",
|
||||
className,
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ const StatisticsView = () => {
|
|||
};
|
||||
|
||||
return (
|
||||
<div className="group w-full mt-4 space-y-1 text-gray-500 dark:text-gray-400">
|
||||
<div className="group w-full mt-3 space-y-1 text-gray-500 dark:text-gray-400">
|
||||
<div className="w-full mb-1 flex flex-row justify-between items-center gap-1">
|
||||
<div className="relative text-sm font-medium inline-flex flex-row items-center w-auto dark:text-gray-400 truncate">
|
||||
<span className="truncate">
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ const UserBanner = (props: Props) => {
|
|||
<MenuButton disabled={!user} slots={{ root: "div" }}>
|
||||
<div
|
||||
className={cn(
|
||||
"py-1 my-1 w-auto flex flex-row justify-start items-center cursor-pointer text-gray-800 dark:text-gray-400",
|
||||
"py-1 w-auto flex flex-row justify-start items-center cursor-pointer text-gray-800 dark:text-gray-400",
|
||||
collapsed ? "px-1" : "px-3",
|
||||
)}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,5 @@
|
|||
import { Tooltip } from "@mui/joy";
|
||||
import { Button } from "@usememos/mui";
|
||||
import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
|
||||
import { Suspense, useEffect, useMemo, useState } from "react";
|
||||
import { Outlet, useLocation, useSearchParams } from "react-router-dom";
|
||||
import useLocalStorage from "react-use/lib/useLocalStorage";
|
||||
import usePrevious from "react-use/lib/usePrevious";
|
||||
import Navigation from "@/components/Navigation";
|
||||
import useCurrentUser from "@/hooks/useCurrentUser";
|
||||
|
|
@ -12,16 +8,13 @@ import Loading from "@/pages/Loading";
|
|||
import { Routes } from "@/router";
|
||||
import { useMemoFilterStore } from "@/store/v1";
|
||||
import { cn } from "@/utils";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
|
||||
const RootLayout = () => {
|
||||
const t = useTranslate();
|
||||
const location = useLocation();
|
||||
const [searchParams] = useSearchParams();
|
||||
const { sm } = useResponsiveWidth();
|
||||
const currentUser = useCurrentUser();
|
||||
const memoFilterStore = useMemoFilterStore();
|
||||
const [collapsed, setCollapsed] = useLocalStorage<boolean>("navigation-collapsed", false);
|
||||
const [initialized, setInitialized] = useState(false);
|
||||
const pathname = useMemo(() => location.pathname, [location.pathname]);
|
||||
const prevPathname = usePrevious(pathname);
|
||||
|
|
@ -47,34 +40,15 @@ const RootLayout = () => {
|
|||
<Loading />
|
||||
) : (
|
||||
<div className="w-full min-h-full">
|
||||
<div className={cn("w-full transition-all mx-auto flex flex-row justify-center items-start", collapsed ? "sm:pl-16" : "sm:pl-56")}>
|
||||
<div className={cn("w-full transition-all mx-auto flex flex-row justify-center items-start", "sm:pl-16")}>
|
||||
{sm && (
|
||||
<div
|
||||
className={cn(
|
||||
"group flex flex-col justify-start items-start fixed top-0 left-0 select-none border-r dark:border-zinc-800 h-full bg-zinc-50 dark:bg-zinc-800 dark:bg-opacity-40 transition-all hover:shadow-xl z-2",
|
||||
collapsed ? "w-16 px-2" : "w-56 px-4",
|
||||
"group flex flex-col justify-start items-start fixed top-0 left-0 select-none border-r dark:border-zinc-800 h-full bg-zinc-100 dark:bg-zinc-800 dark:bg-opacity-40 transition-all hover:shadow-xl z-2",
|
||||
"w-16 px-2",
|
||||
)}
|
||||
>
|
||||
<Navigation className="!h-auto" collapsed={collapsed} />
|
||||
<div className={cn("w-full grow h-auto flex flex-col justify-end", collapsed ? "items-center" : "items-start")}>
|
||||
<div
|
||||
className={cn("hidden py-3 group-hover:flex flex-col justify-center items-center")}
|
||||
onClick={() => setCollapsed(!collapsed)}
|
||||
>
|
||||
{!collapsed ? (
|
||||
<Button className="rounded-xl" variant="plain">
|
||||
<ChevronLeftIcon className="w-5 h-auto opacity-70 mr-1" />
|
||||
{t("common.collapse")}
|
||||
</Button>
|
||||
) : (
|
||||
<Tooltip title={t("common.expand")} placement="right" arrow>
|
||||
<Button className="rounded-xl" variant="plain">
|
||||
<ChevronRightIcon className="w-5 h-auto opacity-70" />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<Navigation collapsed={true} />
|
||||
</div>
|
||||
)}
|
||||
<main className="w-full h-auto flex-grow shrink flex flex-col justify-start items-center">
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import dayjs from "dayjs";
|
||||
import { useMemo } from "react";
|
||||
import { ExploreSidebar, ExploreSidebarDrawer } from "@/components/ExploreSidebar";
|
||||
import MemoFilters from "@/components/MemoFilters";
|
||||
import MemoView from "@/components/MemoView";
|
||||
import MobileHeader from "@/components/MobileHeader";
|
||||
import PagedMemoList from "@/components/PagedMemoList";
|
||||
|
|
@ -13,7 +12,7 @@ import { Memo } from "@/types/proto/api/v1/memo_service";
|
|||
import { cn } from "@/utils";
|
||||
|
||||
const Explore = () => {
|
||||
const { md } = useResponsiveWidth();
|
||||
const { md, lg } = useResponsiveWidth();
|
||||
const user = useCurrentUser();
|
||||
const memoFilterStore = useMemoFilterStore();
|
||||
|
||||
|
|
@ -50,15 +49,25 @@ const Explore = () => {
|
|||
}, [user, memoFilterStore.filters, memoFilterStore.orderByTimeAsc]);
|
||||
|
||||
return (
|
||||
<section className="@container w-full max-w-5xl min-h-full flex flex-col justify-start items-center sm:pt-3 md:pt-6 pb-8">
|
||||
<section className="@container w-full min-h-full flex flex-col justify-start items-center">
|
||||
{!md && (
|
||||
<MobileHeader>
|
||||
<ExploreSidebarDrawer />
|
||||
</MobileHeader>
|
||||
)}
|
||||
<div className={cn("w-full flex flex-row justify-start items-start px-4 sm:px-6 gap-4")}>
|
||||
<div className={cn(md ? "w-[calc(100%-15rem)]" : "w-full")}>
|
||||
<MemoFilters />
|
||||
<div className={cn("w-full min-h-full flex flex-row justify-start items-start")}>
|
||||
{md && (
|
||||
<div
|
||||
className={cn(
|
||||
"sticky top-0 left-0 shrink-0 h-[100svh] transition-all",
|
||||
"border-r border-gray-200 dark:border-zinc-800",
|
||||
lg ? "px-5 w-72" : "px-4 w-56",
|
||||
)}
|
||||
>
|
||||
<ExploreSidebar className={cn("py-6")} />
|
||||
</div>
|
||||
)}
|
||||
<div className={cn("w-full mx-auto px-4 sm:px-6 sm:pt-3 md:pt-6 pb-8", md && "max-w-3xl")}>
|
||||
<div className="flex flex-col justify-start items-start w-full max-w-full">
|
||||
<PagedMemoList
|
||||
renderer={(memo: Memo) => <MemoView key={`${memo.name}-${memo.updateTime}`} memo={memo} showCreator showVisibility compact />}
|
||||
|
|
@ -76,11 +85,6 @@ const Explore = () => {
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
{md && (
|
||||
<div className="sticky top-0 left-0 shrink-0 -mt-6 w-56 h-full">
|
||||
<ExploreSidebar className="py-6" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import dayjs from "dayjs";
|
|||
import { useMemo } from "react";
|
||||
import { HomeSidebar, HomeSidebarDrawer } from "@/components/HomeSidebar";
|
||||
import MemoEditor from "@/components/MemoEditor";
|
||||
import MemoFilters from "@/components/MemoFilters";
|
||||
import MemoView from "@/components/MemoView";
|
||||
import MobileHeader from "@/components/MobileHeader";
|
||||
import PagedMemoList from "@/components/PagedMemoList";
|
||||
|
|
@ -14,7 +13,7 @@ import { Memo } from "@/types/proto/api/v1/memo_service";
|
|||
import { cn } from "@/utils";
|
||||
|
||||
const Home = () => {
|
||||
const { md } = useResponsiveWidth();
|
||||
const { md, lg } = useResponsiveWidth();
|
||||
const user = useCurrentUser();
|
||||
const userStore = useUserStore();
|
||||
const memoFilterStore = useMemoFilterStore();
|
||||
|
|
@ -53,16 +52,26 @@ const Home = () => {
|
|||
}, [user, memoFilterStore.filters, memoFilterStore.orderByTimeAsc]);
|
||||
|
||||
return (
|
||||
<section className="@container w-full max-w-5xl min-h-full flex flex-col justify-start items-center sm:pt-3 md:pt-6 pb-8">
|
||||
<section className="@container w-full min-h-full flex flex-col justify-start items-center">
|
||||
{!md && (
|
||||
<MobileHeader>
|
||||
<HomeSidebarDrawer />
|
||||
</MobileHeader>
|
||||
)}
|
||||
<div className={cn("w-full flex flex-row justify-start items-start px-4 sm:px-6 gap-4")}>
|
||||
<div className={cn(md ? "w-[calc(100%-15rem)]" : "w-full")}>
|
||||
<div className={cn("w-full min-h-full flex flex-row justify-start items-start")}>
|
||||
{md && (
|
||||
<div
|
||||
className={cn(
|
||||
"sticky top-0 left-0 shrink-0 h-[100svh] transition-all",
|
||||
"border-r border-gray-200 dark:border-zinc-800",
|
||||
lg ? "px-5 w-72" : "px-4 w-56",
|
||||
)}
|
||||
>
|
||||
<HomeSidebar className={cn("py-6")} />
|
||||
</div>
|
||||
)}
|
||||
<div className={cn("w-full mx-auto px-4 sm:px-6 sm:pt-3 md:pt-6 pb-8", md && "max-w-3xl")}>
|
||||
<MemoEditor className="mb-2" cacheKey="home-memo-editor" />
|
||||
<MemoFilters />
|
||||
<div className="flex flex-col justify-start items-start w-full max-w-full">
|
||||
<PagedMemoList
|
||||
renderer={(memo: Memo) => <MemoView key={`${memo.name}-${memo.displayTime}`} memo={memo} showVisibility showPinned compact />}
|
||||
|
|
@ -83,11 +92,6 @@ const Home = () => {
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
{md && (
|
||||
<div className="sticky top-0 left-0 shrink-0 -mt-6 w-56 h-full">
|
||||
<HomeSidebar className="py-6" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in New Issue