mirror of
https://github.com/wu736139669/hapi.git
synced 2026-11-07 01:21:37 +00:00
111 lines
5.4 KiB
TypeScript
111 lines
5.4 KiB
TypeScript
import { Button } from "@/components/ui/button";
|
|
import { Github, Menu, X } from "lucide-react";
|
|
import { useState } from "react";
|
|
import { Link } from "wouter";
|
|
import { ModeToggle } from "./ModeToggle";
|
|
import { LanguageToggle } from "./LanguageToggle";
|
|
import { useTranslation } from "react-i18next";
|
|
|
|
export default function Layout({ children }: { children: React.ReactNode }) {
|
|
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
|
const { t } = useTranslation();
|
|
|
|
return (
|
|
<div className="min-h-screen flex flex-col bg-background font-sans selection:bg-primary selection:text-primary-foreground">
|
|
{/* Header */}
|
|
<header className="sticky top-0 z-50 w-full border-b-2 border-border bg-background/70 backdrop-blur-xl supports-[backdrop-filter]:bg-background/60">
|
|
<div className="container flex h-16 items-center justify-between">
|
|
<div className="flex items-center gap-2">
|
|
<Link href="/" className="flex items-center gap-2 group">
|
|
<img src="/logo.svg" alt="" className="h-8 w-8 transition-transform group-hover:translate-y-0.5" />
|
|
<span className="font-bold text-xl tracking-tight">HAPI</span>
|
|
</Link>
|
|
</div>
|
|
|
|
{/* Desktop Nav */}
|
|
<nav className="hidden md:flex items-center gap-6">
|
|
<div className="flex items-center gap-4">
|
|
<LanguageToggle />
|
|
<ModeToggle />
|
|
<a href="https://github.com/tiann/hapi" target="_blank" rel="noreferrer" className="text-muted-foreground hover:text-foreground transition-colors">
|
|
<Github className="h-5 w-5" />
|
|
</a>
|
|
<Button className="font-bold shadow-hard hover:translate-y-0.5 hover:shadow-none transition-all border-2 border-border" asChild>
|
|
<a href="/docs/">{t('nav.getStarted')}</a>
|
|
</Button>
|
|
</div>
|
|
</nav>
|
|
|
|
{/* Mobile Menu Toggle */}
|
|
<div className="flex items-center gap-4 md:hidden">
|
|
<LanguageToggle />
|
|
<ModeToggle />
|
|
<button className="p-2" onClick={() => setIsMenuOpen(!isMenuOpen)}>
|
|
{isMenuOpen ? <X className="h-6 w-6" /> : <Menu className="h-6 w-6" />}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Mobile Nav */}
|
|
{isMenuOpen && (
|
|
<div className="md:hidden border-b-2 border-border bg-background p-4">
|
|
<nav className="flex flex-col gap-4">
|
|
<div className="flex flex-col gap-2">
|
|
<Button className="w-full font-bold shadow-hard border-2 border-border" asChild>
|
|
<a href="/docs/">{t('nav.getStarted')}</a>
|
|
</Button>
|
|
<a href="https://github.com/tiann/hapi" target="_blank" rel="noreferrer" className="flex items-center justify-center gap-2 text-sm font-medium p-2 hover:bg-muted rounded-md">
|
|
<Github className="h-4 w-4" /> {t('nav.viewOnGithub')}
|
|
</a>
|
|
</div>
|
|
</nav>
|
|
</div>
|
|
)}
|
|
</header>
|
|
|
|
{/* Main Content */}
|
|
<main className="flex-1">
|
|
{children}
|
|
</main>
|
|
|
|
{/* Footer */}
|
|
<footer className="border-t-2 border-border bg-muted/30 py-12">
|
|
<div className="container">
|
|
<div className="grid grid-cols-1 md:grid-cols-4 gap-8">
|
|
<div className="col-span-1 md:col-span-2">
|
|
<div className="flex items-center gap-2 mb-4">
|
|
<img src="/logo.svg" alt="" className="h-8 w-8" />
|
|
<span className="font-bold text-xl tracking-tight">HAPI</span>
|
|
</div>
|
|
<p className="text-muted-foreground text-sm max-w-xs leading-relaxed" dangerouslySetInnerHTML={{ __html: t('footer.desc') }} />
|
|
</div>
|
|
|
|
<div>
|
|
<h3 className="font-bold mb-4">{t('footer.product')}</h3>
|
|
<ul className="space-y-2 text-sm text-muted-foreground">
|
|
<li><a href="#features" className="hover:text-foreground transition-colors">{t('nav.features')}</a></li>
|
|
<li><a href="#how-it-works" className="hover:text-foreground transition-colors">{t('nav.howItWorks')}</a></li>
|
|
<li><a href="#installation" className="hover:text-foreground transition-colors">{t('nav.installation')}</a></li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div>
|
|
<h3 className="font-bold mb-4">{t('footer.community')}</h3>
|
|
<ul className="space-y-2 text-sm text-muted-foreground">
|
|
<li><a href="https://github.com/tiann/hapi" target="_blank" rel="noreferrer" className="hover:text-foreground transition-colors">GitHub</a></li>
|
|
<li><a href="https://github.com/tiann/hapi/issues" target="_blank" rel="noreferrer" className="hover:text-foreground transition-colors">Issues</a></li>
|
|
<li><a href="https://twitter.com/tiann" target="_blank" rel="noreferrer" className="hover:text-foreground transition-colors">Twitter</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="mt-12 pt-8 border-t-2 border-border flex flex-col md:flex-row justify-between items-center gap-4 text-sm text-muted-foreground">
|
|
<p>{t('footer.copyright', { year: new Date().getFullYear() })}</p>
|
|
<p dangerouslySetInnerHTML={{ __html: t('footer.designedWith') }} />
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
</div>
|
|
);
|
|
}
|