60 lines
2 KiB
TypeScript
60 lines
2 KiB
TypeScript
/**
|
|
* @component ScrollToTopAndThemeToggle
|
|
* @purpose Widgets matching Screenshots 1-5: Dark/Light Mode toggle pill (bottom-left) and Scroll-to-Top circular blue button (bottom-right).
|
|
* @a11y ARIA-labeled buttons, keyboard focusable
|
|
*/
|
|
'use client';
|
|
|
|
import { useState, useEffect } from 'react';
|
|
import { ArrowUp, Moon, Sun } from 'lucide-react';
|
|
|
|
export function ScrollToTopAndThemeToggle() {
|
|
const [showScroll, setShowScroll] = useState(false);
|
|
const [darkMode, setDarkMode] = useState(false);
|
|
|
|
useEffect(() => {
|
|
const handleScroll = () => {
|
|
setShowScroll(window.scrollY > 300);
|
|
};
|
|
window.addEventListener('scroll', handleScroll);
|
|
return () => window.removeEventListener('scroll', handleScroll);
|
|
}, []);
|
|
|
|
const toggleTheme = () => {
|
|
const nextState = !darkMode;
|
|
setDarkMode(nextState);
|
|
if (nextState) {
|
|
document.documentElement.classList.add('dark');
|
|
} else {
|
|
document.documentElement.classList.remove('dark');
|
|
}
|
|
};
|
|
|
|
const scrollToTop = () => {
|
|
window.scrollTo({ top: 0, behavior: 'smooth' });
|
|
};
|
|
|
|
return (
|
|
<>
|
|
{/* Dark/Light Mode Toggle Switch (Bottom Left) */}
|
|
<button
|
|
onClick={toggleTheme}
|
|
aria-label="Toggle Theme"
|
|
className="fixed bottom-4 left-4 z-40 bg-[#1b2559] dark:bg-slate-800 text-white p-2.5 rounded-full shadow-xl border border-gray-700 hover:scale-105 transition-transform flex items-center justify-center cursor-pointer"
|
|
>
|
|
{darkMode ? <Sun className="w-4 h-4 text-amber-400" /> : <Moon className="w-4 h-4 text-blue-300" />}
|
|
</button>
|
|
|
|
{/* Scroll to Top Circular Button (Bottom Right) */}
|
|
{showScroll && (
|
|
<button
|
|
onClick={scrollToTop}
|
|
aria-label="Scroll to top"
|
|
className="fixed bottom-4 right-4 z-40 bg-[#1877f2] hover:bg-[#1565c0] text-white p-3 rounded-full shadow-xl transition-all cursor-pointer animate-in fade-in duration-200"
|
|
>
|
|
<ArrowUp className="w-4 h-4" />
|
|
</button>
|
|
)}
|
|
</>
|
|
);
|
|
}
|