Spaces:
Build error
Build error
Upload components/Header.js with huggingface_hub
Browse files- components/Header.js +116 -22
components/Header.js
CHANGED
|
@@ -1,42 +1,118 @@
|
|
| 1 |
-
import { useState } from 'react'
|
| 2 |
import Link from 'next/link'
|
| 3 |
-
import {
|
| 4 |
-
import {
|
|
|
|
| 5 |
|
| 6 |
export default function Header() {
|
| 7 |
const [isMenuOpen, setIsMenuOpen] = useState(false)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
|
| 9 |
const navigation = [
|
| 10 |
-
{
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
]
|
| 15 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
return (
|
| 17 |
-
<header
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
| 19 |
<div className="flex justify-between items-center py-4">
|
| 20 |
{/* Logo */}
|
| 21 |
-
<Link
|
| 22 |
-
|
| 23 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
</div>
|
| 25 |
<div>
|
| 26 |
-
<span className="text-xl font-bold text-primary-700">
|
|
|
|
|
|
|
| 27 |
<p className="text-xs text-gray-600 -mt-1">Por Prof. Gabriel Ramos</p>
|
| 28 |
</div>
|
| 29 |
</Link>
|
| 30 |
|
| 31 |
{/* Desktop Navigation */}
|
| 32 |
-
<nav
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
{navigation.map((item) => (
|
| 34 |
<Link
|
| 35 |
key={item.name}
|
| 36 |
href={item.href}
|
| 37 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
>
|
| 39 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
</Link>
|
| 41 |
))}
|
| 42 |
</nav>
|
|
@@ -44,7 +120,9 @@ export default function Header() {
|
|
| 44 |
{/* Mobile menu button */}
|
| 45 |
<button
|
| 46 |
onClick={() => setIsMenuOpen(!isMenuOpen)}
|
| 47 |
-
className="md:hidden p-2 rounded-lg text-gray-600 hover:text-primary-600 hover:bg-gray-100"
|
|
|
|
|
|
|
| 48 |
>
|
| 49 |
{isMenuOpen ? <FiX className="h-6 w-6" /> : <FiMenu className="h-6 w-6" />}
|
| 50 |
</button>
|
|
@@ -52,16 +130,31 @@ export default function Header() {
|
|
| 52 |
|
| 53 |
{/* Mobile Navigation */}
|
| 54 |
{isMenuOpen && (
|
| 55 |
-
<div className="md:hidden border-t border-gray-200 py-4">
|
| 56 |
-
<nav
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
{navigation.map((item) => (
|
| 58 |
<Link
|
| 59 |
key={item.name}
|
| 60 |
href={item.href}
|
| 61 |
-
|
| 62 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
>
|
| 64 |
-
{item.
|
|
|
|
| 65 |
</Link>
|
| 66 |
))}
|
| 67 |
</nav>
|
|
@@ -77,7 +170,8 @@ export default function Header() {
|
|
| 77 |
href="https://huggingface.co/spaces/akhaliq/anycoder"
|
| 78 |
target="_blank"
|
| 79 |
rel="noopener noreferrer"
|
| 80 |
-
className="text-primary-600 hover:text-primary-700 font-medium transition-colors duration-200"
|
|
|
|
| 81 |
>
|
| 82 |
Built with anycoder
|
| 83 |
</a>
|
|
|
|
| 1 |
+
import { useState, useEffect } from 'react'
|
| 2 |
import Link from 'next/link'
|
| 3 |
+
import { useRouter } from 'next/router'
|
| 4 |
+
import { FiMenu, FiX, FiSearch } from 'react-icons/fi'
|
| 5 |
+
import { HiSparkles, HiBookOpen } from 'react-icons/hi'
|
| 6 |
|
| 7 |
export default function Header() {
|
| 8 |
const [isMenuOpen, setIsMenuOpen] = useState(false)
|
| 9 |
+
const [isScrolled, setIsScrolled] = useState(false)
|
| 10 |
+
const router = useRouter()
|
| 11 |
+
|
| 12 |
+
// Handle scroll effect for header
|
| 13 |
+
useEffect(() => {
|
| 14 |
+
const handleScroll = () => {
|
| 15 |
+
setIsScrolled(window.scrollY > 20)
|
| 16 |
+
}
|
| 17 |
+
window.addEventListener('scroll', handleScroll)
|
| 18 |
+
return () => window.removeEventListener('scroll', handleScroll)
|
| 19 |
+
}, [])
|
| 20 |
|
| 21 |
const navigation = [
|
| 22 |
+
{
|
| 23 |
+
name: 'Início',
|
| 24 |
+
href: '/',
|
| 25 |
+
icon: HiSparkles,
|
| 26 |
+
description: 'Página principal com visão geral'
|
| 27 |
+
},
|
| 28 |
+
{
|
| 29 |
+
name: 'Biblioteca de Prompts',
|
| 30 |
+
href: '/prompts',
|
| 31 |
+
icon: HiBookOpen,
|
| 32 |
+
description: 'Prompts especializados para sua área'
|
| 33 |
+
},
|
| 34 |
+
{
|
| 35 |
+
name: 'Sobre',
|
| 36 |
+
href: '#sobre',
|
| 37 |
+
description: 'Conheça o Prof. Gabriel Ramos'
|
| 38 |
+
},
|
| 39 |
+
{
|
| 40 |
+
name: 'Contato',
|
| 41 |
+
href: '#contato',
|
| 42 |
+
description: 'Entre em contato conosco'
|
| 43 |
+
},
|
| 44 |
]
|
| 45 |
|
| 46 |
+
const handleNavClick = (href) => {
|
| 47 |
+
setIsMenuOpen(false)
|
| 48 |
+
if (href.startsWith('#')) {
|
| 49 |
+
const element = document.querySelector(href)
|
| 50 |
+
if (element) {
|
| 51 |
+
element.scrollIntoView({ behavior: 'smooth' })
|
| 52 |
+
}
|
| 53 |
+
}
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
return (
|
| 57 |
+
<header
|
| 58 |
+
className={`sticky top-0 z-50 transition-all duration-300 ${
|
| 59 |
+
isScrolled
|
| 60 |
+
? 'bg-white/95 backdrop-blur-md shadow-medium'
|
| 61 |
+
: 'bg-white shadow-soft'
|
| 62 |
+
}`}
|
| 63 |
+
role="banner"
|
| 64 |
+
>
|
| 65 |
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
| 66 |
<div className="flex justify-between items-center py-4">
|
| 67 |
{/* Logo */}
|
| 68 |
+
<Link
|
| 69 |
+
href="/"
|
| 70 |
+
className="flex items-center space-x-3 group"
|
| 71 |
+
aria-label="AI.Wiki.BR - Voltar ao início"
|
| 72 |
+
>
|
| 73 |
+
<div className="bg-primary-600 p-2 rounded-xl group-hover:bg-primary-700 transition-colors duration-200">
|
| 74 |
+
<HiSparkles className="h-6 w-6 text-white" aria-hidden="true" />
|
| 75 |
</div>
|
| 76 |
<div>
|
| 77 |
+
<span className="text-xl font-bold text-primary-700 group-hover:text-primary-800 transition-colors duration-200">
|
| 78 |
+
AI.Wiki.BR
|
| 79 |
+
</span>
|
| 80 |
<p className="text-xs text-gray-600 -mt-1">Por Prof. Gabriel Ramos</p>
|
| 81 |
</div>
|
| 82 |
</Link>
|
| 83 |
|
| 84 |
{/* Desktop Navigation */}
|
| 85 |
+
<nav
|
| 86 |
+
className="hidden md:flex space-x-1"
|
| 87 |
+
role="navigation"
|
| 88 |
+
aria-label="Navegação principal"
|
| 89 |
+
>
|
| 90 |
{navigation.map((item) => (
|
| 91 |
<Link
|
| 92 |
key={item.name}
|
| 93 |
href={item.href}
|
| 94 |
+
onClick={(e) => {
|
| 95 |
+
if (item.href.startsWith('#')) {
|
| 96 |
+
e.preventDefault()
|
| 97 |
+
handleNavClick(item.href)
|
| 98 |
+
}
|
| 99 |
+
|
| 100 |
+
className={`relative px-4 py-2 rounded-lg font-medium transition-all duration-200 group ${
|
| 101 |
+
router.pathname === item.href || (item.href.startsWith('#') && router.asPath === '/')
|
| 102 |
+
? 'text-primary-700 bg-primary-50'
|
| 103 |
+
: 'text-gray-700 hover:text-primary-600 hover:bg-primary-50'
|
| 104 |
+
}`}
|
| 105 |
+
aria-label={item.description}
|
| 106 |
>
|
| 107 |
+
<span className="flex items-center space-x-2">
|
| 108 |
+
{item.icon && <item.icon className="h-4 w-4" aria-hidden="true" />}
|
| 109 |
+
<span>{item.name}</span>
|
| 110 |
+
</span>
|
| 111 |
+
|
| 112 |
+
{/* Active indicator */}
|
| 113 |
+
{(router.pathname === item.href || (item.href.startsWith('#') && router.asPath === '/')) && (
|
| 114 |
+
<div className="absolute bottom-0 left-1/2 transform -translate-x-1/2 w-1 h-1 bg-primary-600 rounded-full" />
|
| 115 |
+
)}
|
| 116 |
</Link>
|
| 117 |
))}
|
| 118 |
</nav>
|
|
|
|
| 120 |
{/* Mobile menu button */}
|
| 121 |
<button
|
| 122 |
onClick={() => setIsMenuOpen(!isMenuOpen)}
|
| 123 |
+
className="md:hidden p-2 rounded-lg text-gray-600 hover:text-primary-600 hover:bg-gray-100 focus:ring-4 focus:ring-primary-200 transition-all duration-200"
|
| 124 |
+
aria-expanded={isMenuOpen}
|
| 125 |
+
aria-label={isMenuOpen ? 'Fechar menu' : 'Abrir menu'}
|
| 126 |
>
|
| 127 |
{isMenuOpen ? <FiX className="h-6 w-6" /> : <FiMenu className="h-6 w-6" />}
|
| 128 |
</button>
|
|
|
|
| 130 |
|
| 131 |
{/* Mobile Navigation */}
|
| 132 |
{isMenuOpen && (
|
| 133 |
+
<div className="md:hidden border-t border-gray-200 py-4 animate-slide-up">
|
| 134 |
+
<nav
|
| 135 |
+
className="flex flex-col space-y-2"
|
| 136 |
+
role="navigation"
|
| 137 |
+
aria-label="Menu mobile"
|
| 138 |
+
>
|
| 139 |
{navigation.map((item) => (
|
| 140 |
<Link
|
| 141 |
key={item.name}
|
| 142 |
href={item.href}
|
| 143 |
+
onClick={(e) => {
|
| 144 |
+
if (item.href.startsWith('#')) {
|
| 145 |
+
e.preventDefault()
|
| 146 |
+
handleNavClick(item.href)
|
| 147 |
+
}
|
| 148 |
+
|
| 149 |
+
className={`flex items-center space-x-3 p-3 rounded-lg font-medium transition-all duration-200 ${
|
| 150 |
+
router.pathname === item.href || (item.href.startsWith('#') && router.asPath === '/')
|
| 151 |
+
? 'text-primary-700 bg-primary-50'
|
| 152 |
+
: 'text-gray-700 hover:text-primary-600 hover:bg-primary-50'
|
| 153 |
+
}`}
|
| 154 |
+
aria-label={item.description}
|
| 155 |
>
|
| 156 |
+
{item.icon && <item.icon className="h-5 w-5" aria-hidden="true" />}
|
| 157 |
+
<span>{item.name}</span>
|
| 158 |
</Link>
|
| 159 |
))}
|
| 160 |
</nav>
|
|
|
|
| 170 |
href="https://huggingface.co/spaces/akhaliq/anycoder"
|
| 171 |
target="_blank"
|
| 172 |
rel="noopener noreferrer"
|
| 173 |
+
className="text-primary-600 hover:text-primary-700 font-medium transition-colors duration-200 focus:ring-2 focus:ring-primary-300 rounded"
|
| 174 |
+
aria-label="Built with anycoder - Link externo"
|
| 175 |
>
|
| 176 |
Built with anycoder
|
| 177 |
</a>
|