Files
Webserver/components/mdx/MobileTableOfContents.tsx

51 lines
1.8 KiB
TypeScript
Raw Normal View History

2026-02-07 20:17:46 -05:00
'use client';
import { useState } from 'react';
type Heading = {
id: string;
text: string;
level: number;
};
export function MobileTableOfContents({ headings }: { headings: Heading[] }) {
const [isOpen, setIsOpen] = useState(false);
if (headings.length === 0) return null;
return (
<div className="block xl:hidden mb-8 border border-zinc-200 dark:border-zinc-800 rounded-lg overflow-hidden">
<button
onClick={() => setIsOpen(!isOpen)}
2026-02-08 23:18:21 -05:00
aria-expanded={isOpen}
aria-controls="mobile-toc"
2026-02-07 20:17:46 -05:00
className="w-full flex items-center justify-between p-4 bg-zinc-50 dark:bg-zinc-900 text-sm font-medium text-zinc-900 dark:text-zinc-100"
>
<span>Table of Contents</span>
<span className={`transform transition-transform ${isOpen ? 'rotate-180' : ''}`}>
</span>
</button>
{isOpen && (
2026-02-08 23:18:21 -05:00
<ul id="mobile-toc" className="p-4 bg-white dark:bg-black border-t border-zinc-200 dark:border-zinc-800 space-y-3">
2026-02-07 20:17:46 -05:00
{headings.map((heading) => (
<li
key={heading.id}
style={{ paddingLeft: `${(heading.level - 2) * 12}px` }}
>
<a
href={`#${heading.id}`}
onClick={() => setIsOpen(false)}
className="block text-sm text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-100 truncate"
>
{heading.text}
</a>
</li>
))}
</ul>
)}
</div>
);
}