Skip to content
Open
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
129 changes: 43 additions & 86 deletions src/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React, { useState, useEffect } from 'react';
import { Menu, X, Search, Sun, Moon } from 'lucide-react';
import { Menu, Search, Sun, Moon } from 'lucide-react';
import { useLocation, Link } from 'react-router-dom';
import { useTheme } from '../context/ThemeContext';
import Sidebar from './Sidebar';

const Header: React.FC = () => {
const [isScrolled, setIsScrolled] = useState(false);
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
const location = useLocation();
const { theme, toggleTheme } = useTheme();
const isLandingPage = location.pathname === '/';
Expand Down Expand Up @@ -36,31 +37,34 @@ const Header: React.FC = () => {
>
<div className="container mx-auto px-4 md:px-8 lg:px-12">
<div className="flex items-center justify-between">
{/* Logo */}
<Link to="/" className="flex items-center">
<img
src="/iotastudiologo.png"
alt="iotastudio logo"
className="h-12 w-12 mr-4 drop-shadow-lg object-contain"
/>
<div className="flex items-center">
<span className="text-2xl md:text-3xl lg:text-4xl font-bold tracking-tight text-neutral-900 dark:text-white">
iotastudio
</span>
<span className="text-2xl md:text-3xl lg:text-4xl font-bold tracking-tight text-teal-500">
.ai
</span>
</div>
</Link>
<div className="flex items-center">
{/* Hamburger Menu */}
<button
className="mr-4 focus:outline-none"
onClick={() => setIsSidebarOpen(true)}
aria-label="Toggle menu"
>
<Menu size={28} className="text-neutral-900 dark:text-neutral-100" />
</button>
{/* Logo */}
<Link to="/" className="flex items-center">
<img
src="/iotastudiologo.png"
alt="iotastudio logo"
className="h-12 w-12 mr-4 drop-shadow-lg object-contain"
/>
<div className="flex items-center">
<span className="text-2xl md:text-3xl lg:text-4xl font-bold tracking-tight text-neutral-900 dark:text-white">
iotastudio
</span>
<span className="text-2xl md:text-3xl lg:text-4xl font-bold tracking-tight text-teal-500">
.ai
</span>
</div>
</Link>
</div>


{/* Nav */}
<nav className="hidden lg:flex items-center space-x-8 xl:space-x-12">
{['#features', '#how-it-works', '#for-developers', '#for-users'].map((href) => (
<a key={href} href={href} className={commonLinkClasses}>
{href.replace('#', '').replace(/-/g, ' ').replace(/\b\w/g, c => c.toUpperCase())}
</a>
))}
</nav>

{/* Desktop Icons */}
<div className="hidden lg:flex items-center space-x-4 xl:space-x-6">
Expand Down Expand Up @@ -91,69 +95,22 @@ const Header: React.FC = () => {
</Link>
</div>

{/* Mobile Toggle */}
<button
className="lg:hidden focus:outline-none"
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
aria-label="Toggle menu"
>
{isMobileMenuOpen ? (
<X size={28} className="text-neutral-900 dark:text-neutral-100" />
) : (
<Menu size={28} className="text-neutral-900 dark:text-neutral-100" />
)}
</button>
</div>
</div>

{/* Mobile Menu */}
{isMobileMenuOpen && (
<div className="lg:hidden absolute w-full left-0 top-full bg-white dark:bg-[#1E2117] border-t border-neutral-300 dark:border-neutral-800 backdrop-blur-sm transition-colors">
<div className="container mx-auto px-6 py-4">
<nav className="flex flex-col space-y-4">
{['#features', '#for-developers', '#for-users'].map((href) => (
<a
key={href}
href={href}
className={`${commonLinkClasses} py-2`}
onClick={() => setIsMobileMenuOpen(false)}
>
{href.replace('#', '').replace(/-/g, ' ').replace(/\b\w/g, c => c.toUpperCase())}
</a>
))}

<div className="pt-4 border-t border-neutral-300 dark:border-neutral-800 flex flex-col space-y-3">
<Link
to="/login"
className={`${borderButtonClass} border-neutral-900 text-neutral-900 dark:border-neutral-100 dark:text-neutral-100 hover:bg-black/10 dark:hover:bg-white/10`}
onClick={() => setIsMobileMenuOpen(false)}
>
Log In
</Link>
<Link
to="/signup"
className={`${borderButtonClass} border-neutral-900 text-neutral-900 dark:border-neutral-100 dark:text-neutral-100 hover:bg-black/10 dark:hover:bg-white/10`}
onClick={() => setIsMobileMenuOpen(false)}
>
Sign Up
</Link>
</div>
<div className="flex items-center lg:hidden">
<button onClick={toggleTheme} className={iconButtonClass} aria-label="Toggle theme">
{theme === 'dark' ? (
<Sun size={24} className="text-neutral-900 dark:text-neutral-100" />
) : (
<Moon size={24} className="text-neutral-900 dark:text-neutral-100" />
)}
</button>

<button
onClick={toggleTheme}
className="mt-4 flex items-center justify-center w-12 h-12 rounded-full hover:bg-black/10 dark:hover:bg-white/10 transition-colors"
aria-label="Toggle theme"
>
{theme === 'dark' ? (
<Sun size={24} className="text-neutral-900 dark:text-neutral-100" />
) : (
<Moon size={24} className="text-neutral-900 dark:text-neutral-100" />
)}
</button>
</nav>
<button className={iconButtonClass} aria-label="Search">
<Search size={24} className="text-neutral-900 dark:text-neutral-100" />
</button>
</div>
</div>
)}
</div>
<Sidebar isOpen={isSidebarOpen} onClose={() => setIsSidebarOpen(false)} />
</header>
);
};
Expand Down
69 changes: 69 additions & 0 deletions src/components/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import React from 'react';
import { X } from 'lucide-react';
import { HashLink } from 'react-router-hash-link';
import { Link } from 'react-router-dom';

interface SidebarProps {
isOpen: boolean;
onClose: () => void;
}

const navLinks = [
{ name: 'Home', href: '/browse-models' },
{ name: 'Features', href: '#features' },
{ name: 'How It Works', href: '#how-it-works' },
{ name: 'For Developers', href: '#for-developers' },
{ name: 'For Users', href: '#for-users' },
];

const Sidebar: React.FC<SidebarProps> = ({ isOpen, onClose }) => {
return (
<>
{/* Overlay */}
<div
className={`fixed inset-0 bg-black bg-opacity-50 z-50 transition-opacity duration-300 ease-in-out ${isOpen ? 'opacity-100' : 'opacity-0 pointer-events-none'}`}
onClick={onClose}
></div>

{/* Sidebar */}
<div
className={`fixed top-0 left-0 h-full w-72 bg-white dark:bg-gray-800 shadow-lg z-50 transform transition-transform duration-300 ease-in-out ${isOpen ? 'translate-x-0' : '-translate-x-full'}`}
>
<div className="p-4 flex justify-between items-center border-b border-gray-200 dark:border-gray-700">
<h2 className="text-xl font-bold text-neutral-900 dark:text-white">Menu</h2>
<button onClick={onClose} className="p-2 rounded-full hover:bg-gray-200 dark:hover:bg-gray-700">
<X className="w-6 h-6 text-neutral-900 dark:text-white" />
</button>
</div>
<nav className="p-4">
<ul>
{navLinks.map((link) => (
<li key={link.name}>
{link.name === 'Home' ? (
<Link
to={link.href}
onClick={onClose}
className="block py-3 px-4 text-lg font-semibold text-neutral-900 dark:text-neutral-100 hover:bg-teal-50 dark:hover:bg-gray-700 rounded-md transition-colors"
>
{link.name}
</Link>
) : (
<HashLink
smooth
to={link.href}
onClick={onClose}
className="block py-3 px-4 text-lg font-semibold text-neutral-900 dark:text-neutral-100 hover:bg-teal-50 dark:hover:bg-gray-700 rounded-md transition-colors"
>
{link.name}
</HashLink>
)}
</li>
))}
</ul>
</nav>
</div>
</>
);
};

export default Sidebar;
30 changes: 15 additions & 15 deletions src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,28 +23,28 @@ function ThemedApp() {
const { theme } = useTheme();

return (
<div className={theme}>
<BrowserRouter>
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<App />} />
<Route path="login" element={<LoginPage />} />
<Route path="signup" element={<SignUpPage />} />
<Route path="get-started" element={<LoginPage />} />
<Route path="publish" element={<PublishModel />} />
<Route path="browse-models" element={<BrowseModels />} /> {/* ✅ ADD THIS */}
<Route path="*" element={<Navigate to="/" replace />} />
</Route>
</Routes>
</BrowserRouter>
<div className={theme}>
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<App />} />
<Route path="login" element={<LoginPage />} />
<Route path="signup" element={<SignUpPage />} />
<Route path="get-started" element={<LoginPage />} />
<Route path="publish" element={<PublishModel />} />
<Route path="browse-models" element={<BrowseModels />} />
<Route path="*" element={<Navigate to="/" replace />} />
</Route>
</Routes>
</div>
);
}

createRoot(document.getElementById('root')!).render(
<StrictMode>
<ThemeProvider>
<ThemedApp />
<BrowserRouter>
<ThemedApp />
</BrowserRouter>
</ThemeProvider>
</StrictMode>
);