Skip to content

Commit

Permalink
feat: add SiderTrigger
Browse files Browse the repository at this point in the history
  • Loading branch information
condorheroblog committed Oct 17, 2024
1 parent 5095d6e commit a6d8674
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 87 deletions.
118 changes: 64 additions & 54 deletions src/layout/container-layout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ import { Drawer, theme } from "antd";
import KeepAlive, { useKeepaliveRef } from "keepalive-for-react";
import { useEffect, useMemo, useState } from "react";
import { createUseStyles } from "react-jss";

import { useLocation, useOutlet } from "react-router-dom";

import BasicTabs from "../basic-tabs";
import Footer from "../footer";
import Header from "../header";
import Logo from "../logo";
import SiderMenu from "../sider-menu";
import SiderTrigger from "../sider-trigger";
import { LayoutContext } from "./layout-context";

const useStyles = createUseStyles({
drawerStyles: {
Expand All @@ -23,7 +24,6 @@ const useStyles = createUseStyles({
},
},
"& .ant-drawer-header": {
// backgroundColor: "#001529",
display: "none",
},
},
Expand Down Expand Up @@ -72,62 +72,72 @@ export default function ContainerLayout() {
});
}, [openTabs]);

const layoutContextValue = useMemo(() => ({ collapsed, setCollapsed }), [collapsed, setCollapsed]);

return (
<section className={cn("md:pl-52 transition-all flex flex-col h-screen", { "md:pl-0": isMaximize })}>
<Header
collapsed={collapsed}
setCollapsed={setCollapsed}
/>
<BasicTabs />
{isMobile
? (
<Drawer
open={collapsed}
placement="left"
width="clamp(200px, 50vw, 210px)"
className={classes.drawerStyles}
onClose={() => setCollapsed(false)}
>
<SiderMenu />
</Drawer>
)
: (
<aside
style={
{
backgroundColor: colorBgContainer,
boxShadow: "3px 0 5px 0 rgb(29, 35, 41, 0.05)",
}
}
className={cn("fixed left-0 top-0 bottom-0 transition-all overflow-y-auto w-52", { "w-0": isMaximize })}
>
<Logo collapsed={collapsed} />
<SiderMenu />
</aside>
)}
<main
className="overflow-y-auto p-4 flex-grow"
style={
{
backgroundColor: colorBgLayout,
}
}
<LayoutContext.Provider value={layoutContextValue}>
<section className={cn(
"transition-all flex flex-col h-screen",
collapsed ? "md:pl-14" : "md:pl-52",
{ "md:pl-0": isMaximize },
)}
>
{!isRefresh
<Header />
<BasicTabs />
{isMobile
? (
<KeepAlive
max={20}
strategy="PRE"
activeName={cacheKey}
aliveRef={aliveRef}
<Drawer
open={collapsed}
placement="left"
width="clamp(200px, 50vw, 210px)"
className={classes.drawerStyles}
onClose={() => setCollapsed(false)}
>
{outlet}
</KeepAlive>
<SiderMenu />
</Drawer>
)
: null}
</main>
<Footer />
</section>

: (
<aside
style={
{
backgroundColor: colorBgContainer,
boxShadow: "3px 0 5px 0 rgb(29, 35, 41, 0.05)",
}
}
className={cn(
"fixed left-0 top-0 bottom-0 transition-all overflow-y-auto",
collapsed ? "md:w-14" : "md:w-52",
{ "md:w-0": isMaximize },
)}
>
<Logo collapsed={collapsed} />
<SiderMenu />
<SiderTrigger />
</aside>
)}
<main
className="overflow-y-auto p-4 flex-grow"
style={
{
backgroundColor: colorBgLayout,
}
}
>
{!isRefresh
? (
<KeepAlive
max={20}
strategy="PRE"
activeName={cacheKey}
aliveRef={aliveRef}
>
{outlet}
</KeepAlive>
)
: null}
</main>
<Footer />
</section>
</LayoutContext.Provider>
);
}
9 changes: 9 additions & 0 deletions src/layout/container-layout/layout-context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { createContext } from "react";

export const LayoutContext = createContext<{
collapsed: boolean
setCollapsed: React.Dispatch<React.SetStateAction<boolean>>
}>({
collapsed: false,
setCollapsed: () => { },
});
2 changes: 1 addition & 1 deletion src/layout/footer/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export default function Footer() {
return (
<footer
className="px-0 py-3 flex justify-center text-xs md:text-sm dark:bg-black"
className="h-10 flex items-center justify-center text-xs md:text-sm dark:bg-black"
>
Copyright &copy; 2023 Condor Hero All right reserved
</footer>
Expand Down
9 changes: 5 additions & 4 deletions src/layout/header/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { LayoutContext } from "#src/layout/container-layout/layout-context";
import { useGlobalStore, useTabsStore } from "#src/store";
import { cn } from "#src/utils";
import { MenuFoldOutlined, MenuUnfoldOutlined } from "@ant-design/icons";
import { Button, theme } from "antd";

import { useContext } from "react";
import { createUseStyles } from "react-jss";

import BreadcrumbViews from "../breadcrumb-views";
import { FullscreenMenu } from "./components/fullscreen-menu";
import { LanguageMenu } from "./components/language-menu";
Expand Down Expand Up @@ -36,15 +38,14 @@ const useStyles = createUseStyles(({ token }) => {

export interface HeaderProps {
className?: string
collapsed: boolean
setCollapsed: (collapsed: boolean) => void
}

export default function Header({ className, collapsed, setCollapsed }: HeaderProps) {
export default function Header({ className }: HeaderProps) {
const {
token: { colorBgContainer },
} = theme.useToken();
const classes = useStyles();
const { collapsed, setCollapsed } = useContext(LayoutContext);
const isMobile = useGlobalStore(state => state.isMobile);
const isMaximize = useTabsStore(state => state.isMaximize);

Expand Down
1 change: 1 addition & 0 deletions src/layout/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export { default as Header } from "./header";
export { default as Logo } from "./logo";
export { default as ParentLayout } from "./parent-layout";
export { default as SiderMenu } from "./sider-menu";
export { default as SiderTrigger } from "./sider-trigger";
39 changes: 14 additions & 25 deletions src/layout/logo/index.tsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,33 @@
import logo from "#src/assets/images/logo.svg";
import { Typography } from "antd";
import { createUseStyles } from "react-jss";
import { clsx } from "clsx";

import { useNavigate } from "react-router-dom";

const { Title } = Typography;

const useStyles = createUseStyles({
logoContainer: {
"display": "flex",
"justifyContent": "center",
"alignItems": "center",
"gap": "0.5em",
"height": "3.5em",
"&:hover": {
cursor: "pointer",
},
},
logo: {
width: "2.4em",
},
});

export interface LogoProps {
collapsed: boolean
}

export default function Logo({ collapsed }: LogoProps) {
const classes = useStyles();
const navigate = useNavigate();

return (
<div className={classes.logoContainer} onClick={() => navigate(import.meta.env.VITE_BASE_HOME_PATH)}>
<img src={logo} alt="logo" className={classes.logo} />
<div
// 和 header 高度保持一致
className="h-12 flex items-center justify-center gap-2 cursor-pointer"
onClick={() => navigate(import.meta.env.VITE_BASE_HOME_PATH)}
>
<img
src={logo}
alt="logo"
width={32}
height={32}
/>

<Title level={1} className={clsx("!text-sm !m-0", { hidden: collapsed })} ellipsis={true}>React Antd Admin</Title>

{collapsed
? null
: (
<Title level={1} className="!text-sm !m-0" ellipsis={true}>React Antd Admin</Title>
)}
</div>
);
}
5 changes: 4 additions & 1 deletion src/layout/sider-menu/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import type { MenuProps } from "antd";
import type { ItemType } from "antd/es/menu/interface";

import { LayoutContext } from "#src/layout/container-layout/layout-context";
import { useGlobalStore, usePermissionStore, useUserStore } from "#src/store";
import { Menu } from "antd";
import { useEffect, useMemo, useState } from "react";
import { useContext, useEffect, useMemo, useState } from "react";
import { useMatches, useNavigate } from "react-router-dom";

export function findChildrenLen(menuItems: ItemType[], targetKey: string) {
Expand All @@ -21,6 +22,7 @@ export function findChildrenLen(menuItems: ItemType[], targetKey: string) {
export default function SiderMenu() {
const matches = useMatches();
const navigate = useNavigate();
const { collapsed } = useContext(LayoutContext);
const [openKeys, setOpenKeys] = useState<string[]>([]);
const lng = useUserStore(state => state.lng);
const isMobile = useGlobalStore(state => state.isMobile);
Expand Down Expand Up @@ -62,6 +64,7 @@ export default function SiderMenu() {
return (
<Menu
className="!border-none"
inlineCollapsed={isMobile ? false : collapsed}
// menuItem key is not changed when language changes
key={lng}
style={{ height: isMobile ? "100%" : "initial" }}
Expand Down
25 changes: 25 additions & 0 deletions src/layout/sider-trigger/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { BasicButton } from "#src/components";
import { LayoutContext } from "#src/layout/container-layout/layout-context";
import { cn } from "#src/utils";

import { MenuFoldOutlined, MenuUnfoldOutlined } from "@ant-design/icons";
import { useContext } from "react";

interface SiderTriggerProps {
className?: string
}
export default function SiderTrigger({ className }: SiderTriggerProps) {
const { collapsed, setCollapsed } = useContext(LayoutContext);

return (
<BasicButton
type="text"
style={{
boxShadow: "0px -3px 5px 0 rgb(29, 35, 41, 0.05)",
}}
icon={collapsed ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
onClick={() => setCollapsed(!collapsed)}
className={cn(className, "absolute bottom-0 h-10 !w-full rounded-none border border-t-gray-200")}
/>
);
}
16 changes: 14 additions & 2 deletions src/styles/antdTheme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@ import type { ThemeConfig } from "antd";
* @see https://ant.design/theme-editor (English version)
* @see https://ant.design/docs/react/customize-theme (English version configuration guide)
*/
export const customAntdLightTheme: ThemeConfig = {};
export const customAntdLightTheme: ThemeConfig = {
components: {
Menu: {
collapsedWidth: 56,
},
},
};

/**
* 自定义的Ant Design深色主题配置
Expand All @@ -22,4 +28,10 @@ export const customAntdLightTheme: ThemeConfig = {};
* @see https://ant.design/theme-editor (English version)
* @see https://ant.design/docs/react/customize-theme (English version configuration guide)
*/
export const customAntdDarkTheme: ThemeConfig = {};
export const customAntdDarkTheme: ThemeConfig = {
components: {
Menu: {
collapsedWidth: 56,
},
},
};

0 comments on commit a6d8674

Please sign in to comment.