Skip to content

Commit 96fe3fa

Browse files
committed
feat: header drawer
Signed-off-by: Innei <[email protected]>
1 parent 279f1cc commit 96fe3fa

File tree

6 files changed

+183
-40
lines changed

6 files changed

+183
-40
lines changed

src/app/notes/[id]/page.tsx

+5-5
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,12 @@ const NoteMetaBar = () => {
112112

113113
const children = [] as ReactNode[]
114114
if (note.weather || !note.mood) {
115-
children.push(<DividerVertical className="!mx-2 scale-y-50" />)
115+
children.push(<DividerVertical className="!mx-2 scale-y-50" key="d0" />)
116116
}
117117

118118
if (note.weather) {
119119
children.push(
120-
<span className="inline-flex items-center space-x-1">
120+
<span className="inline-flex items-center space-x-1" key="weather">
121121
{weather2icon(note.weather)}
122122
<span className="font-medium">{note.weather}</span>
123123
<DividerVertical className="!mx-2 scale-y-50" />
@@ -127,7 +127,7 @@ const NoteMetaBar = () => {
127127

128128
if (note.mood) {
129129
children.push(
130-
<span className="inline-flex items-center space-x-1">
130+
<span className="inline-flex items-center space-x-1" key="mood">
131131
{mood2icon(note.mood)}
132132
<span className="font-medium">{note.mood}</span>
133133
</span>,
@@ -136,8 +136,8 @@ const NoteMetaBar = () => {
136136

137137
if (note.count.read > 0) {
138138
children.push(
139-
<DividerVertical className="!mx-2 scale-y-50" />,
140-
<span className="inline-flex items-center space-x-1">
139+
<DividerVertical className="!mx-2 scale-y-50" key="d1" />,
140+
<span className="inline-flex items-center space-x-1" key="readcount">
141141
<i className="icon-[mingcute--book-6-line]" />
142142
<span className="font-medium">{note.count.read}</span>
143143
</span>,

src/components/icons/emoji.tsx

+9-9
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export function EmojiSmile() {
1616
)
1717
}
1818

19-
export function FaSolidSadCry() {
19+
export function EmojiSadCry() {
2020
return (
2121
<svg
2222
xmlns="http://www.w3.org/2000/svg"
@@ -32,7 +32,7 @@ export function FaSolidSadCry() {
3232
)
3333
}
3434

35-
export function FaSolidSadTear() {
35+
export function EmojiSadTear() {
3636
return (
3737
<svg
3838
xmlns="http://www.w3.org/2000/svg"
@@ -48,7 +48,7 @@ export function FaSolidSadTear() {
4848
)
4949
}
5050

51-
export function FaSolidAngry() {
51+
export function EmojiAngry() {
5252
return (
5353
<svg
5454
xmlns="http://www.w3.org/2000/svg"
@@ -64,7 +64,7 @@ export function FaSolidAngry() {
6464
)
6565
}
6666

67-
export function FaSolidTired() {
67+
export function EmojiTired() {
6868
return (
6969
<svg
7070
xmlns="http://www.w3.org/2000/svg"
@@ -80,7 +80,7 @@ export function FaSolidTired() {
8080
)
8181
}
8282

83-
export function FaSolidMeh() {
83+
export function EmojiMeh() {
8484
return (
8585
<svg
8686
xmlns="http://www.w3.org/2000/svg"
@@ -102,7 +102,7 @@ export function FaSolidMeh() {
102102
)
103103
}
104104

105-
export function FaSolidGrinSquintTears() {
105+
export function EmojiGrinSquintTears() {
106106
return (
107107
<svg
108108
xmlns="http://www.w3.org/2000/svg"
@@ -118,7 +118,7 @@ export function FaSolidGrinSquintTears() {
118118
)
119119
}
120120

121-
export function FaSolidFrownOpen() {
121+
export function EmojiFrownOpen() {
122122
return (
123123
<svg
124124
xmlns="http://www.w3.org/2000/svg"
@@ -134,7 +134,7 @@ export function FaSolidFrownOpen() {
134134
)
135135
}
136136

137-
export function FaSolidGrimace() {
137+
export function EmojiGrimace() {
138138
return (
139139
<svg
140140
xmlns="http://www.w3.org/2000/svg"
@@ -150,7 +150,7 @@ export function FaSolidGrimace() {
150150
)
151151
}
152152

153-
export function FaSolidFlushed() {
153+
export function EmojiFlushed() {
154154
return (
155155
<svg
156156
xmlns="http://www.w3.org/2000/svg"

src/components/layout/header/internal/HeaderActionButton.tsx

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
export const HeaderActionButton: Component = ({ children }) => {
1+
export const HeaderActionButton: Component<JSX.IntrinsicElements['button']> = ({
2+
children,
3+
...rest
4+
}) => {
25
return (
36
<button
4-
type="button"
57
className="group h-10 rounded-full bg-gradient-to-b from-zinc-50/50 to-white/90 px-3 text-sm shadow-lg shadow-zinc-800/5 ring-1 ring-zinc-900/5 backdrop-blur transition dark:from-zinc-900/50 dark:to-zinc-800/90 dark:ring-white/10 dark:hover:ring-white/20"
8+
{...rest}
69
>
710
{children}
811
</button>

src/components/layout/header/internal/HeaderDrawerButton.tsx

+121-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,19 @@
1+
'use client'
2+
3+
import * as Dialog from '@radix-ui/react-dialog'
4+
import { memo } from 'react'
5+
import { AnimatePresence, motion } from 'framer-motion'
6+
import { atom, useAtom } from 'jotai'
7+
import Link from 'next/link'
18
import type { SVGProps } from 'react'
29

10+
import { CloseIcon } from '~/components/icons/close'
11+
import { MotionButtonBase } from '~/components/ui/button/MotionButton'
12+
import { reboundPreset } from '~/constants/spring'
13+
import { jotaiStore } from '~/lib/store'
14+
315
import { HeaderActionButton } from './HeaderActionButton'
16+
import { useHeaderConfig } from './HeaderDataConfigureProvider'
417

518
function IcBaselineMenuOpen(props: SVGProps<SVGSVGElement>) {
619
return (
@@ -13,10 +26,115 @@ function IcBaselineMenuOpen(props: SVGProps<SVGSVGElement>) {
1326
)
1427
}
1528

29+
const drawerOpenAtom = atom(false)
1630
export const HeaderDrawerButton = () => {
31+
const [open, setOpen] = useAtom(drawerOpenAtom)
32+
33+
return (
34+
<Dialog.Root open={open} onOpenChange={(open) => setOpen(open)}>
35+
<Dialog.Trigger asChild>
36+
<HeaderActionButton>
37+
<IcBaselineMenuOpen />
38+
</HeaderActionButton>
39+
</Dialog.Trigger>
40+
<Dialog.Portal forceMount>
41+
<AnimatePresence>
42+
{open && (
43+
<>
44+
<Dialog.Overlay asChild>
45+
<motion.div
46+
className="fixed inset-0 z-[11] bg-slate-50/80 backdrop-blur-sm dark:bg-slate-900/80"
47+
initial={{ opacity: 0 }}
48+
animate={{ opacity: 1 }}
49+
exit={{ opacity: 0 }}
50+
/>
51+
</Dialog.Overlay>
52+
53+
<Dialog.Content>
54+
<motion.dialog
55+
className="fixed inset-0 z-[12] flex max-h-[100vh] min-h-0 items-center justify-center overflow-hidden rounded-xl bg-base-100/90"
56+
initial={{ opacity: 0.8 }}
57+
animate={{ opacity: 1 }}
58+
exit={{ opacity: 0 }}
59+
>
60+
<Dialog.DialogClose asChild>
61+
<MotionButtonBase
62+
className="absolute right-4 top-4 p-4"
63+
onClick={() => {
64+
setOpen(false)
65+
}}
66+
>
67+
<CloseIcon />
68+
</MotionButtonBase>
69+
</Dialog.DialogClose>
70+
71+
<HeaderDrawerContent />
72+
</motion.dialog>
73+
</Dialog.Content>
74+
</>
75+
)}
76+
</AnimatePresence>
77+
</Dialog.Portal>
78+
</Dialog.Root>
79+
)
80+
}
81+
82+
// @ts-ignore
83+
const LinkInternal: typeof Link = memo(({ children, ...rest }) => {
1784
return (
18-
<HeaderActionButton>
19-
<IcBaselineMenuOpen />
20-
</HeaderActionButton>
85+
<Link
86+
{...rest}
87+
onClick={() => {
88+
jotaiStore.set(drawerOpenAtom, false)
89+
}}
90+
>
91+
{children}
92+
</Link>
93+
)
94+
})
95+
96+
const HeaderDrawerContent = () => {
97+
const { config } = useHeaderConfig()
98+
99+
return (
100+
<div className="h-[100vh] w-[90vw] space-y-4 overflow-auto py-8 scrollbar-none">
101+
{config.map((section, index) => {
102+
return (
103+
<motion.section
104+
initial={{ y: 30, opacity: 0 }}
105+
animate={{ y: 0, opacity: 1 }}
106+
transition={{
107+
...reboundPreset,
108+
delay: index * 0.08,
109+
}}
110+
key={section.path}
111+
>
112+
<LinkInternal className="block" href={section.path}>
113+
<span className="flex items-center space-x-2 py-2 text-[16px]">
114+
<i>{section.icon}</i>
115+
<h2>{section.title}</h2>
116+
</span>
117+
</LinkInternal>
118+
119+
{section.subMenu && (
120+
<ul className="my-2 grid grid-cols-2 gap-2">
121+
{section.subMenu.map((sub) => {
122+
return (
123+
<li key={sub.path}>
124+
<LinkInternal
125+
className="inline-block p-2"
126+
href={sub.path}
127+
>
128+
{sub.title}
129+
</LinkInternal>
130+
</li>
131+
)
132+
})}
133+
</ul>
134+
)}
135+
</motion.section>
136+
)
137+
})}
138+
</div>
21139
)
22140
}
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { memo } from 'react'
2+
import { motion } from 'framer-motion'
3+
import type { HTMLMotionProps } from 'framer-motion'
4+
5+
import { microReboundPreset } from '~/constants/spring'
6+
7+
export const MotionButtonBase: Component<HTMLMotionProps<'button'>> = memo(
8+
({ children, ...rest }) => {
9+
return (
10+
<motion.button
11+
initial={true}
12+
whileFocus={{ scale: 1.05 }}
13+
whileHover={{ scale: 1.05 }}
14+
whileTap={{ scale: 0.95 }}
15+
transition={{ ...microReboundPreset }}
16+
{...rest}
17+
>
18+
{children}
19+
</motion.button>
20+
)
21+
},
22+
)

src/lib/meta-icon.ts

+21-21
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,16 @@ import type { FC } from 'react'
33

44
import { PhSunBold } from '~/components/icons/appearance'
55
import {
6+
EmojiAngry,
7+
EmojiFlushed,
8+
EmojiFrownOpen,
9+
EmojiGrimace,
10+
EmojiGrinSquintTears,
11+
EmojiMeh,
12+
EmojiSadCry,
13+
EmojiSadTear,
614
EmojiSmile,
7-
FaSolidAngry,
8-
FaSolidFlushed,
9-
FaSolidFrownOpen,
10-
FaSolidGrimace,
11-
FaSolidGrinSquintTears,
12-
FaSolidMeh,
13-
FaSolidSadCry,
14-
FaSolidSadTear,
15-
FaSolidTired,
15+
EmojiTired,
1616
} from '~/components/icons/emoji'
1717
import {
1818
BiCloudLightningRainFill,
@@ -37,18 +37,18 @@ export const weather2icon = (weather: string) => {
3737
export const mood2icon = (mood: string) => {
3838
const map: Record<string, FC> = {
3939
开心: EmojiSmile,
40-
伤心: FaSolidSadTear,
41-
大哭: FaSolidSadCry,
42-
生气: FaSolidAngry,
43-
痛苦: FaSolidTired,
44-
悲哀: FaSolidMeh,
45-
不快: FaSolidMeh,
46-
激动: FaSolidGrinSquintTears,
47-
担心: FaSolidFrownOpen,
48-
可怕: FaSolidGrimace,
49-
可恶: FaSolidAngry,
50-
绝望: FaSolidFrownOpen,
51-
焦虑: FaSolidFlushed,
40+
伤心: EmojiSadTear,
41+
大哭: EmojiSadCry,
42+
生气: EmojiAngry,
43+
痛苦: EmojiTired,
44+
悲哀: EmojiMeh,
45+
不快: EmojiMeh,
46+
激动: EmojiGrinSquintTears,
47+
担心: EmojiFrownOpen,
48+
可怕: EmojiGrimace,
49+
可恶: EmojiAngry,
50+
绝望: EmojiFrownOpen,
51+
焦虑: EmojiFlushed,
5252
}
5353
return React.createElement(map[mood] || EmojiSmile)
5454
}

0 commit comments

Comments
 (0)