Skip to content
Open

fixed #1348

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
177 changes: 123 additions & 54 deletions src/components/Footer.tsx
Original file line number Diff line number Diff line change
@@ -1,108 +1,177 @@
"use client";

import { useState } from "react";
import Link from "next/link";
import { Github, Twitter, Instagram, Linkedin, ArrowRight, ShieldCheck, Zap, Globe, ExternalLink, Lock, Mail } from "lucide-react";
import {
Github,
Twitter,
Instagram,
Linkedin,
ArrowRight,
ShieldCheck,
Zap,
Globe,
ExternalLink,
Lock,
Mail,
} from "lucide-react";

export default function Footer() {
const [isExpanded, setIsExpanded] = useState(false);

return (
<footer className="w-full border-t border-[var(--border)] bg-[var(--bg)] text-[var(--text)] px-6 py-16 mt-20 transition-colors duration-300">
<div className="max-w-7xl mx-auto grid grid-cols-1 md:grid-cols-12 gap-12 md:gap-8">

<div className="max-w-7xl mx-auto grid grid-cols-1 md:grid-cols-12 gap-y-12 md:gap-x-12">
{/* Brand Section */}
<div className="md:col-span-5 space-y-6">
<div className="space-y-1">
<div>
<h2 className="text-2xl font-bold tracking-tight">Reframe</h2>
<p className="text-[9px] font-mono tracking-[0.4em] uppercase opacity-50">Browser Video Studio</p>
<p className="text-[10px] font-mono tracking-[0.35em] uppercase opacity-50 mt-1">
Browser Video Studio
</p>
</div>
<p className="text-sm opacity-70 leading-relaxed max-w-sm">
Professional video processing directly in your browser using
<span className="font-medium opacity-100"> FFmpeg.wasm</span> — fast, private, and open source.

<p className="text-sm opacity-70 leading-relaxed max-w-md">
Professional video processing directly in your browser using{" "}
<span className="font-medium opacity-100">FFmpeg.wasm</span> — fast,
private, and open source.
</p>

<div className="flex flex-wrap gap-2">
{[
{ icon: <ShieldCheck size={12} />, label: "100% Local" },
{ icon: <Zap size={12} />, label: "Fast" },
{ icon: <Globe size={12} />, label: "Open Source" },
].map((tag) => (
<span key={tag.label} className="flex items-center gap-1.5 px-3 py-1 rounded-lg border border-[var(--border)] bg-[var(--surface)] text-[10px] font-semibold tracking-wide uppercase transition-all duration-200 hover:-translate-y-0.5 hover:border-[var(--accent)] hover:bg-[var(--accent-muted)] cursor-pointer select-none">
{tag.icon} {tag.label}
<span
key={tag.label}
className="flex items-center gap-1.5 px-3 py-1 rounded-lg border border-[var(--border)] bg-[var(--surface)] text-[10px] font-semibold tracking-wide uppercase opacity-80 hover:opacity-100 hover:border-[var(--accent)] transition-all"
>
{tag.icon}
{tag.label}
</span>
))}
</div>
</div>

{/* Links Section */}
{/* Navigation */}
<div className="md:col-span-3 space-y-5">
<h3 className="text-[10px] font-bold uppercase tracking-[0.2em] opacity-40">Navigation</h3>
<h3 className="text-[11px] font-bold uppercase tracking-[0.2em] opacity-60">
Navigation
</h3>

<nav className="flex flex-col gap-3 text-sm">
<a href="https://github.com/magic-peach/reframe" target="_blank" rel="noopener" className="opacity-70 hover:opacity-100 hover:text-[var(--accent)] hover:translate-x-1 transition-all duration-300 w-fit flex items-center gap-2 group">
<Github size={14} className="group-hover:scale-110 transition-transform duration-300" />
<a
href="https://github.com/magic-peach/reframe"
target="_blank"
rel="noopener noreferrer"
aria-label="GitHub repository"
className="flex items-center gap-2 opacity-70 hover:opacity-100 hover:text-[var(--accent)] transition-all w-fit focus-visible:outline focus-visible:outline-2 focus-visible:outline-[var(--accent)] rounded"
>
<Github size={14} />
GitHub
<ExternalLink size={10} className="opacity-0 group-hover:opacity-60 transition-opacity duration-300" />
<ExternalLink size={10} className="opacity-60" />
</a>
<Link href="/contact" className="opacity-70 hover:opacity-100 hover:text-[var(--accent)] hover:translate-x-1 transition-all duration-300 w-fit flex items-center gap-2 group">
<Mail size={14} className="group-hover:scale-110 transition-transform duration-300" />

<Link
href="/contact"
aria-label="Contact page"
className="flex items-center gap-2 opacity-70 hover:opacity-100 hover:text-[var(--accent)] transition-all w-fit focus-visible:outline focus-visible:outline-2 focus-visible:outline-[var(--accent)] rounded"
>
<Mail size={14} />
Contact
</Link>
<Link href="/privacy" className="opacity-70 hover:opacity-100 hover:text-[var(--accent)] hover:translate-x-1 transition-all duration-300 w-fit flex items-center gap-2 group">
<Lock size={14} className="group-hover:scale-110 transition-transform duration-300" />

<Link
href="/privacy"
aria-label="Privacy policy"
className="flex items-center gap-2 opacity-70 hover:opacity-100 hover:text-[var(--accent)] transition-all w-fit focus-visible:outline focus-visible:outline-2 focus-visible:outline-[var(--accent)] rounded"
>
<Lock size={14} />
Privacy Policy
</Link>
</nav>
</div>

{/* Right Section */}
<div className="md:col-span-4 flex flex-col items-start md:items-end space-y-8">

<div className="md:col-span-4 space-y-10 md:justify-self-end w-full md:w-auto">
{/* Newsletter */}
<div className="w-full flex flex-col items-start md:items-end gap-3">
<h3 className="text-[10px] font-bold uppercase tracking-[0.2em] opacity-40">Updates</h3>
{!isExpanded ? (
<button type="button" onClick={() => setIsExpanded(true)} aria-label="Open updates signup form" aria-expanded={isExpanded} aria-controls="updates-signup-form" className="w-40 px-3 flex items-center justify-center bg-[var(--surface)] border border-[var(--border)] rounded-lg py-3 hover:bg-[var(--border)] transition-all duration-500 group">
<span className="text-[10px] font-bold uppercase tracking-[0.2em] opacity-60 group-hover:opacity-100 transition-opacity">Stay Tuned</span>
<div className="space-y-3">
<h3 className="text-[11px] font-bold uppercase tracking-[0.2em] opacity-60">
Updates
</h3>

<form
className="flex items-center w-full sm:w-80 bg-[var(--surface)] border border-[var(--border)] rounded-lg px-3 focus-within:border-[var(--accent)] transition"
onSubmit={(e) => e.preventDefault()}
aria-label="Newsletter signup"
>
<input
type="email"
required
placeholder="Enter your email"
aria-label="Email address"
className="w-full bg-transparent py-3 text-[11px] font-semibold tracking-widest uppercase placeholder:opacity-30 focus:outline-none"
/>

<button
type="submit"
aria-label="Subscribe to updates"
onMouseDown={(e) => e.preventDefault()} className="text-[var(--accent)] hover:text-[var(--accent-hover)] transition p-1 focus-visible:outline focus-visible:outline-2 focus-visible:outline-[var(--accent)] rounded"
>
<ArrowRight size={16} />
</button>
) : (
<div id="updates-signup-form" className="w-full sm:w-72 px-4 flex items-center bg-[var(--surface)] border border-[var(--accent)] rounded-lg transition-all duration-500">
<form aria-label="Updates signup form" onSubmit={(e) => { e.preventDefault(); setIsExpanded(false); }} className="flex w-full items-center">
<input type="email" placeholder="ENTER EMAIL" className="bg-transparent border-none text-[10px] font-bold tracking-widest text-[var(--text)] focus:outline-none w-full py-3 placeholder:opacity-30" aria-label="Email address for updates" onBlur={() => setIsExpanded(false)} />
<button aria-label="Submit email for updates" type="submit" onMouseDown={(e) => e.preventDefault()} className="text-[var(--accent)] hover:text-[var(--accent-hover)] p-1">
<ArrowRight size={16} aria-hidden="true" />
</button>
</form>
</div>
)}
</form>
</div>

{/* Community */}
<div className="flex flex-col items-start md:items-end gap-3">
<h3 className="text-[10px] font-bold uppercase tracking-[0.2em] opacity-40">Community</h3>
<div className="flex items-center gap-3">
<div className="space-y-3">
<h3 className="text-[11px] font-bold uppercase tracking-[0.2em] opacity-60">
Community
</h3>

<div className="flex items-center gap-3 flex-wrap">
{[
{ href: "https://github.com/magic-peach/reframe", icon: <Github size={18} />, label: "GitHub", tooltip: "Star us on GitHub" },
{ href: "https://twitter.com", icon: <Twitter size={18} />, label: "Twitter", tooltip: "Follow on Twitter" },
{ href: "https://instagram.com", icon: <Instagram size={18} />, label: "Instagram", tooltip: "Follow on Instagram" },
{ href: "https://linkedin.com", icon: <Linkedin size={18} />, label: "LinkedIn", tooltip: "Connect on LinkedIn" },
{
href: "https://github.com/magic-peach/reframe",
icon: <Github size={18} />,
label: "GitHub",
},
{
href: "https://twitter.com",
icon: <Twitter size={18} />,
label: "Twitter",
},
{
href: "https://instagram.com",
icon: <Instagram size={18} />,
label: "Instagram",
},
{
href: "https://linkedin.com",
icon: <Linkedin size={18} />,
label: "LinkedIn",
},
].map((social) => (
<div key={social.label} className="relative group">
<a href={social.href} target="_blank" rel="noopener" aria-label={social.label} className="p-2.5 rounded-lg border border-[var(--border)] bg-[var(--surface)] hover:border-[var(--accent)] hover:bg-[var(--accent-muted)] transition-all duration-200 hover:-translate-y-1 active:scale-95 flex items-center justify-center">
<span className="opacity-70 group-hover:opacity-100 transition-opacity duration-200">{social.icon}</span>
</a>
<span className="absolute -top-9 left-1/2 -translate-x-1/2 bg-[var(--text)] text-[var(--bg)] text-[9px] font-bold uppercase tracking-widest px-2 py-1 rounded opacity-0 group-hover:opacity-100 transition-opacity duration-200 whitespace-nowrap pointer-events-none">
{social.tooltip}
<a
key={social.label}
href={social.href}
target="_blank"
rel="noopener noreferrer"
aria-label={social.label}
className="relative group p-2.5 rounded-lg border border-[var(--border)] bg-[var(--surface)] hover:border-[var(--accent)] hover:bg-[var(--accent-muted)] transition-all focus-visible:outline focus-visible:outline-2 focus-visible:outline-[var(--accent)]"
>
<span className="opacity-70 group-hover:opacity-100">
{social.icon}
</span>
</div>
</a>
))}
</div>
</div>
</div>
</div>

{/* Bottom Bar */}
<div className="max-w-7xl mx-auto mt-16 pt-8 border-t border-[var(--border)] flex flex-col md:flex-row justify-between items-center gap-4 text-[9px] font-bold uppercase tracking-[0.3em] opacity-40">
<div className="max-w-7xl mx-auto mt-16 pt-8 border-t border-[var(--border)] flex flex-col md:flex-row justify-between items-center gap-4 text-[10px] font-semibold uppercase tracking-[0.25em] opacity-50">
<p>© {new Date().getFullYear()} Reframe · MIT License</p>

<div className="flex items-center gap-2">
<span className="w-1.5 h-1.5 rounded-full bg-[var(--accent)] shadow-[0_0_8px_var(--accent)]" />
Processing happens locally
Expand Down