Light mode
This commit is contained in:
@@ -2,8 +2,10 @@
|
||||
|
||||
'use client';
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useTheme } from 'next-themes';
|
||||
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
|
||||
import { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';
|
||||
import { oneDark, oneLight } from 'react-syntax-highlighter/dist/esm/styles/prism';
|
||||
|
||||
const pythonCode = `import quantum_entanglement
|
||||
import neural_net_vibes
|
||||
@@ -44,16 +46,26 @@ if __name__ == "__main__":
|
||||
analyzer.check_is_sandwich(target="glizzy")`;
|
||||
|
||||
export default function BlurredCode() {
|
||||
const { resolvedTheme } = useTheme();
|
||||
const [mounted, setMounted] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => setMounted(true), 0);
|
||||
return () => clearTimeout(timer);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="absolute inset-0 overflow-hidden bg-[#0d1117] z-0 pointer-events-none flex justify-center">
|
||||
<div className="relative w-full h-full text-left p-8 opacity-40 blur-[2px] group-hover:blur-none group-hover:opacity-100 transition-all duration-700 animate-[scrollUp_40s_linear_infinite]">
|
||||
<SyntaxHighlighter
|
||||
language="python"
|
||||
style={vscDarkPlus}
|
||||
customStyle={{ background: 'transparent', margin: 0, padding: 0, fontSize: '14px' }}
|
||||
>
|
||||
{pythonCode + '\n\n\n' + pythonCode + '\n\n\n' + pythonCode}
|
||||
</SyntaxHighlighter>
|
||||
<div className="absolute inset-0 overflow-hidden bg-slate-50 dark:bg-[#0d1117] transition-colors duration-300 z-0 pointer-events-none flex justify-center">
|
||||
<div className="relative w-full h-full text-left p-8 opacity-40 blur-[3px] group-hover:blur-[2px] group-hover:opacity-100 transition-all duration-700 animate-[scrollUp_40s_linear_infinite] [&_pre]:bg-transparent! [&_code]:bg-transparent!">
|
||||
{mounted && (
|
||||
<SyntaxHighlighter
|
||||
language="python"
|
||||
style={resolvedTheme === 'light' ? oneLight : oneDark}
|
||||
customStyle={{ margin: 0, padding: 0, fontSize: '14px' }}
|
||||
>
|
||||
{pythonCode + '\n\n\n' + pythonCode + '\n\n\n' + pythonCode}
|
||||
</SyntaxHighlighter>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -2,23 +2,41 @@
|
||||
|
||||
'use client';
|
||||
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useTheme } from 'next-themes';
|
||||
|
||||
interface MatrixRainProps {
|
||||
color?: string;
|
||||
fps?: number;
|
||||
}
|
||||
|
||||
export default function MatrixRain({ color = '#84c0a0', fps = 15 }: MatrixRainProps) {
|
||||
export default function MatrixRain({ color, fps = 15 }: MatrixRainProps) {
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||
const lastWidth = useRef<number>(0);
|
||||
const { resolvedTheme } = useTheme();
|
||||
const [mounted, setMounted] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => setMounted(true), 0);
|
||||
return () => clearTimeout(timer);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!mounted) return;
|
||||
|
||||
const canvas = canvasRef.current;
|
||||
if (!canvas) return;
|
||||
const ctx = canvas.getContext('2d');
|
||||
if (!ctx) return;
|
||||
|
||||
const isLight = resolvedTheme === 'light';
|
||||
// Use slate-50 (#f8fafc) for light mode, #0d1117 for dark mode
|
||||
const bgColor = isLight ? '#f8fafc' : '#0d1117';
|
||||
// The semi-transparent overlay that creates the fading trail effect
|
||||
const fadeColor = isLight ? 'rgba(248, 250, 252, 0.2)' : 'rgba(13, 17, 23, 0.2)';
|
||||
// A darker green for light mode to maintain contrast, or the default/prop color for dark mode
|
||||
const textColor = color || (isLight ? '#1c2d25' : '#84c0a0');
|
||||
|
||||
const fontSize = 16;
|
||||
let columns = 0;
|
||||
let drops: number[] = [];
|
||||
@@ -26,7 +44,7 @@ export default function MatrixRain({ color = '#84c0a0', fps = 15 }: MatrixRainPr
|
||||
const setCanvasSize = () => {
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight + 120;
|
||||
ctx.fillStyle = '#0d1117';
|
||||
ctx.fillStyle = bgColor;
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
};
|
||||
|
||||
@@ -43,13 +61,13 @@ export default function MatrixRain({ color = '#84c0a0', fps = 15 }: MatrixRainPr
|
||||
initDrops();
|
||||
|
||||
const draw = () => {
|
||||
ctx.fillStyle = 'rgba(13, 17, 23, 0.2)';
|
||||
ctx.fillStyle = fadeColor;
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.font = `bold ${fontSize}px monospace`;
|
||||
|
||||
for (let i = 0; i < drops.length; i++) {
|
||||
const text = Math.random() > 0.5 ? '0' : '1';
|
||||
ctx.fillStyle = color;
|
||||
ctx.fillStyle = textColor;
|
||||
ctx.fillText(text, i * fontSize, drops[i] * fontSize);
|
||||
|
||||
if (drops[i] * fontSize > canvas.height && Math.random() > 0.975) {
|
||||
@@ -75,14 +93,16 @@ export default function MatrixRain({ color = '#84c0a0', fps = 15 }: MatrixRainPr
|
||||
clearInterval(intervalId);
|
||||
window.removeEventListener('resize', handleResize);
|
||||
};
|
||||
}, [color, fps]);
|
||||
}, [color, fps, resolvedTheme, mounted]); // Re-run effect if theme changes
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 pointer-events-none w-screen h-[110vh] bg-[#0d1117]" style={{ zIndex: -1 }}>
|
||||
<canvas
|
||||
ref={canvasRef}
|
||||
className="absolute inset-0 w-full h-full opacity-[0.15] blur-[0.5px]"
|
||||
/>
|
||||
<div className="fixed inset-0 pointer-events-none w-screen h-[110vh] bg-slate-50 dark:bg-[#0d1117] transition-colors duration-300" style={{ zIndex: -1 }}>
|
||||
{mounted && (
|
||||
<canvas
|
||||
ref={canvasRef}
|
||||
className="absolute inset-0 w-full h-full opacity-[0.35] dark:opacity-[0.15] blur-[0.5px]"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
+36
-14
@@ -3,51 +3,61 @@
|
||||
'use client';
|
||||
|
||||
import Link from 'next/link';
|
||||
import { useState } from 'react';
|
||||
import { useState, useEffect } from 'react';
|
||||
import Image from 'next/image';
|
||||
import { useTheme } from 'next-themes';
|
||||
import { FaSun, FaMoon } from 'react-icons/fa';
|
||||
|
||||
export default function Navbar() {
|
||||
const [isExpanded, setIsExpanded] = useState(false);
|
||||
const { theme, setTheme } = useTheme();
|
||||
const [mounted, setMounted] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => setMounted(true), 0);
|
||||
return () => clearTimeout(timer);
|
||||
}, []);
|
||||
|
||||
const toggleMenu = () => setIsExpanded(!isExpanded);
|
||||
const closeMenu = () => setIsExpanded(false);
|
||||
|
||||
return (
|
||||
<header className="fixed h-25 bg-[#0d1117]/80 backdrop-blur-md border-b border-white/10 left-0 right-0 z-100 transition-all duration-300">
|
||||
<nav className="flex justify-between h-full items-center max-w-400 px-8 mx-auto">
|
||||
<header className="fixed h-25 bg-white/80 dark:bg-[#0d1117]/80 backdrop-blur-md border-b border-slate-200 dark:border-white/10 left-0 right-0 z-100 transition-colors duration-300">
|
||||
<nav className="flex justify-between h-full items-center max-w-450 px-8 mx-auto">
|
||||
|
||||
<Link href="/" className="group text-white no-underline flex uppercase font-extrabold items-center tracking-[1px] transition-transform hover:scale-105" onClick={closeMenu}>
|
||||
<div className="w-12 h-12 flex justify-center items-center rounded-full bg-[#84c0a0]/10 border border-[#84c0a0]/30 shadow-[0_0_15px_rgba(132,192,160,0.2)] group-hover:bg-[#84c0a0]/20 transition-all duration-300">
|
||||
<Link href="/" className="group text-slate-900 dark:text-white no-underline flex uppercase font-extrabold items-center tracking-[1px] transition-transform hover:scale-105" onClick={closeMenu}>
|
||||
<div className="w-12 h-12 flex justify-center items-center rounded-full bg-[#84c0a0] dark:bg-[#84c0a0]/10 border border-[#84c0a0]/30 shadow-[0_0_15px_rgba(132,192,160,0.2)] group-hover:bg-[#84c0a0]/80 group-hover:dark:bg-[#84c0a0]/20 transition-all duration-300">
|
||||
<Image
|
||||
src="/assets/logos/logo.svg"
|
||||
alt="Wiking"
|
||||
width={32}
|
||||
height={32}
|
||||
className="w-8 h-8 filter dark:invert-0 invert"
|
||||
className="w-8 h-8"
|
||||
/>
|
||||
</div>
|
||||
<span className="hidden md:block ml-4 text-sm tracking-widest text-[#84c0a0] font-mono group-hover:text-white transition-colors">
|
||||
<span className="hidden md:block ml-4 text-sm tracking-widest text-[#84c0a0] font-mono transition">
|
||||
SODERBERG TECH
|
||||
</span>
|
||||
</Link>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="cursor-pointer border-none bg-transparent w-10 h-10 flex items-center justify-center flex-col md:hidden relative group"
|
||||
className="cursor-pointer border-none bg-transparent w-10 h-10 flex items-center justify-center flex-col md:hidden relative group z-50"
|
||||
aria-expanded={isExpanded}
|
||||
onClick={toggleMenu}
|
||||
>
|
||||
<span className={`block h-0.5 bg-white transition-all duration-300 ease-in-out group-hover:bg-[#84c0a0] ${isExpanded ? 'absolute m-0 w-7 rotate-45' : 'w-6 m-0.75'}`}></span>
|
||||
<span className={`block h-0.5 bg-white transition-all duration-300 ease-in-out group-hover:bg-[#84c0a0] ${isExpanded ? 'opacity-0 w-0' : 'w-6 m-0.75'}`}></span>
|
||||
<span className={`block h-0.5 bg-white transition-all duration-300 ease-in-out group-hover:bg-[#84c0a0] ${isExpanded ? 'absolute m-0 w-7 -rotate-45' : 'w-6 m-0.75'}`}></span>
|
||||
<span className={`block h-0.5 bg-slate-900 dark:bg-white transition-all duration-300 ease-in-out group-hover:bg-[#84c0a0] ${isExpanded ? 'absolute m-0 w-7 rotate-45' : 'w-6 m-0.75'}`}></span>
|
||||
<span className={`block h-0.5 bg-slate-900 dark:bg-white transition-all duration-300 ease-in-out group-hover:bg-[#84c0a0] ${isExpanded ? 'opacity-0 w-0' : 'w-6 m-0.75'}`}></span>
|
||||
<span className={`block h-0.5 bg-slate-900 dark:bg-white transition-all duration-300 ease-in-out group-hover:bg-[#84c0a0] ${isExpanded ? 'absolute m-0 w-7 -rotate-45' : 'w-6 m-0.75'}`}></span>
|
||||
</button>
|
||||
|
||||
<div
|
||||
className={`fixed top-25 bottom-0 left-0 right-0 transition-all duration-300 md:static md:block md:opacity-100 md:visible md:h-full ${isExpanded ? 'bg-[#0d1117]/60 backdrop-blur-sm opacity-100 visible' : 'opacity-0 invisible'}`}
|
||||
className={`fixed top-25 bottom-0 left-0 right-0 transition-all duration-300 md:static md:block md:opacity-100 md:visible md:h-full ${isExpanded ? 'bg-white/90 dark:bg-[#0d1117]/60 backdrop-blur-sm opacity-100 visible' : 'opacity-0 invisible'}`}
|
||||
onClick={closeMenu}
|
||||
>
|
||||
<ul
|
||||
className={`list-none absolute flex flex-col items-center left-0 right-0 m-4 rounded-3xl bg-[#131920]/70 backdrop-blur-2xl md:backdrop-blur-none border border-white/10 shadow-2xl md:m-0 md:p-0 md:border-none md:shadow-none md:static md:flex-row md:w-full md:h-full md:bg-transparent md:justify-end gap-2 md:gap-8 transition-all duration-300 ${isExpanded ? 'p-8 translate-y-0 opacity-100' : '-translate-y-4 opacity-0 md:translate-y-0 md:opacity-100'}`}
|
||||
// Added md:dark:bg-transparent and md:dark:border-none to clear the mobile dark mode styling on desktop!
|
||||
className={`list-none absolute flex flex-col items-center left-0 right-0 m-4 rounded-3xl bg-white/90 dark:bg-[#0d1117]/90 backdrop-blur-2xl md:backdrop-blur-none border border-slate-200 dark:border-white/10 md:border-none md:dark:border-none shadow-2xl md:m-0 md:p-0 md:shadow-none md:static md:flex-row md:w-full md:h-full md:bg-transparent md:dark:bg-transparent md:justify-end gap-2 md:gap-8 transition-all duration-300 ${isExpanded ? 'p-8 translate-y-0 opacity-100' : '-translate-y-4 opacity-0 md:translate-y-0 md:opacity-100'}`}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
{[
|
||||
@@ -58,7 +68,7 @@ export default function Navbar() {
|
||||
].map((link) => (
|
||||
<li key={link.name} className="w-full md:w-auto">
|
||||
<Link
|
||||
className="relative flex justify-center items-center text-gray-300 uppercase font-bold tracking-[2px] text-sm px-4 py-3 rounded-xl hover:text-white hover:bg-white/5 transition-all duration-300 group overflow-hidden"
|
||||
className="relative flex justify-center items-center text-slate-600 dark:text-gray-300 uppercase font-bold tracking-[2px] text-sm px-4 py-3 rounded-xl hover:text-slate-900 dark:hover:text-white hover:bg-slate-100 dark:hover:bg-white/5 transition-all duration-300 group overflow-hidden"
|
||||
href={link.path}
|
||||
onClick={closeMenu}
|
||||
>
|
||||
@@ -67,6 +77,18 @@ export default function Navbar() {
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
|
||||
<li className="w-full md:w-auto flex justify-center mt-4 md:mt-0 md:pl-2">
|
||||
{mounted && (
|
||||
<button
|
||||
onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}
|
||||
className="p-3 md:p-2.5 rounded-full bg-slate-100 dark:bg-white/10 text-slate-600 dark:text-white hover:bg-slate-200 dark:hover:bg-white/20 transition-all flex items-center justify-center"
|
||||
aria-label="Toggle Theme"
|
||||
>
|
||||
{theme === 'dark' ? <FaSun size={18} /> : <FaMoon size={18} />}
|
||||
</button>
|
||||
)}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
@@ -15,7 +15,7 @@ interface GalleryImage {
|
||||
|
||||
export default function PhotoGallery({ images }: { images: GalleryImage[] }) {
|
||||
return (
|
||||
<div className="bg-[#0a0d11] flex justify-center w-full min-h-screen border-t border-white/5">
|
||||
<div className="bg-slate-100 dark:bg-[#0a0d11] flex justify-center w-full min-h-screen border-t border-slate-200 dark:border-white/5 transition-colors duration-300">
|
||||
<Gallery>
|
||||
<div className="grid grid-cols-2 lg:grid-cols-4 2xl:grid-cols-6 grid-flow-dense w-full">
|
||||
{images.map((img, index) => {
|
||||
@@ -24,7 +24,7 @@ export default function PhotoGallery({ images }: { images: GalleryImage[] }) {
|
||||
return (
|
||||
<div
|
||||
key={index}
|
||||
className={`relative bg-[#0d1117] overflow-hidden group cursor-pointer border-[0.5px] border-white/5 ${isHorizontal ? 'col-span-2' : 'col-span-1'}`}
|
||||
className={`relative bg-slate-200 dark:bg-[#0d1117] overflow-hidden group cursor-pointer transition-colors duration-300 ${isHorizontal ? 'col-span-2' : 'col-span-1'}`}
|
||||
>
|
||||
<Item
|
||||
original={img.src}
|
||||
@@ -39,8 +39,11 @@ export default function PhotoGallery({ images }: { images: GalleryImage[] }) {
|
||||
onClick={open}
|
||||
className="w-full h-full relative block min-h-75"
|
||||
>
|
||||
<div className="absolute inset-0 border-8 border-[#0d1117]/50 transition-all duration-300 z-10 pointer-events-none"></div>
|
||||
<div className="absolute inset-4 border-2 border-white/10 transition-all duration-500 z-10 pointer-events-none group-hover:scale-95 group-hover:border-[#84c0a0]/60 [clip-path:polygon(0_calc(100%-1rem),0_100%,1rem_100%,1rem_0,0_0,0_1rem,100%_1rem,100%_0,calc(100%-1rem)_0,calc(100%-1rem)_100%,100%_100%,100%_calc(100%-1rem))]"></div>
|
||||
{/* Outer Frame - Light border in light mode, Dark in dark mode */}
|
||||
<div className="absolute inset-0 border-8 border-slate-100/10 dark:border-[#0d1117]/40 transition-colors duration-300 z-10 pointer-events-none"></div>
|
||||
|
||||
{/* Inner Hover Frame */}
|
||||
<div className="absolute inset-4 border-2 border-slate-300/50 dark:border-white/10 transition-all duration-500 z-10 pointer-events-none group-hover:scale-95 group-hover:border-[#84c0a0]/80 dark:group-hover:border-[#84c0a0]/60 [clip-path:polygon(0_calc(100%-1rem),0_100%,1rem_100%,1rem_0,0_0,0_1rem,100%_1rem,100%_0,calc(100%-1rem)_0,calc(100%-1rem)_100%,100%_100%,100%_calc(100%-1rem))]"></div>
|
||||
|
||||
<Image
|
||||
src={img.src}
|
||||
@@ -49,7 +52,7 @@ export default function PhotoGallery({ images }: { images: GalleryImage[] }) {
|
||||
height={isHorizontal ? 800 : 800}
|
||||
quality={90}
|
||||
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
|
||||
className="w-full h-full object-cover block opacity-80 transition-all duration-700 group-hover:scale-110 group-hover:opacity-100"
|
||||
className="w-full h-full object-cover block transition-all duration-700 group-hover:scale-110 group-hover:opacity-100 dark:group-hover:opacity-100"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
// app/components/ThemeProvider.tsx
|
||||
|
||||
'use client';
|
||||
|
||||
import { ThemeProvider as NextThemesProvider } from 'next-themes';
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
export function ThemeProvider({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<NextThemesProvider attribute="class" defaultTheme="system" enableSystem>
|
||||
{children}
|
||||
</NextThemesProvider>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user