File size: 3,448 Bytes
65d68f5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
"use client";

import Link from "next/link";
import Image from "next/image";
import { usePathname } from "next/navigation";
import { cn } from "@/lib/utils";
import { navigationSections } from "@/lib/navigation";

function isActive(pathname: string, href: string) {
  return pathname === href || (href !== "/" && pathname.startsWith(href));
}

type SidebarProps = {
  onNavigate?: () => void;
};

export function Sidebar({ onNavigate }: SidebarProps) {
  const pathname = usePathname();

  return (
    <aside className="sticky top-0 flex h-screen w-[248px] shrink-0 flex-col border-r border-white/[0.075] bg-[#050505]/96 shadow-[14px_0_50px_rgba(0,0,0,0.36)]">
      <div className="flex items-center gap-3 px-5 py-6">
        <div className="relative grid size-10 shrink-0 place-items-center overflow-hidden rounded-2xl border border-white/[0.1] bg-white/[0.04] shadow-[inset_0_1px_0_rgba(255,255,255,0.04)]">
          <Image src="/docdoe-logo-mark.png" alt="DocDoe AI" width={26} height={26} className="object-contain" priority />
        </div>
        <div className="min-w-0">
          <p className="truncate text-[16px] font-bold text-white">DocDoe AI</p>
          <p className="text-[10px] font-semibold uppercase text-white/45">Exam signals</p>
        </div>
      </div>

      <nav className="flex-1 space-y-5 overflow-y-auto px-3.5 py-2" aria-label="Sidebar">
        {navigationSections.map((section) => (
          <div key={section.title} className="space-y-1">
            <p className="px-3 pb-1 text-[10px] font-bold uppercase text-white/36">
              {section.title}
            </p>
            {section.items.map((item) => {
              const active = isActive(pathname ?? "", item.href);
              const Icon = item.icon;
              return (
                <Link
                  key={item.href}
                  href={item.href}
                  onClick={() => onNavigate?.()}
                  className={cn(
                    "nav-item group relative z-10 flex items-center gap-3 rounded-2xl border px-3.5 py-2.5 text-[13px] font-medium transition-all duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/24 touch-ripple",
                    active
                      ? "border-white/[0.14] bg-white/[0.07] text-white shadow-[inset_0_1px_0_rgba(255,255,255,0.04)]"
                      : "border-transparent text-white/56 hover:bg-white/[0.04] hover:text-white/88",
                  )}
                >
                  {active ? (
                    <span className="absolute left-1 top-1/2 h-5 w-0.5 -translate-y-1/2 rounded-full bg-white/70" aria-hidden="true" />
                  ) : null}
                  <Icon
                    className={cn("size-[17px] shrink-0", active ? "text-white/85" : "text-current")}
                    strokeWidth={active ? 2.2 : 1.9}
                  />
                  <span className={cn("truncate", active && "font-semibold")}>{item.label}</span>
                  {active ? (
                    <span className="ml-auto size-1.5 shrink-0 rounded-full bg-white/68" aria-hidden="true" />
                  ) : null}
                </Link>
              );
            })}
          </div>
        ))}
      </nav>

      <div className="mt-auto border-t border-white/[0.06] p-4">
        <p className="px-2 text-[10px] font-semibold uppercase text-white/34">DocDoe AI v1.2</p>
      </div>
    </aside>
  );
}