Skip to content

Commit d91e83d

Browse files
committed
Enhance Mobile Table of Contents: Implement collapsible functionality and improve layout with Chevron icon for better user interaction
1 parent ba297d9 commit d91e83d

1 file changed

Lines changed: 45 additions & 30 deletions

File tree

app/ui/MobileToc.tsx

Lines changed: 45 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
'use client'
2+
import { ChevronDownIcon } from '@heroicons/react/24/outline'
23
import { useState } from 'react'
34

45
interface Props {
@@ -9,39 +10,53 @@ export default function MobileToc({ headers }: Props) {
910
const [activeId, setActiveId] = useState<string>(
1011
headers ? headers[0]?.id : '',
1112
)
13+
const [isOpen, setIsOpen] = useState(false)
1214

1315
return (
1416
headers && (
15-
<nav className="h-fit max-w-sm pt-6 md:max-w-none xl:hidden">
16-
<h2 className="mb-3 text-sm font-semibold leading-6 text-gray-700 dark:text-white">
17-
On this page
18-
</h2>
19-
<hr className="mb-4 h-1 w-10 border-0 bg-blue-600 dark:bg-blue-500" />
20-
<ul className="flex flex-col gap-0.5">
21-
{headers.map((header, index) => {
22-
const isActive = activeId === header.id
23-
let padding = 'pl-3'
24-
if (header.level === 3) padding = 'pl-7'
25-
if (header.level === 4) padding = 'pl-11'
26-
if (header.level === 5) padding = 'pl-15'
27-
if (header.level === 6) padding = 'pl-19'
28-
return (
29-
<li key={index}>
30-
<a
31-
href={`#${header.id}`}
32-
className={`block truncate rounded-md py-1 text-sm transition-colors ${padding} ${
33-
isActive
34-
? 'bg-gray-100 text-blue-600 dark:bg-gray-800 dark:text-blue-500'
35-
: 'text-gray-500 hover:text-blue-600 dark:text-gray-400 dark:hover:text-blue-500'
36-
}`}
37-
onClick={() => setActiveId(header.id)}
38-
>
39-
{header.title}
40-
</a>
41-
</li>
42-
)
43-
})}
44-
</ul>
17+
<nav className="h-fit w-full max-w-prose pt-6 xl:hidden">
18+
<button
19+
type="button"
20+
onClick={() => setIsOpen((prev) => !prev)}
21+
className="flex w-full items-center justify-between"
22+
>
23+
<h2 className="text-sm font-semibold leading-6 text-gray-700 dark:text-white">
24+
On this page
25+
</h2>
26+
<ChevronDownIcon
27+
className={`h-4 w-4 text-gray-500 transition-transform duration-200 dark:text-gray-400 ${
28+
isOpen ? 'rotate-180' : ''
29+
}`}
30+
/>
31+
</button>
32+
<hr className="mt-3 h-1 w-10 border-0 bg-blue-600 dark:bg-blue-500" />
33+
{isOpen && (
34+
<ul className="mt-4 flex flex-col gap-0.5">
35+
{headers.map((header, index) => {
36+
const isActive = activeId === header.id
37+
let padding = 'pl-3'
38+
if (header.level === 3) padding = 'pl-7'
39+
if (header.level === 4) padding = 'pl-11'
40+
if (header.level === 5) padding = 'pl-15'
41+
if (header.level === 6) padding = 'pl-19'
42+
return (
43+
<li key={index}>
44+
<a
45+
href={`#${header.id}`}
46+
className={`block truncate rounded-md py-1 text-sm transition-colors ${padding} ${
47+
isActive
48+
? 'bg-gray-100 text-blue-600 dark:bg-gray-800 dark:text-blue-500'
49+
: 'text-gray-500 hover:text-blue-600 dark:text-gray-400 dark:hover:text-blue-500'
50+
}`}
51+
onClick={() => setActiveId(header.id)}
52+
>
53+
{header.title}
54+
</a>
55+
</li>
56+
)
57+
})}
58+
</ul>
59+
)}
4560
</nav>
4661
)
4762
)

0 commit comments

Comments
 (0)