Skip to content

Commit abc143f

Browse files
committed
feat: move homepage's sidebar contents into drawer on mobile
1 parent 7d09188 commit abc143f

File tree

9 files changed

+244
-180
lines changed

9 files changed

+244
-180
lines changed

src/apis/announcement.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ export function useAnnouncement() {
2020
.then((res) => res.text())
2121
.catch((e) => {
2222
if ((e as Error).message === 'Failed to fetch') {
23-
console.warn(e)
2423
throw new Error('网络错误')
2524
}
2625

src/components/NavExpandButton.tsx

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,13 @@ import { navAtom, toggleExpandNavAtom } from 'store/nav'
66

77
export const NavExpandButton = () => {
88
const expanded = useAtomValue(navAtom)
9-
const toggleExpaned = useSetAtom(toggleExpandNavAtom)
9+
const toggleExpand = useSetAtom(toggleExpandNavAtom)
1010

1111
return (
12-
<div className="sm:hidden">
13-
<Button
14-
onClick={toggleExpaned}
15-
icon={expanded.expanded ? 'cross' : 'menu'}
16-
/>
17-
</div>
12+
<Button
13+
className="md:!hidden"
14+
onClick={() => toggleExpand()}
15+
icon={expanded.expanded ? 'cross' : 'menu'}
16+
/>
1817
)
1918
}

src/components/announcement/AnnPanel.tsx

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Card, Icon } from '@blueprintjs/core'
22

33
import clsx from 'clsx'
4-
import { FC, useEffect, useMemo, useState } from 'react'
4+
import { FC, ReactNode, useEffect, useMemo, useState } from 'react'
55

66
import { useAnnouncement } from '../../apis/announcement'
77
import {
@@ -15,9 +15,10 @@ import { AnnDialog } from './AnnDialog'
1515

1616
interface AnnPanelProps {
1717
className?: string
18+
trigger?: (params: { handleClick: () => void }) => ReactNode
1819
}
1920

20-
export const AnnPanel: FC<AnnPanelProps> = ({ className }) => {
21+
export const AnnPanel: FC<AnnPanelProps> = ({ className, trigger }) => {
2122
const { data, error } = useAnnouncement()
2223
const announcement = useMemo(
2324
() => (data ? parseAnnouncement(data) : undefined),
@@ -45,34 +46,36 @@ export const AnnPanel: FC<AnnPanelProps> = ({ className }) => {
4546
}
4647
}, [announcement, lastNoticed, setLastNoticed])
4748

49+
const handleClick = () => {
50+
setIsOpen({ yes: true, manually: true })
51+
setDisplaySections(announcement?.sections)
52+
}
53+
54+
trigger ??= ({ handleClick }) => (
55+
<Card interactive className={clsx(className)} onClick={handleClick}>
56+
<CardTitle icon="info-sign">公告</CardTitle>
57+
58+
<div className="flex">
59+
{announcement && (
60+
<ul className="grow list-disc pl-4">
61+
{announcement?.sections
62+
.slice(0, 3)
63+
.map(({ title }) => <li key={title}>{title}</li>)}
64+
</ul>
65+
)}
66+
{!announcement && error && (
67+
<div className="grow text-red-500">
68+
公告加载失败:{formatError(error)}
69+
</div>
70+
)}
71+
<Icon className="self-end" icon="more" size={14} />
72+
</div>
73+
</Card>
74+
)
75+
4876
return (
4977
<>
50-
<Card
51-
interactive
52-
className={clsx(className)}
53-
onClick={() => {
54-
setIsOpen({ yes: true, manually: true })
55-
setDisplaySections(announcement?.sections)
56-
}}
57-
>
58-
<CardTitle icon="info-sign">公告</CardTitle>
59-
60-
<div className="flex">
61-
{announcement && (
62-
<ul className="grow list-disc pl-4">
63-
{announcement?.sections
64-
.slice(0, 3)
65-
.map(({ title }) => <li key={title}>{title}</li>)}
66-
</ul>
67-
)}
68-
{!announcement && error && (
69-
<div className="grow text-red-500">
70-
公告加载失败:{formatError(error)}
71-
</div>
72-
)}
73-
<Icon className="self-end" icon="more" size={14} />
74-
</div>
75-
</Card>
78+
{trigger({ handleClick })}
7679
<AnnDialog
7780
sections={displaySections}
7881
isOpen={!!isOpen?.yes}

src/components/drawer/NavAside.tsx

Lines changed: 84 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,100 @@
1-
import { Button, Portal } from '@blueprintjs/core'
1+
import { Drawer, Menu, MenuDivider } from '@blueprintjs/core'
2+
import { MenuItem2 } from '@blueprintjs/popover2'
23

34
import { useAtomValue, useSetAtom } from 'jotai'
4-
import { LINKS } from 'layouts/AppLayout'
5+
import { useState } from 'react'
56
import { NavLink } from 'react-router-dom'
67

78
import { navAtom, toggleExpandNavAtom } from 'store/nav'
89

10+
import { NAV_LINKS, SOCIAL_LINKS } from '../../links'
11+
import { useCurrentSize } from '../../utils/useCurrenSize'
12+
import { AnnPanel } from '../announcement/AnnPanel'
13+
import { OperationSetEditorDialog } from '../operation-set/OperationSetEditor'
14+
915
export const NavAside = () => {
16+
const { isMD } = useCurrentSize()
1017
const nav = useAtomValue(navAtom)
1118
const toggleNav = useSetAtom(toggleExpandNavAtom)
12-
const navLinks = [...LINKS]
1319

14-
if (!nav.expanded) return null
20+
const [showOperationSetDialog, setShowOperationSetDialog] = useState(false)
21+
22+
if (!isMD) return null
1523

1624
return (
17-
<Portal>
18-
{/* todo: 这里可以重写移动端header 需要去掉top */}
19-
<div className="fixed inset-0 top-14 z-50 overflow-y-auto backdrop-blur-lg sm:hidden">
20-
<div className="px-4 sm:px-6 pt-3 pb-6">
21-
<nav className="flex flex-col gap-3">
22-
{navLinks.map((link) => (
23-
<div className="flex-col w-full" key={link.to}>
24-
<NavLink
25-
to={link.to}
26-
className="text-sm text-zinc-600 dark:text-slate-100 !no-underline"
25+
<>
26+
<Drawer
27+
isOpen={isMD && !!nav.expanded}
28+
onClose={() => toggleNav()}
29+
position="left"
30+
size="100%"
31+
portalClassName="[&>.bp4-overlay-container]:z-10"
32+
backdropClassName="bg-transparent"
33+
className="bg-transparent backdrop-blur-lg overflow-y-auto mt-14 p-2"
34+
>
35+
<Menu className="p-0 space-y-2 bg-transparent font-bold">
36+
{NAV_LINKS.map((link) => (
37+
<NavLink key={link.to} to={link.to} className="block !no-underline">
38+
{({ isActive }) => (
39+
<MenuItem2
40+
key={link.to}
41+
icon={link.icon}
42+
active={isActive}
43+
text={link.label}
44+
className="p-2 rounded-md"
45+
tagName="div"
2746
onClick={() => toggleNav()}
28-
>
29-
{({ isActive }) => (
30-
<Button
31-
minimal
32-
icon={link.icon}
33-
active={isActive}
34-
className="w-full flex items-center"
35-
style={{ justifyContent: 'flex-start' }}
36-
>
37-
{link.label}
38-
</Button>
39-
)}
40-
</NavLink>
41-
</div>
42-
))}
43-
</nav>
47+
/>
48+
)}
49+
</NavLink>
50+
))}
51+
<MenuDivider />
52+
<MenuItem2
53+
icon="folder-new"
54+
text="创建作业集..."
55+
className="p-2 rounded-md"
56+
onClick={() => {
57+
setShowOperationSetDialog(true)
58+
toggleNav()
59+
}}
60+
/>
61+
<AnnPanel
62+
trigger={({ handleClick }) => (
63+
<MenuItem2
64+
icon="info-sign"
65+
text="公告"
66+
className="p-2 rounded-md"
67+
onClick={handleClick}
68+
/>
69+
)}
70+
/>
71+
<MenuDivider />
72+
</Menu>
73+
<div className="flex flex-wrap leading-relaxed mt-2 p-2 section-social-links">
74+
{SOCIAL_LINKS.map((link) => (
75+
<a
76+
href={link.href}
77+
target="_blank"
78+
rel="noopener noreferrer"
79+
className="flex items-center text-zinc-600 dark:text-slate-100 no-underline"
80+
>
81+
{link.icon}
82+
<span>{link.label}</span>
83+
</a>
84+
)).reduce((prev, curr) => (
85+
<>
86+
{prev}
87+
<div className="mx-2 opacity-50">·</div>
88+
{curr}
89+
</>
90+
))}
4491
</div>
45-
</div>
46-
</Portal>
92+
</Drawer>
93+
94+
<OperationSetEditorDialog
95+
isOpen={showOperationSetDialog}
96+
onClose={() => setShowOperationSetDialog(false)}
97+
/>
98+
</>
4799
)
48100
}

src/layouts/AppLayout.tsx

Lines changed: 6 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Button, IconName, Navbar, Tag } from '@blueprintjs/core'
1+
import { Button, Navbar, Tag } from '@blueprintjs/core'
22

33
import { Link, NavLink } from 'react-router-dom'
44
import { FCC } from 'types'
@@ -9,33 +9,13 @@ import { NavExpandButton } from 'components/NavExpandButton'
99
import { ThemeSwitchButton } from 'components/ThemeSwitchButton'
1010
import { NavAside } from 'components/drawer/NavAside'
1111

12-
export const LINKS: {
13-
to: string
14-
label: string
15-
icon: IconName
16-
}[] = [
17-
{
18-
to: '/',
19-
label: '首页',
20-
icon: 'home',
21-
},
22-
{
23-
to: '/create',
24-
label: '创建作业',
25-
icon: 'add',
26-
},
27-
{
28-
to: '/about',
29-
label: '关于',
30-
icon: 'info-sign',
31-
},
32-
]
12+
import { NAV_LINKS } from '../links'
3313

3414
// const darkMode = localStorage.getItem('darkMode') === 'true'
3515

3616
export const AppLayout: FCC = ({ children }) => (
3717
<div className="flex flex-col h-full w-full bg-zinc-50 ">
38-
<Navbar className="flex w-full px-8 py-2 items-center bg-zinc-100 shadow fixed h-14 z-10 whitespace-nowrap overflow-x-none overflow-y-hidden">
18+
<Navbar className="flex w-full px-8 py-2 items-center bg-zinc-100 shadow fixed h-14 z-20 whitespace-nowrap overflow-x-none overflow-y-hidden">
3919
<Link to="/" className="flex items-center hover:no-underline ">
4020
<div className="select-none text-lg font-bold leading-none">
4121
MAA Copilot
@@ -48,8 +28,8 @@ export const AppLayout: FCC = ({ children }) => (
4828

4929
<div className="w-[1px] bg-gray-200 ml-4 mr-2 my-0.5 flex self-stretch" />
5030

51-
<div className="sm:flex items-center hidden">
52-
{LINKS.map((link) => (
31+
<div className="md:flex items-center hidden">
32+
{NAV_LINKS.map((link) => (
5333
<NavLink
5434
key={link.to}
5535
to={link.to}
@@ -66,7 +46,7 @@ export const AppLayout: FCC = ({ children }) => (
6646

6747
<div className="flex-1" />
6848

69-
<div className="flex sm:gap-4 gap-3">
49+
<div className="flex md:gap-4 gap-3">
7050
<NavExpandButton />
7151
<ThemeSwitchButton />
7252
<AccountManager />

src/links.tsx

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { Icon as BlueprintIcon, IconName } from '@blueprintjs/core'
2+
import simpleIconsGitHub from '@iconify/icons-simple-icons/github'
3+
import simpleIconsQQ from '@iconify/icons-simple-icons/tencentqq'
4+
import { Icon as IconifyIcon } from '@iconify/react'
5+
6+
export const NAV_LINKS: {
7+
to: string
8+
label: string
9+
icon: IconName
10+
}[] = [
11+
{
12+
to: '/',
13+
label: '首页',
14+
icon: 'home',
15+
},
16+
{
17+
to: '/create',
18+
label: '创建作业',
19+
icon: 'add',
20+
},
21+
{
22+
to: '/about',
23+
label: '关于',
24+
icon: 'info-sign',
25+
},
26+
]
27+
28+
export const SOCIAL_LINKS = [
29+
{
30+
icon: <BlueprintIcon icon="globe" className="mr-2" size={12} />,
31+
href: 'https://maa.plus',
32+
label: 'MAA 官网',
33+
},
34+
{
35+
icon: <BlueprintIcon icon="edit" className="mr-2" size={12} />,
36+
href: 'https://github.com/MaaAssistantArknights/maa-copilot-frontend/issues/new/choose',
37+
label: '意见与反馈',
38+
},
39+
{
40+
icon: (
41+
<IconifyIcon icon={simpleIconsGitHub} className="mr-2" fontSize="12px" />
42+
),
43+
href: 'https://github.com/MaaAssistantArknights/MaaAssistantArknights',
44+
label: 'MAA GitHub Repo',
45+
},
46+
{
47+
icon: (
48+
<IconifyIcon icon={simpleIconsGitHub} className="mr-2" fontSize="12px" />
49+
),
50+
href: 'https://github.com/MaaAssistantArknights/maa-copilot-frontend',
51+
label: '前端 GitHub Repo',
52+
},
53+
{
54+
icon: (
55+
<IconifyIcon icon={simpleIconsGitHub} className="mr-2" fontSize="12px" />
56+
),
57+
href: 'https://github.com/MaaAssistantArknights/MaaBackendCenter',
58+
label: '后端 GitHub Repo',
59+
},
60+
{
61+
icon: <IconifyIcon icon={simpleIconsQQ} className="mr-2" fontSize="12px" />,
62+
href: 'https://jq.qq.com/?_wv=1027&k=ElimpMzQ',
63+
label: '作业制作者交流群:1169188429',
64+
},
65+
{
66+
icon: <IconifyIcon icon={simpleIconsQQ} className="mr-2" fontSize="12px" />,
67+
href: 'https://ota.maa.plus/MaaAssistantArknights/api/qqgroup/index.html',
68+
label: '作业分享群',
69+
},
70+
]

0 commit comments

Comments
 (0)