Skip to content

Commit c71bee2

Browse files
committed
refactor: 首页适配响应式
1 parent 6e39caa commit c71bee2

File tree

8 files changed

+192
-76
lines changed

8 files changed

+192
-76
lines changed

src/components/AccountManager.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import { LoginPanel } from 'components/account/LoginPanel'
2424
import { EditorFieldProps } from 'components/editor/EditorFieldProps'
2525
import { authAtom } from 'store/auth'
2626
import { NetworkError } from 'utils/fetcher'
27+
import { useCurrentSize } from 'utils/useCurrenSize'
2728
import { useNetworkState } from 'utils/useNetworkState'
2829
import { wrapErrorMessage } from 'utils/wrapErrorMessage'
2930

@@ -303,6 +304,7 @@ export const AccountAuthDialog: ComponentType<{
303304
export const AccountManager: ComponentType = withGlobalErrorBoundary(() => {
304305
const [open, setOpen] = useState(false)
305306
const [authState] = useAtom(authAtom)
307+
const { isSM } = useCurrentSize()
306308

307309
return (
308310
<>
@@ -318,7 +320,7 @@ export const AccountManager: ComponentType = withGlobalErrorBoundary(() => {
318320
</Popover2>
319321
) : (
320322
<Button className="ml-auto" icon="user" onClick={() => setOpen(true)}>
321-
登录 / 注册
323+
{!isSM && '登录 / 注册'}
322324
</Button>
323325
)}
324326
</>

src/components/NavExpandButton.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Button } from '@blueprintjs/core'
2+
3+
import { useAtomValue, useSetAtom } from 'jotai'
4+
5+
import { navAtom, toggleExpandNavAtom } from 'store/nav'
6+
7+
export const NavExpandButton = () => {
8+
const expanded = useAtomValue(navAtom)
9+
const toggleExpaned = useSetAtom(toggleExpandNavAtom)
10+
11+
return (
12+
<div className="sm:hidden">
13+
<Button
14+
onClick={toggleExpaned}
15+
icon={expanded.expanded ? 'cross' : 'menu'}
16+
/>
17+
</div>
18+
)
19+
}

src/components/OperationCard.tsx

Lines changed: 66 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -51,58 +51,77 @@ export const OperationCard = ({
5151
<Card
5252
interactive={true}
5353
elevation={Elevation.TWO}
54-
className="mb-2 last:mb-0"
54+
className="mb-4 sm:mb-2 last:mb-0"
5555
onClick={() => setDrawerOpen(true)}
5656
>
57-
<div className="flex items-start">
58-
<H4 className="inline-block pb-1 border-b-2 border-zinc-200 border-solid mb-2 mr-2">
59-
{operationDoc.doc.title}
60-
</H4>
61-
<Tooltip2
62-
placement="bottom"
63-
content={<div className="max-w-sm dark:text-slate-900">下载原 JSON</div>}
64-
>
65-
<Button
66-
small
67-
className="mr-2 mb-2"
68-
icon="download"
69-
onClick={(e) => {
70-
e.stopPropagation()
71-
handleDownloadJSON(operationDoc)
72-
}}
73-
/>
74-
</Tooltip2>
75-
<Tooltip2
76-
placement="bottom"
77-
content={<div className="max-w-sm dark:text-slate-900">复制神秘代码</div>}
78-
>
79-
<Button
80-
small
81-
className="mb-2"
82-
icon="clipboard"
83-
onClick={(e) => {
84-
e.stopPropagation()
85-
handleCopyShortCode(operation)
86-
}}
87-
/>
88-
</Tooltip2>
89-
<div className="flex-1" />
90-
<div className="flex flex-col items-end whitespace-nowrap">
91-
<div className="w-full flex justify-end text-zinc-500">
92-
<div className="flex items-center mr-4">
93-
<Icon icon="star" className="mr-1.5" />
57+
<div className="flex flex-wrap mb-4 sm:mb-2">
58+
{/* title */}
59+
<div className="flex flex-col gap-3">
60+
<div className="flex gap-2">
61+
<H4 className="inline-block pb-1 border-b-2 border-zinc-200 border-solid mb-2">
62+
{operationDoc.doc.title}
63+
</H4>
64+
<Tooltip2
65+
placement="bottom"
66+
content={
67+
<div className="max-w-sm dark:text-slate-900">
68+
下载原 JSON
69+
</div>
70+
}
71+
>
72+
<Button
73+
small
74+
icon="download"
75+
onClick={(e) => {
76+
e.stopPropagation()
77+
handleDownloadJSON(operationDoc)
78+
}}
79+
/>
80+
</Tooltip2>
81+
<Tooltip2
82+
placement="bottom"
83+
content={
84+
<div className="max-w-sm dark:text-slate-900">
85+
复制神秘代码
86+
</div>
87+
}
88+
>
89+
<Button
90+
small
91+
icon="clipboard"
92+
onClick={(e) => {
93+
e.stopPropagation()
94+
handleCopyShortCode(operation)
95+
}}
96+
/>
97+
</Tooltip2>
98+
</div>
99+
<H5 className="flex items-center text-slate-900 -mt-3">
100+
<EDifficultyLevel
101+
level={
102+
findLevelByStageName(levels, operationDoc.stageName) ||
103+
createCustomLevel(operationDoc.stageName)
104+
}
105+
difficulty={operationDoc.difficulty}
106+
/>
107+
</H5>
108+
</div>
109+
110+
<div className="lg:flex-1 hidden" />
111+
112+
{/* meta */}
113+
<div className="flex flex-col flex-1 gap-y-1.5 gap-x-4">
114+
<div className="flex flex-wrap sm:justify-end items-center gap-x-4 gap-y-1 text-zinc-500">
115+
<div className="flex items-center gap-1.5">
116+
<Icon icon="star" />
94117
<OperationRating
95118
className="text-sm"
96119
operation={operation}
97120
layout="horizontal"
98121
/>
99122
</div>
100123

101-
<Tooltip2
102-
className="mr-4"
103-
placement="top"
104-
content={`访问量:${operation.views}`}
105-
>
124+
<Tooltip2 placement="top" content={`访问量:${operation.views}`}>
106125
<div>
107126
<Icon icon="eye-open" className="mr-1.5" />
108127
<span>{operation.views}</span>
@@ -117,8 +136,7 @@ export const OperationCard = ({
117136
/>
118137
</div>
119138
</div>
120-
121-
<div className="w-full flex justify-end text-zinc-500 mt-1.5">
139+
<div className="text-zinc-500 self-end">
122140
<Tooltip2 placement="top" content={`作者:${operation.uploader}`}>
123141
<div>
124142
<Icon icon="user" className="mr-1.5" />
@@ -128,24 +146,15 @@ export const OperationCard = ({
128146
</div>
129147
</div>
130148
</div>
131-
<H5 className="flex items-center text-slate-900 -mt-3">
132-
<EDifficultyLevel
133-
level={
134-
findLevelByStageName(levels, operationDoc.stageName) ||
135-
createCustomLevel(operationDoc.stageName)
136-
}
137-
difficulty={operationDoc.difficulty}
138-
/>
139-
</H5>
140-
<div className="flex">
141-
<div className="text-gray-700 leading-normal w-1/2">
149+
<div className="flex md:flex-row flex-col gap-4">
150+
<div className="text-gray-700 leading-normal md:w-1/2">
142151
{/* <div className="text-sm text-zinc-600 mb-2 font-bold">作业描述</div> */}
143152
<Paragraphs
144153
content={operationDoc.doc.details}
145154
limitHeight={21 * 13.5} // 13 lines, 21px per line; the extra 0.5 line is intentional so the `mask` effect is obvious
146155
/>
147156
</div>
148-
<div className="w-1/2 ml-4">
157+
<div className="md:w-1/2">
149158
<div className="text-sm text-zinc-600 mb-2 font-bold">
150159
干员/干员组
151160
</div>

src/components/ThemeSwitchButton.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ export const ThemeSwitchButton = () => {
2020
}, [theme])
2121
return (
2222
<Button
23-
className="mr-4"
2423
onClick={handleThemeSwitch}
2524
icon={theme === 'dark' ? 'moon' : 'flash'}
2625
></Button>

src/components/drawer/NavAside.tsx

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { Button, Portal } from '@blueprintjs/core'
2+
3+
import { useAtomValue, useSetAtom } from 'jotai'
4+
import { LINKS } from 'layouts/AppLayout'
5+
import { NavLink } from 'react-router-dom'
6+
7+
import { navAtom, toggleExpandNavAtom } from 'store/nav'
8+
9+
export const NavAside = () => {
10+
const nav = useAtomValue(navAtom)
11+
const toggleNav = useSetAtom(toggleExpandNavAtom)
12+
const navLinks = [...LINKS]
13+
14+
if (!nav.expanded) return null
15+
16+
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 !no-underline"
27+
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>
44+
</div>
45+
</div>
46+
</Portal>
47+
)
48+
}

src/layouts/AppLayout.tsx

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ import { FCC } from 'types'
55

66
import { AccountManager } from 'components/AccountManager'
77
import { BackToTop } from 'components/BackToTop'
8+
import { NavExpandButton } from 'components/NavExpandButton'
89
import { ThemeSwitchButton } from 'components/ThemeSwitchButton'
10+
import { NavAside } from 'components/drawer/NavAside'
911

10-
const LINKS: {
12+
export const LINKS: {
1113
to: string
1214
label: string
1315
icon: IconName
@@ -28,7 +30,7 @@ const LINKS: {
2830

2931
export const AppLayout: FCC = ({ children }) => (
3032
<div className="flex flex-col h-full w-full bg-zinc-50 ">
31-
<Navbar className="flex w-full px-8 py-2 items-center bg-zinc-100 shadow fixed h-14 z-10 whitespace-nowrap overflow-x-auto overflow-y-hidden">
33+
<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">
3234
<Link to="/" className="flex items-center hover:no-underline ">
3335
<div className="select-none text-lg font-bold leading-none">
3436
MAA Copilot
@@ -41,25 +43,31 @@ export const AppLayout: FCC = ({ children }) => (
4143

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

44-
{LINKS.map((link) => (
45-
<NavLink
46-
key={link.to}
47-
to={link.to}
48-
className="text-sm text-zinc-600 !no-underline ml-2"
49-
>
50-
{({ isActive }) => (
51-
<Button minimal icon={link.icon} active={isActive}>
52-
{link.label}
53-
</Button>
54-
)}
55-
</NavLink>
56-
))}
46+
<div className="sm:flex items-center hidden">
47+
{LINKS.map((link) => (
48+
<NavLink
49+
key={link.to}
50+
to={link.to}
51+
className="text-sm text-zinc-600 !no-underline ml-2"
52+
>
53+
{({ isActive }) => (
54+
<Button minimal icon={link.icon} active={isActive}>
55+
{link.label}
56+
</Button>
57+
)}
58+
</NavLink>
59+
))}
60+
</div>
5761

5862
<div className="flex-1" />
5963

60-
<ThemeSwitchButton />
61-
<AccountManager />
64+
<div className="flex sm:gap-4 gap-3">
65+
<NavExpandButton />
66+
<ThemeSwitchButton />
67+
<AccountManager />
68+
</div>
6269
</Navbar>
70+
<NavAside />
6371

6472
<div className="docs-content-wrapper pt-14 pb-16">{children}</div>
6573

src/store/nav.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { atom } from 'jotai'
2+
3+
interface NavState {
4+
expanded?: boolean
5+
}
6+
7+
export const navAtom = atom<NavState>({
8+
expanded: false,
9+
})
10+
11+
export const toggleExpandNavAtom = atom(null, (get, set, value) => {
12+
set(navAtom, {
13+
...get(navAtom),
14+
expanded: !get(navAtom).expanded,
15+
})
16+
})

src/utils/useCurrenSize.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { useMemo } from 'react'
2+
import { useWindowSize } from 'react-use'
3+
4+
// https://tailwindcss.com/docs/container
5+
export const useCurrentSize = () => {
6+
const { width } = useWindowSize()
7+
8+
const isSM = useMemo(() => width < 640, [width])
9+
const isMD = useMemo(() => width >= 640 && width < 768, [width])
10+
const isLG = useMemo(() => width >= 768 && width < 1024, [width])
11+
const isXL = useMemo(() => width >= 1024 && width < 1280, [width])
12+
const is2XL = useMemo(() => width >= 1280 && width < 1536, [width])
13+
14+
return { isSM, isMD, isLG, isXL, is2XL }
15+
}

0 commit comments

Comments
 (0)