|
| 1 | +"use client"; |
| 2 | + |
1 | 3 | import Image from "next/image";
|
2 | 4 | import Link from "next/link";
|
| 5 | +import { |
| 6 | + ComponentProps, |
| 7 | + createRef, |
| 8 | + ElementRef, |
| 9 | + useEffect, |
| 10 | + useRef, |
| 11 | +} from "react"; |
| 12 | +import { useParams } from "next/navigation"; |
| 13 | +import clsx from "clsx"; |
3 | 14 |
|
4 | 15 | import { getDemos } from "@/lib/helper";
|
5 |
| -import { ComponentProps } from "react"; |
6 |
| - |
7 |
| -export const demos = getDemos(); |
8 | 16 |
|
9 | 17 | export default function Nav({
|
10 |
| - current, |
| 18 | + demos, |
11 | 19 | ...props
|
12 |
| -}: ComponentProps<"nav"> & { current?: string }) { |
| 20 | +}: { demos: ReturnType<typeof getDemos> } & ComponentProps<"nav">) { |
| 21 | + const ulRef = useRef<ElementRef<"ul">>(null); |
| 22 | + const lisRef = useRef( |
| 23 | + Array.from({ length: demos.length }).map(() => createRef<HTMLLIElement>()) |
| 24 | + ); |
| 25 | + |
| 26 | + const { demoname } = useParams(); |
| 27 | + |
| 28 | + const firstRef = useRef(true); |
| 29 | + useEffect(() => { |
| 30 | + const i = demos.findIndex(({ name }) => name === demoname); |
| 31 | + const li = lisRef.current[i]?.current; |
| 32 | + if (li) |
| 33 | + li.scrollIntoView({ |
| 34 | + inline: "center", |
| 35 | + block: "center", |
| 36 | + behavior: firstRef.current ? "instant" : "smooth", |
| 37 | + }); |
| 38 | + firstRef.current = false; |
| 39 | + }, [demoname, demos]); |
| 40 | + |
13 | 41 | return (
|
14 | 42 | <>
|
15 | 43 | <style
|
@@ -44,23 +72,24 @@ export default function Nav({
|
44 | 72 |
|
45 | 73 | a {display:block; background:white;}
|
46 | 74 |
|
| 75 | + a.active {outline:1px solid black;} |
| 76 | +
|
47 | 77 | a img {
|
48 | 78 | object-fit:cover; aspect-ratio:16/9; width:auto; height:7rem;
|
49 | 79 | }
|
50 | 80 | }
|
51 | 81 | `,
|
52 | 82 | }}
|
53 | 83 | />
|
| 84 | + |
54 | 85 | <nav {...props}>
|
55 |
| - <ul> |
| 86 | + <ul ref={ulRef}> |
56 | 87 | {demos.map(({ name, thumb }, i) => {
|
57 | 88 | return (
|
58 |
| - <li key={thumb}> |
| 89 | + <li key={thumb} ref={lisRef.current[i]}> |
59 | 90 | <Link
|
60 | 91 | href={`/demos/${name}`}
|
61 |
| - style={{ |
62 |
| - outline: `2px solid ${name === current ? "black" : "transparent"}`, |
63 |
| - }} |
| 92 | + className={clsx({ active: demoname === name })} |
64 | 93 | >
|
65 | 94 | <Image src={thumb} width={16} height={9} alt="" />
|
66 | 95 | </Link>
|
|
0 commit comments