Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions src/components/docs-sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ export function DocsSidebar() {
<div className='py-6 pr-6 lg:py-8'>
<div className='w-full'>
{docsConfig.sidebarNav.map((section, index) => (
<div key={index} className='pb-8'>
<h4 className='text-foreground mb-1 rounded-md px-2 py-1 text-sm text-[10px] font-bold tracking-tight uppercase opacity-70'>
<div key={index} className='pb-6'>
<h4 className='mb-1 px-2 text-sm font-semibold text-zinc-900 dark:text-zinc-100'>
{section.title}
</h4>
{section.items?.length ? (
Expand All @@ -35,18 +35,18 @@ interface DocsSidebarNavItemsProps {

function DocsSidebarNavItems({ items, pathname }: DocsSidebarNavItemsProps) {
return items.length ? (
<div className='grid grid-flow-row auto-rows-max text-sm'>
<div className='flex flex-col space-y-1 border-l border-zinc-200 ml-3 pl-2 text-sm dark:border-zinc-800'>
{items.map((item, index) =>
item.href ? (
<Link
key={index}
href={item.href}
className={cn(
'group flex w-full items-center rounded-md border border-transparent px-2 py-1.5 transition-all duration-200',
'group flex w-full items-center rounded-md border border-transparent px-2 py-1.5 transition-colors',
item.disabled && 'cursor-not-allowed opacity-60',
pathname === item.href
? 'bg-accent/50 text-foreground font-medium shadow-sm'
: 'text-muted-foreground hover:bg-accent/30 hover:text-foreground',
? 'bg-zinc-100 font-medium text-zinc-900 dark:bg-zinc-800/50 dark:text-zinc-50'
: 'text-zinc-600 hover:bg-zinc-100 hover:text-zinc-900 dark:text-zinc-400 dark:hover:bg-zinc-800/50 dark:hover:text-zinc-50',
)}
target={item.external ? '_blank' : ''}
rel={item.external ? 'noreferrer' : ''}
Expand All @@ -62,13 +62,13 @@ function DocsSidebarNavItems({ items, pathname }: DocsSidebarNavItemsProps) {
<span
key={index}
className={cn(
'text-muted-foreground flex w-full cursor-not-allowed items-center rounded-md p-2 hover:underline',
'flex w-full cursor-not-allowed items-center rounded-md px-2 py-1.5 text-zinc-600 hover:underline dark:text-zinc-400',
item.disabled && 'cursor-not-allowed opacity-60',
)}
>
{item.title}
{item.label ? (
<span className='bg-muted text-muted-foreground ml-2 rounded-md px-1.5 py-0.5 text-xs leading-none no-underline group-hover:no-underline'>
<span className='ml-2 rounded-md bg-muted px-1.5 py-0.5 text-xs leading-none text-muted-foreground no-underline group-hover:no-underline'>
{item.label}
</span>
) : null}
Expand Down
141 changes: 90 additions & 51 deletions src/components/mobile-nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
import * as React from "react"
import Link from "next/link"
import { usePathname } from "next/navigation"
import { Menu } from "lucide-react"
import { Github, Menu } from "lucide-react"
import { docsConfig } from "@/config/docs"
import { Button } from "@/components/ui/button"
import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet"
import { docsConfig } from "@/config/docs"
import { cn } from "@/lib/utils"

export function MobileNav() {
Expand All @@ -18,61 +18,87 @@ export function MobileNav() {
<SheetTrigger asChild>
<Button
variant="ghost"
className="mr-2 px-0 text-base hover:bg-transparent focus-visible:bg-transparent focus-visible:ring-0 focus-visible:ring-offset-0 md:hidden"
size="icon"
className="md:hidden"
>
<Menu className="h-5 w-5" />
<span className="sr-only">Toggle Menu</span>
<Menu className="size-5" />
<span className="sr-only">Open navigation</span>
</Button>
</SheetTrigger>
<SheetContent side="left" className="pr-0">
<MobileLink
href="/"
className="flex items-center"
onOpenChange={setOpen}
>
<span className="font-bold">NeuroLab</span>
</MobileLink>
<div className="my-4 h-[calc(100vh-8rem)] overflow-y-auto pb-10 pl-6">
<div className="flex flex-col space-y-3">
{docsConfig.mainNav?.map(
<SheetContent
side="left"
className="w-[86vw] max-w-sm border-r border-zinc-200 bg-white px-0 dark:border-zinc-800 dark:bg-zinc-950"
>
<div className="border-b border-zinc-200 px-5 py-5 dark:border-zinc-800">
<Link
href="/"
onClick={() => setOpen(false)}
className="block"
>
<div className="text-sm font-semibold text-zinc-950 dark:text-zinc-50">
NeuroLab Docs
</div>
<div className="mt-1 text-xs text-zinc-500 dark:text-zinc-400">
Platform documentation
</div>
</Link>
</div>

<div className="px-3 py-4">
Comment thread
m-prosper-10 marked this conversation as resolved.
<div className="space-y-1">
<Link
href="https://github.com/neurolab-0x"
target="_blank"
rel="noreferrer"
onClick={() => setOpen(false)}
className="flex items-center gap-2 rounded-lg px-3 py-2 text-sm text-zinc-600 transition-colors hover:bg-zinc-100 hover:text-zinc-950 dark:text-zinc-300 dark:hover:bg-zinc-900 dark:hover:text-zinc-50"
>
<Github className="size-4" />
<span>View code</span>
</Link>
{docsConfig.mainNav.map(
(item) =>
item.href && (
<MobileLink
key={item.href}
href={item.href}
pathname={pathname}
onOpenChange={setOpen}
>
{item.title}
</MobileLink>
)
)}
</div>
<div className="flex flex-col space-y-2">
{docsConfig.sidebarNav.map((item, index) => (
<div key={index} className="flex flex-col space-y-3 pt-6">
<h4 className="font-medium">{item.title}</h4>
{item?.items?.length &&
item.items.map((item) => (
<React.Fragment key={item.href}>
{!item.disabled &&
(item.href ? (
<MobileLink
href={item.href}
onOpenChange={setOpen}
className={cn(
"text-muted-foreground",
pathname === item.href && "text-foreground"
)}
>
{item.title}
</MobileLink>
) : (
item.title
))}
</React.Fragment>
))}
</div>
))}

<div className="mt-6 border-t border-zinc-200 pt-6 dark:border-zinc-800">
<div className="px-3 text-xs font-semibold uppercase tracking-[0.16em] text-zinc-500 dark:text-zinc-400">
Documentation
</div>
<div className="mt-3 space-y-6">
{docsConfig.sidebarNav.map((section) => (
<div key={section.title}>
<div className="px-2 mb-1 text-sm font-semibold text-zinc-900 dark:text-zinc-100">
{section.title}
</div>
<div className="flex flex-col space-y-1 border-l border-zinc-200 ml-3 pl-2 dark:border-zinc-800">
{section.items.map((item) =>
item.href ? (
<MobileLink
key={item.href}
href={item.href}
pathname={pathname}
onOpenChange={setOpen}
className="px-2 py-1.5 text-zinc-600 dark:text-zinc-400"
>
{item.title}
</MobileLink>
) : null
)}
</div>
</div>
))}
</div>
</div>
</div>
</SheetContent>
Expand All @@ -82,31 +108,44 @@ export function MobileNav() {

interface MobileLinkProps {
href: string
pathname: string
onOpenChange?: (open: boolean) => void
children: React.ReactNode
className?: string
}

function MobileLink({
href,
pathname,
onOpenChange,
className,
children,
...props
className,
}: MobileLinkProps) {
const pathname = usePathname()
const allHrefs = [
...docsConfig.mainNav.map((n) => n.href),
...docsConfig.sidebarNav.flatMap((s) => s.items.map((i) => i.href)),
].filter(Boolean) as string[]

const active =
pathname === href ||
(href !== "/" &&
pathname.startsWith(href) &&
!allHrefs.some(
(other) =>
other !== href && pathname.startsWith(other) && other.length > href.length
))

return (
<Link
href={href}
onClick={() => {
onOpenChange?.(false)
}}
onClick={() => onOpenChange?.(false)}
className={cn(
"text-foreground/70 transition-colors hover:text-foreground",
pathname === href && "text-foreground",
"block rounded-lg px-3 py-2 text-sm transition-colors",
active
? "bg-zinc-100 font-medium text-zinc-950 dark:bg-zinc-900 dark:text-zinc-50"
: "hover:bg-zinc-100 hover:text-zinc-950 dark:hover:bg-zinc-900 dark:hover:text-zinc-50",
className
)}
{...props}
>
{children}
</Link>
Expand Down
22 changes: 7 additions & 15 deletions src/components/search.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,16 @@
'use client'

import Link from 'next/link'
import { Search as SearchIcon } from 'lucide-react'
import { Button } from '@/components/ui/button'

export function Search() {
return (
<Button
type='button'
variant='outline'
className='relative h-9 w-full cursor-default justify-start text-sm text-muted-foreground sm:pr-12 md:w-40 lg:w-64'
disabled
aria-disabled='true'
title='Search is not implemented yet'
<Link
href='/docs'
className='flex h-10 w-[220px] items-center gap-2 rounded-lg border border-zinc-200 bg-zinc-50 px-3 text-sm text-zinc-500 transition-colors hover:border-zinc-300 hover:bg-white hover:text-zinc-700 dark:border-zinc-800 dark:bg-zinc-900 dark:text-zinc-400 dark:hover:border-zinc-700 dark:hover:bg-zinc-950 dark:hover:text-zinc-200 lg:w-[260px]'
>
<SearchIcon className='mr-2 h-4 w-4' />
<span className='hidden lg:inline-flex'>Search coming soon</span>
<span className='inline-flex lg:hidden'>Search</span>
<kbd className='pointer-events-none absolute right-1.5 top-1.5 hidden h-6 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium opacity-100 sm:flex'>
<span className='text-xs'>⌘</span>K
</kbd>
</Button>
<SearchIcon className='size-4' />
<span className='truncate'>Search documentation</span>
</Link>
)
}
84 changes: 53 additions & 31 deletions src/components/site-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,58 +2,80 @@

import Link from 'next/link'
import { usePathname } from 'next/navigation'
import { cn } from '@/lib/utils'
import { Github, Star } from 'lucide-react'
import { docsConfig } from '@/config/docs'
import { MobileNav } from '@/components/mobile-nav'
import { ThemeToggle } from '@/components/theme-toggle'
import { Search } from '@/components/search'
import { LucideGithub } from 'lucide-react'
import { ThemeToggle } from '@/components/theme-toggle'
import { cn } from '@/lib/utils'

export function SiteHeader() {
const pathname = usePathname()

return (
<header className='bg-background/60 border-border/40 hover:border-border/80 sticky top-0 z-50 w-full border-b backdrop-blur-md transition-all duration-300 ease-in-out'>
<div className='container flex h-16 items-center'>
<header className='sticky top-0 z-50 w-full border-b border-zinc-200/80 bg-white/90 backdrop-blur-md dark:border-zinc-800 dark:bg-zinc-950/85'>
<div className='container flex h-16 items-center gap-3'>
<MobileNav />
<div className='mr-4 hidden md:flex'>
<Link
href='/'
className='mr-8 flex items-center space-x-2 transition-opacity hover:opacity-80'
>
<span className='hidden text-lg font-extrabold tracking-tighter uppercase sm:inline-block'>
NeuroLab

<Link href='/' className='flex min-w-0 items-center gap-3'>
<span className='min-w-0'>
<span className='block truncate font-sans text-lg font-semibold text-zinc-950 dark:text-zinc-50'>
NeuroLab Docs
</span>
</Link>
<nav className='flex items-center space-x-8 text-sm font-medium'>
{docsConfig.mainNav.map((item) => (
</span>
</Link>

<nav className='ml-4 hidden items-center gap-1 lg:flex'>
{docsConfig.mainNav.map((item) => {
const allMainHrefs = docsConfig.mainNav.map((n) => n.href).filter(Boolean) as string[]
const isActive =
pathname === item.href ||
(!!item.href &&
item.href !== '/' &&
pathname.startsWith(item.href) &&
!allMainHrefs.some(
(other) =>
other !== item.href &&
pathname.startsWith(other) &&
other.length > item.href!.length
))

return (
<Link
key={item.href}
href={item.href || '/'}
className={cn(
'hover:text-foreground relative py-1 transition-colors',
pathname === item.href
? 'text-foreground after:bg-primary font-semibold after:absolute after:bottom-0 after:left-0 after:h-0.5 after:w-full after:rounded-full'
: 'text-foreground/60',
'rounded-lg px-3 py-2 text-sm font-medium transition-colors',
isActive
? 'bg-zinc-100 text-zinc-950 dark:bg-zinc-900 dark:text-zinc-50'
: 'text-zinc-600 hover:bg-zinc-100 hover:text-zinc-950 dark:text-zinc-300 dark:hover:bg-zinc-900 dark:hover:text-zinc-50',
)}
target={item.external ? '_blank' : undefined}
rel={item.external ? 'noreferrer' : undefined}
>
{item.title}
</Link>
))}
</nav>
)
})}
</nav>

<div className='ml-auto hidden md:block'>
<Search />
</div>
<div className='flex flex-1 items-center justify-between space-x-2 md:justify-end'>
<div className='rounded-md border border-zinc-200 p-2 transition-colors hover:bg-zinc-50 dark:border-zinc-800 dark:hover:bg-zinc-900'>
<LucideGithub />
</div>
<div className='w-full flex-1 md:w-auto md:flex-none'>
<Search />
</div>
<div className='rounded-md border border-zinc-200 transition-colors hover:bg-zinc-50 dark:border-zinc-800 dark:hover:bg-zinc-900'>
<ThemeToggle />
</div>

<Link
href='https://github.com/neurolab-0x'
target='_blank'
rel='noreferrer'
className='hidden items-center gap-2 rounded-lg border border-zinc-200 bg-white px-3 py-2 text-sm text-zinc-600 transition-colors hover:border-zinc-300 hover:text-zinc-950 md:flex dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-300 dark:hover:border-zinc-700 dark:hover:text-zinc-50'
>
<Github className='size-4' />
221K{' '}
<Star className='size-4 text-zinc-600 transition-colors hover:text-zinc-950 dark:text-zinc-300 dark:hover:text-zinc-50' />
</Link>

<div className='rounded-lg border border-zinc-200 bg-white dark:border-zinc-800 dark:bg-zinc-950'>
<ThemeToggle />
</div>
</div>
</header>
Expand Down
Loading