docs-mobile-nav.tsx 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. "use client";
  2. import { useState, useMemo } from "react";
  3. import Link from "next/link";
  4. import { usePathname } from "next/navigation";
  5. import { List } from "lucide-react";
  6. import {
  7. Sheet,
  8. SheetTrigger,
  9. SheetContent,
  10. SheetTitle,
  11. } from "@/components/ui/sheet";
  12. const navigation = [
  13. {
  14. title: "Getting Started",
  15. items: [
  16. { title: "Introduction", href: "/docs" },
  17. { title: "Installation", href: "/docs/installation" },
  18. { title: "Quick Start", href: "/docs/quick-start" },
  19. ],
  20. },
  21. {
  22. title: "Core Concepts",
  23. items: [
  24. { title: "Catalog", href: "/docs/catalog" },
  25. { title: "Components", href: "/docs/components" },
  26. { title: "Data Binding", href: "/docs/data-binding" },
  27. { title: "Actions", href: "/docs/actions" },
  28. { title: "Visibility", href: "/docs/visibility" },
  29. { title: "Validation", href: "/docs/validation" },
  30. ],
  31. },
  32. {
  33. title: "Guides",
  34. items: [
  35. { title: "AI SDK Integration", href: "/docs/ai-sdk" },
  36. { title: "Streaming", href: "/docs/streaming" },
  37. { title: "Code Export", href: "/docs/code-export" },
  38. ],
  39. },
  40. {
  41. title: "API Reference",
  42. items: [
  43. { title: "@json-render/core", href: "/docs/api/core" },
  44. { title: "@json-render/react", href: "/docs/api/react" },
  45. { title: "@json-render/codegen", href: "/docs/api/codegen" },
  46. ],
  47. },
  48. ];
  49. // Flatten all pages for current page lookup
  50. const allPages = navigation.flatMap((section) => section.items);
  51. export function DocsMobileNav() {
  52. const [open, setOpen] = useState(false);
  53. const pathname = usePathname();
  54. const currentPage = useMemo(() => {
  55. const page = allPages.find((page) => page.href === pathname);
  56. return page ?? allPages[0];
  57. }, [pathname]);
  58. return (
  59. <Sheet open={open} onOpenChange={setOpen}>
  60. <SheetTrigger className="lg:hidden sticky top-[calc(3.5rem+1px)] z-40 w-full px-6 py-3 bg-background/80 backdrop-blur-sm border-b border-border flex items-center justify-between focus:outline-none">
  61. <div className="text-sm font-medium">{currentPage?.title}</div>
  62. <div className="w-8 h-8 flex items-center justify-center">
  63. <List className="h-4 w-4 text-muted-foreground" />
  64. </div>
  65. </SheetTrigger>
  66. <SheetContent className="overflow-y-auto p-6">
  67. <SheetTitle className="mb-6">Table of Contents</SheetTitle>
  68. <nav className="space-y-6">
  69. {navigation.map((section) => (
  70. <div key={section.title}>
  71. <h4 className="text-xs font-medium text-muted-foreground uppercase tracking-wider mb-2">
  72. {section.title}
  73. </h4>
  74. <ul className="space-y-1">
  75. {section.items.map((item) => (
  76. <li key={item.href}>
  77. <Link
  78. href={item.href}
  79. onClick={() => setOpen(false)}
  80. className={`text-sm block py-2 transition-colors ${
  81. pathname === item.href
  82. ? "text-primary font-medium"
  83. : "text-muted-foreground hover:text-foreground"
  84. }`}
  85. >
  86. {item.title}
  87. </Link>
  88. </li>
  89. ))}
  90. </ul>
  91. </div>
  92. ))}
  93. </nav>
  94. </SheetContent>
  95. </Sheet>
  96. );
  97. }