Skip to content

Commit c12d5e9

Browse files
committed
feat: 文章页头部显示meta数据
1 parent 0d34197 commit c12d5e9

File tree

4 files changed

+102
-21
lines changed

4 files changed

+102
-21
lines changed
Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
'use client';
22

3-
import { useRouter, usePathname } from 'next/navigation';
3+
import { useRouter, usePathname, useParams } from 'next/navigation';
44
import Image from 'next/image';
55
import { useMemo } from 'react';
6-
import { m } from 'framer-motion';
6+
import { m, AnimatePresence } from 'framer-motion';
77

8-
export const AnimatedLogo = () => {
8+
export const AnimatedLogo = ({ forcePlay = false }: { forcePlay?: boolean }) => {
99
const router = useRouter();
1010
const pathName = usePathname();
11+
const params = useParams();
12+
const nid = params.nid;
1113
const handleClick = useMemo(() => () => router.push('/'), [pathName]);
14+
if (nid && !forcePlay) return null;
1215

1316
return (
1417
<button className=" cursor-pointer" onClick={() => handleClick()}>
@@ -20,21 +23,24 @@ export const AnimatedLogo = () => {
2023

2124
const SideOwnerAvatar = () => {
2225
return (
23-
<m.div
24-
initial={{ opacity: 0, y: 10 }}
25-
animate={{ opacity: 1, y: 0 }}
26-
exit={{ opacity: 0, y: -10 }}
27-
className="pointer-events-none relative z-[9] size-[40px] select-none"
28-
>
29-
<div className=" mask mask-squircle overflow-hidden">
30-
<Image
31-
src="/image/owner.jpg"
32-
alt="Site Owner Avatar"
33-
width={40}
34-
height={40}
35-
className="ring-2 ring-slate-200 dark:ring-neutral-800"
36-
/>
37-
</div>
38-
</m.div>
26+
<AnimatePresence>
27+
{' '}
28+
<m.div
29+
initial={{ opacity: 0, y: 10 }}
30+
animate={{ opacity: 1, y: 0 }}
31+
exit={{ opacity: 0, y: -10 }}
32+
className="pointer-events-none relative z-[9] size-[40px] select-none"
33+
>
34+
<div className=" mask mask-squircle overflow-hidden">
35+
<Image
36+
src="/image/owner.jpg"
37+
alt="Site Owner Avatar"
38+
width={40}
39+
height={40}
40+
className="ring-2 ring-slate-200 dark:ring-neutral-800"
41+
/>
42+
</div>
43+
</m.div>
44+
</AnimatePresence>
3945
);
4046
};

src/components/layout/Header/Header.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,12 @@ import { HeaderCenterArea, HeaderLeftButtonArea, HeaderLogoArea } from './Header
66
import { HeaderCenterContent } from './HeaderCenterContent';
77
import { AnimatedLogo } from './AnimatedLogo';
88
import styles from './header.module.css';
9+
import { HeaderMeta } from './HeaderMeta';
910

1011
import { cn } from '@/lib/helper';
12+
import { buildPostData } from '@/core';
13+
14+
const { postDataMap } = buildPostData();
1115

1216
const Header = () => {
1317
return (
@@ -23,11 +27,15 @@ const Header = () => {
2327

2428
<HeaderLogoArea>
2529
<AnimatedLogo />
30+
31+
<div className="block lg:hidden">
32+
<HeaderMeta postDataMap={postDataMap} />
33+
</div>
2634
</HeaderLogoArea>
2735
<div className=" sr-only"></div>
2836
<HeaderCenterArea>
2937
<HeaderCenterContent />
30-
{/* TODO 文章页面时显示一些文章信息 */}
38+
<HeaderMeta postDataMap={postDataMap} />
3139
</HeaderCenterArea>
3240

3341
{/* <div className="flex size-full [grid-area:right] items-center"></div> */}

src/components/layout/Header/HeaderCenterContent.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import { LayoutGroup, m, useMotionTemplate, useMotionValue } from 'framer-motion';
44
import React, { memo } from 'react';
5-
import { usePathname } from 'next/navigation';
5+
import { usePathname, useParams } from 'next/navigation';
66
import Link from 'next/link';
77

88
import { MenuPopover } from './MenuPopover';
@@ -17,6 +17,9 @@ import {
1717
import { cn } from '@/lib/helper';
1818

1919
export const HeaderCenterContent = () => {
20+
const params = useParams();
21+
if (params.nid) return null;
22+
2023
return (
2124
<LayoutGroup>
2225
<AnimatedMenu>
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
'use client';
2+
3+
import { useParams } from 'next/navigation';
4+
import { AnimatePresence, m } from 'framer-motion';
5+
6+
import { AnimatedLogo } from './AnimatedLogo';
7+
8+
import type { PostMap } from '@/core';
9+
10+
const animationProps = {
11+
initial: {
12+
opacity: 0,
13+
y: 20,
14+
},
15+
exit: {
16+
opacity: 0,
17+
y: 20,
18+
},
19+
animate: {
20+
opacity: 1,
21+
y: 0,
22+
23+
transition: {
24+
type: 'spring',
25+
stiffness: 300,
26+
damping: 20,
27+
},
28+
},
29+
};
30+
31+
export const HeaderMeta = ({ postDataMap }: { postDataMap: PostMap }) => {
32+
const params = useParams();
33+
const postId = params.nid as string;
34+
console.log(postId);
35+
36+
const postData = postDataMap[postId];
37+
console.log(postData);
38+
39+
return (
40+
<AnimatePresence>
41+
{postData && (
42+
<m.div
43+
className="absolute inset-0 flex min-w-0 items-center justify-between gap-3 px-0 lg:px-16"
44+
data-testid="header-meta"
45+
{...animationProps}
46+
>
47+
<div className="flex min-w-0 shrink grow flex-col">
48+
<small className="min-w-0 truncate">
49+
<span className="text-gray-600/60 dark:text-gray-300/60">{postData.tag}</span>
50+
</small>
51+
<h2 className="min-w-0 truncate text-[1.2rem] font-medium leading-normal">
52+
{postData.title}
53+
</h2>
54+
</div>
55+
56+
<div className=" min-w-0 shrink-[5] flex-col text-right leading-5 flex">
57+
<AnimatedLogo forcePlay={true} />
58+
<span className="font-medium sr-only">{'zwの小站'}</span>
59+
</div>
60+
</m.div>
61+
)}
62+
</AnimatePresence>
63+
);
64+
};

0 commit comments

Comments
 (0)