Skip to content

Commit 81a29dd

Browse files
committed
scrollIntoView
1 parent 0f3423f commit 81a29dd

File tree

2 files changed

+42
-11
lines changed

2 files changed

+42
-11
lines changed

apps/website/app/layout.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ import type { Metadata } from "next";
22
import { Inter } from "next/font/google";
33
import "./globals.css";
44
import Nav from "@/components/Nav";
5+
import { getDemos } from "@/lib/helper";
56

67
const inter = Inter({ subsets: ["latin"] });
8+
const demos = getDemos();
79

810
export const metadata: Metadata = {
911
title: "pmndrs examples",
@@ -30,7 +32,7 @@ export default function RootLayout({
3032
/>
3133

3234
<main>{children}</main>
33-
<Nav />
35+
<Nav demos={demos} />
3436
</body>
3537
</html>
3638
);

apps/website/components/Nav.tsx

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,43 @@
1+
"use client";
2+
13
import Image from "next/image";
24
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";
314

415
import { getDemos } from "@/lib/helper";
5-
import { ComponentProps } from "react";
6-
7-
export const demos = getDemos();
816

917
export default function Nav({
10-
current,
18+
demos,
1119
...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+
1341
return (
1442
<>
1543
<style
@@ -44,23 +72,24 @@ export default function Nav({
4472
4573
a {display:block; background:white;}
4674
75+
a.active {outline:1px solid black;}
76+
4777
a img {
4878
object-fit:cover; aspect-ratio:16/9; width:auto; height:7rem;
4979
}
5080
}
5181
`,
5282
}}
5383
/>
84+
5485
<nav {...props}>
55-
<ul>
86+
<ul ref={ulRef}>
5687
{demos.map(({ name, thumb }, i) => {
5788
return (
58-
<li key={thumb}>
89+
<li key={thumb} ref={lisRef.current[i]}>
5990
<Link
6091
href={`/demos/${name}`}
61-
style={{
62-
outline: `2px solid ${name === current ? "black" : "transparent"}`,
63-
}}
92+
className={clsx({ active: demoname === name })}
6493
>
6594
<Image src={thumb} width={16} height={9} alt="" />
6695
</Link>

0 commit comments

Comments
 (0)