Global Import in the menu; mobile drawer nav

- Add a top-level "Import" entry to the sidebar and a global /import page, so
  you can start a tree from a GEDCOM without first creating an empty one. The
  import flow now picks its destination (new tree, or an existing one) — the
  tree-scoped page reuses the same <GedcomImport> with a fixed destination and
  keeps Export.
- Extract the sidebar chrome into <AppShell> and give small screens a working
  menu: a hamburger opens the full sidebar as a slide-in drawer (it was just a
  logo + "Trees" link before). Used by both /trees and /import.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-07 10:40:01 -04:00
parent 5824e70895
commit 1164841950
7 changed files with 416 additions and 323 deletions
+4 -1
View File
@@ -17,7 +17,7 @@ import { useEffect, useState } from "react";
import { api } from "@/lib/api/client";
import { cn } from "@/lib/utils";
export function AppSidebar() {
export function AppSidebar({ onNavigate }: { onNavigate?: () => void }) {
const pathname = usePathname();
const router = useRouter();
const segs = pathname.split("/").filter(Boolean); // ["trees", "<id>", ...]
@@ -35,6 +35,7 @@ export function AppSidebar() {
}, [treeId]);
async function logout() {
onNavigate?.();
await api.POST("/api/v1/auth/logout");
router.push("/login");
}
@@ -52,6 +53,7 @@ export function AppSidebar() {
}) => (
<Link
href={href}
onClick={onNavigate}
className={cn(
"flex items-center gap-3 rounded-lg px-3 py-2 text-sm transition-colors",
active
@@ -72,6 +74,7 @@ export function AppSidebar() {
</Link>
<Item href="/trees" label="Trees" icon={FolderTree} active={pathname === "/trees"} />
<Item href="/import" label="Import" icon={ArrowDownUp} active={pathname === "/import"} />
{treeId && (
<div className="mt-5 flex flex-col gap-1">