ThatAIguyA world of ideas

THE CONSCIOUSNESS ATLAS
Read. Experiment. Follow the evidence.

ConsciousnessLearn · Explore · Joseph Anady

Janady13/llms-txt-hub / apps/web/components/layout/header.tsx

Source identity, revision, and recovered contents.

GitHub sourceSource text recovered

Source identity

FieldRecorded value
Source typeGitHub source
Original recordJanady13/llms-txt-hub / apps/web/components/layout/header.tsx
DateNot specified in source
RepositoryJanady13/llms-txt-hub
Revisione0f4bf978d4df168369c7601d9c5f5ea89e84377
Branchmain
Path or archive memberapps/web/components/layout/header.tsx
Original SHA-256219423ed3ba243835d55443cd19cf41998aae9b765ae26a672e36b3b0c9479d6
Git blob SHA8ae41c0853abf6d05af9f45fc8eea9fe19116e9a
Reading-copy SHA-256219423ed3ba243835d55443cd19cf41998aae9b765ae26a672e36b3b0c9479d6

Original source ↗

Recovered source transcript

'use client' import { useAuth } from '@thedaviddias/auth' import { Menu, Search, UserPlus } from 'lucide-react' import Link from 'next/link' import { useEffect, useState } from 'react' import { useAnalyticsEvents } from '@/components/analytics-tracker' import { GithubStars } from '@/components/stats/github-stars' import { useSearch } from '@/hooks/use-search' import { getRoute } from '@/lib/routes' import { NavLink } from './header-nav-link' import { DesktopSearchForm, MobileSearchOverlay } from './header-search' import { UserDropdownMenu } from './header-user-menu' import { MobileDrawer } from './mobile-drawer' /** * Generates a user slug from user data * * @param user - User object from auth * @returns string - Generated user slug */ function generateSlugFromUser(user: any): string { if (!user) return '' // Try to get username from user_metadata const username = user.user_metadata?.user_name if (username) { return username } // Fallback to user ID if no username available return user.id } /** * Main header component with navigation, search, and user actions * * @returns JSX.Element - Header component */ export function Header() { const [showMobileSearch, setShowMobileSearch] = useState(false) const [showMobileDrawer, setShowMobileDrawer] = useState(false) const [showAutocomplete, setShowAutocomplete] = useState(false) const [showMobileAutocomplete, setShowMobileAutocomplete] = useState(false) const { searchQuery, setSearchQuery, handleSearch } = useSearch() const { user, isLoaded, signOut } = useAuth() const { trackSearch } = useAnalyticsEvents() const userSlug = user ? generateSlugFromUser(user) : '' const isProfilePrivate = Boolean(user?.publicMetadata?.isProfilePrivate) // Check if profile is incomplete (needs name or username to be visible) const needsNameOrUsername = Boolean( user && !user.user_metadata?.full_name && !user.user_metadata?.user_name && !user.publicMetadata?.github_username ) // Auto-focus mobile search input when it appears and handle escape key useEffect(() => { if (showMobileSearch) { // Prevent body scroll when search is open document.body.style.overflow = 'hidden' } else { document.body.style.overflow = '' } return () => { document.body.style.overflow = '' } }, [showMobileSearch]) /** * Handles form submission for search * * @param e - Form event */ const onSubmit = (e: React.FormEvent) => { e.preventDefault() if (searchQuery.trim()) { // Track search submission trackSearch( searchQuery, 0, showMobileSearch ? 'header-mobile-search' : 'header-desktop-search' ) handleSearch(searchQuery) setSearchQuery('') setShowAutocomplete(false) setShowMobileAutocomplete(false) if (showMobileSearch) { setShowMobileSearch(false) setShowMobileAutocomplete(false) } } } /** * Handles desktop search input focus */ const handleInputFocus = () => { setShowAutocomplete(true) } /** * Handles mobile search input focus */ const handleMobileInputFocus = () => { setShowMobileAutocomplete(true) } /** * Handles desktop search input change * * @param e - Input change event */ const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => { setSearchQuery(e.target.value) if (!showAutocomplete) setShowAutocomplete(true) } /** * Handles mobile search input change * * @param e - Input change event */ const handleMobileSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => { setSearchQuery(e.target.value) if (!showMobileAutocomplete) setShowMobileAutocomplete(true) } return ( <> <header className="sticky top-0 z-50 bg-background/80 backdrop-blur-lg border-b border-border/50"> <div className="w-full px-4 sm:px-6 h-16 flex 2xl:grid 2xl:grid-cols-3 items-center justify-between 2xl:justify-center gap-3 sm:gap-4"> {/* Logo + Menu - Left */} <div className="flex items-center gap-2"> {/* Mobile menu toggle */} <button type="button" onClick={() => setShowMobileDrawer(true)} className="block sm:hidden p-2 hover:bg-muted rounded-md transition-colors -ml-2" aria-label="Open menu" > <Menu className="h-5 w-5" /> </button> <Link href={getRoute('home')} className="group text-lg font-bold whitespace-nowrap tracking-tight" > <span className="inline transition-colors">llms.txt</span> <span className="inline ml-1 text-muted-foreground group-hover:text-foreground transition-colors"> hub </span> </Link> </div> {/* Search - Center (prominent on desktop) */} <DesktopSearchForm searchQuery={searchQuery} onSearchChange={handleSearchChange} onInputFocus={handleInputFocus} onSubmit={onSubmit} showAutocomplete={showAutocomplete} onAutocompleteClose={() => setShowAutocomplete(false)} onAutocompleteSelect={() => { setShowAutocomplete(false) setSearchQuery('') }} /> {/* Navigation + Actions - Right */} <div className="flex items-center gap-2 sm:gap-4 2xl:justify-end"> {/* Desktop navigation */} <nav className="hidden lg:flex items-center gap-4"> <NavLink href={getRoute('projects')}>Projects</NavLink> <NavLink href={getRoute('docs.list')}>Docs</NavLink> <NavLink href={getRoute('guides.list')}>Guides</NavLink> <NavLink href={getRoute('members.list')}>Members</NavLink> {/* <NavLink href={getRoute('news')}>News</NavLink> */} </nav> {/* Mobile search icon */} <button type="button" className="md:hidden text-muted-foreground hover:text-foreground" onClick={() => setShowMobileSearch(!showMobileSearch)} aria-label="Toggle search" > <Search className="h-5 w-5" /> </button> <div> <GithubStars mobileCompact={true} /> </div> {!isLoaded ? ( <div className="h-9 w-9 sm:w-[88px]" /> ) : user ? ( <UserDropdownMenu user={user} userSlug={userSlug} isProfilePrivate={isProfilePrivate} needsNameOrUsername={needsNameOrUsername} onSignOut={signOut} /> ) : ( <Link href="/login" className="inline-flex items-center justify-center rounded-none text-sm font-bold h-9 px-4 bg-foreground text-background hover:bg-foreground/90 transition-all duration-200 press-effect" aria-label="Sign up" title="Sign up" > <UserPlus className="h-4 w-4 sm:hidden" /> <span className="hidden sm:inline">Sign Up</span> </Link> )} </div> </div> {/* Mobile search overlay */} <MobileSearchOverlay showMobileSearch={showMobileSearch} searchQuery={searchQuery} onSearchChange={handleMobileSearchChange} onInputFocus={handleMobileInputFocus} onSubmit={onSubmit} showMobileAutocomplete={showMobileAutocomplete} onMobileSearchClose={() => { setShowMobileSearch(false) setShowMobileAutocomplete(false) }} onAutocompleteSelect={() => { setShowMobileAutocomplete(false) setShowMobileSearch(false) setSearchQuery('') }} /> </header> {/* Mobile Drawer */} <MobileDrawer isOpen={showMobileDrawer} onClose={() => setShowMobileDrawer(false)} featuredCount={6} /> </> ) }

Search equations, builds, manuscript text, and recovered sources.