From 6717cbb30e0b712065bc7173afcd613103de7abe Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 22 Aug 2026 07:33:36 +0000
Subject: [PATCH] Add dark mode, theme, and UI polish across the site
Co-authored-by: 20kaushik02 <59662438+20kaushik02@users.noreply.github.com>
---
public/index.html | 12 ++++++++--
src/App.js | 45 ++++++++++++++++++++++++++++++++++----
src/components/Landing.js | 8 +++----
src/components/Menu.js | 18 ++++++++++++---
src/components/Projects.js | 22 ++++++++++---------
src/theme.js | 43 ++++++++++++++++++++++++++++++++++++
6 files changed, 125 insertions(+), 23 deletions(-)
create mode 100644 src/theme.js
diff --git a/public/index.html b/public/index.html
index aa8b7d7..9f7b02f 100644
--- a/public/index.html
+++ b/public/index.html
@@ -3,8 +3,17 @@
-
+
+
+
+
+
+
+
+
+
+
-
Kaushik's Website
diff --git a/src/App.js b/src/App.js
index 97ab7b6..6c92bfa 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,10 +1,28 @@
-import { createContext, useEffect, useState } from 'react';
+import { createContext, useEffect, useMemo, useState } from 'react';
+import { ThemeProvider } from '@mui/material/styles';
+import CssBaseline from '@mui/material/CssBaseline';
import Menu from './components/Menu';
+import { getAppTheme } from './theme';
export const WidthContext = createContext();
+export const ColorModeContext = createContext({ mode: 'light', toggleMode: () => { } });
+
+const THEME_STORAGE_KEY = 'colorMode';
+
+function getInitialMode() {
+ const stored = window.localStorage.getItem(THEME_STORAGE_KEY);
+ if (stored === 'light' || stored === 'dark') {
+ return stored;
+ }
+ return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
+ ? 'dark'
+ : 'light';
+}
function App() {
const [width, setWidth] = useState(0);
+ const [mode, setMode] = useState(getInitialMode);
+
// Get window dimensions on resize
useEffect(() => {
window.addEventListener("resize", updateWindowDimensions);
@@ -20,10 +38,29 @@ function App() {
useEffect(() => {
updateWindowDimensions();
}, []);
+
+ const colorMode = useMemo(() => ({
+ mode,
+ toggleMode: () => {
+ setMode((prevMode) => {
+ const nextMode = prevMode === 'light' ? 'dark' : 'light';
+ window.localStorage.setItem(THEME_STORAGE_KEY, nextMode);
+ return nextMode;
+ });
+ },
+ }), [mode]);
+
+ const theme = useMemo(() => getAppTheme(mode), [mode]);
+
return (
-
-
-
+
+
+
+
+
+
+
+
);
}
diff --git a/src/components/Landing.js b/src/components/Landing.js
index 90d4a6f..b61b67e 100644
--- a/src/components/Landing.js
+++ b/src/components/Landing.js
@@ -16,14 +16,14 @@ const socialsData = [
const Landing = () => {
return (
<>
+
+ Hi, I'm Kaushik 👋
+
{/* summary */}
+ primary={"Welcome to my (messy) homepage. I like data! My passions lie in data engineering/analytics, distributed technologies, networks and security, web development, machine learning... you get the picture."} />
{/* current endeavor */}
diff --git a/src/components/Menu.js b/src/components/Menu.js
index 1184189..8c18545 100644
--- a/src/components/Menu.js
+++ b/src/components/Menu.js
@@ -3,7 +3,6 @@ import * as React from 'react';
import AppBar from '@mui/material/AppBar';
import Avatar from '@mui/material/Avatar';
import Box from '@mui/material/Box';
-import CssBaseline from '@mui/material/CssBaseline';
import Divider from '@mui/material/Divider';
import Drawer from '@mui/material/Drawer';
import IconButton from '@mui/material/IconButton';
@@ -16,6 +15,7 @@ import MenuIcon from '@mui/icons-material/Menu';
import Toolbar from '@mui/material/Toolbar';
import Typography from '@mui/material/Typography';
import Link from '@mui/material/Link';
+import Tooltip from '@mui/material/Tooltip';
import LandingIcon from '@mui/icons-material/Home';
import ProjectsIcon from '@mui/icons-material/AccountTree';
@@ -23,6 +23,8 @@ import CareerIcon from '@mui/icons-material/Work';
import InterestsIcon from '@mui/icons-material/Headphones';
import ArticleIcon from '@mui/icons-material/Article';
import BlogIcon from '@mui/icons-material/RateReview';
+import LightModeIcon from '@mui/icons-material/LightMode';
+import DarkModeIcon from '@mui/icons-material/DarkMode';
import Landing from './Landing';
// import LoremIpsum from './LoremIpsum';
@@ -30,6 +32,7 @@ import Projects from './Projects';
import Career from './Career';
import { handleLinkClick } from '../utils/linkClick';
import UnderConstruction from './UnderConstruction';
+import { ColorModeContext } from '../App';
const drawerWidth = 240;
@@ -64,6 +67,11 @@ function Menu(props) {
const [mobileOpen, setMobileOpen] = React.useState(false);
const [isClosing, setIsClosing] = React.useState(false);
const [activeSection, setActiveSection] = React.useState(menuSections[0]);
+ const { mode, toggleMode } = React.useContext(ColorModeContext);
+
+ React.useEffect(() => {
+ document.title = `Kaushik | ${activeSection.display_name}`;
+ }, [activeSection]);
const handleDrawerClose = () => {
setIsClosing(true);
@@ -130,7 +138,6 @@ function Menu(props) {
return (
-
-
+
{activeSection.appbar_text}
+
+
+ {mode === 'dark' ? : }
+
+
{
const width = useContext(WidthContext);
const ProjectCard = ({ project }) => {
return (
-
-
+
+
{
alt={project.name}
onClick={() => handleLinkClick(process.env.PUBLIC_URL + "Projects/" + project.img)}
/>
-
-
+
+
{project.name}
@@ -102,11 +104,11 @@ const Projects = () => {
)}
-
+
{project.tools.map((tool, index) =>
-
+
)}
-
+
@@ -132,7 +134,7 @@ const Projects = () => {
pagination={{
dynamicBullets: true,
}}
- navigation={false}
+ navigation={width >= 480}
speed={400}
spaceBetween={10}
slidesPerView={width >= 480 ? 2.6 : 1.1}
@@ -142,7 +144,7 @@ const Projects = () => {
{projectsData.map((project) =>
diff --git a/src/theme.js b/src/theme.js
new file mode 100644
index 0000000..55cbc92
--- /dev/null
+++ b/src/theme.js
@@ -0,0 +1,43 @@
+import { createTheme } from '@mui/material/styles';
+
+// Central place to tweak the site's look and feel.
+export const getAppTheme = (mode) => createTheme({
+ palette: {
+ mode,
+ primary: {
+ main: mode === 'dark' ? '#7ad0c9' : '#00695f',
+ },
+ secondary: {
+ main: '#ef6c00',
+ },
+ background: mode === 'dark'
+ ? { default: '#121212', paper: '#1c1c1c' }
+ : { default: '#f7f7f5', paper: '#ffffff' },
+ },
+ shape: {
+ borderRadius: 10,
+ },
+ typography: {
+ fontFamily: [
+ '-apple-system', 'BlinkMacSystemFont', '"Segoe UI"', 'Roboto', 'Oxygen',
+ 'Ubuntu', 'Cantarell', '"Fira Sans"', '"Droid Sans"', '"Helvetica Neue"',
+ 'sans-serif',
+ ].join(','),
+ h5: {
+ fontWeight: 600,
+ },
+ },
+ components: {
+ MuiCard: {
+ styleOverrides: {
+ root: {
+ transition: 'transform 200ms ease, box-shadow 200ms ease',
+ '&:hover': {
+ transform: 'translateY(-4px)',
+ boxShadow: '0 8px 20px rgba(0,0,0,0.15)',
+ },
+ },
+ },
+ },
+ },
+});