diff --git a/src/App.jsx b/src/App.jsx
index 7473e26..2f5b59c 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -8,12 +8,14 @@ import {
Heading,
HoverCard,
HStack,
+ IconButton,
Image,
Input,
SimpleGrid,
Stack,
Text,
Textarea,
+ Theme,
} from "@chakra-ui/react";
import {
Activity,
@@ -26,12 +28,14 @@ import {
Linkedin,
Mail,
Menu,
+ Moon,
RadioTower,
ShieldCheck,
+ Sun,
TerminalSquare,
X,
} from "lucide-react";
-import { useMemo, useState } from "react";
+import { useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import resumePdf from "../assets/curriculum.pdf";
@@ -42,6 +46,50 @@ const navItems = ["about", "experience", "skills", "projects", "contact"];
const projectIcons = [ShieldCheck, Cloud, TerminalSquare];
const experienceIcons = [Briefcase, Headphones, Activity];
+function createAppearancePalette(basePalette, isDark) {
+ if (!isDark) {
+ return {
+ ...basePalette,
+ appBg: "#f8fafc",
+ bodyText: "#43516a",
+ cardShadow: "0 16px 40px rgba(31, 41, 55, 0.08)",
+ elevatedBg: "#ffffff",
+ footerText: "#64748b",
+ headerBg: "rgba(255, 255, 255, 0.86)",
+ hoverCardBg: "#ffffff",
+ iconPanelShadow: "0 10px 22px rgba(31, 41, 55, 0.12)",
+ inputBg: "rgba(255, 255, 255, 0.9)",
+ locationText: "#64748b",
+ sectionNote: "#64748b",
+ };
+ }
+
+ return {
+ ...basePalette,
+ appBg: "#08111e",
+ bodyText: "#b6c3d9",
+ cardGradient:
+ "linear-gradient(145deg, rgba(7, 18, 33, 0.94), rgba(13, 25, 43, 0.96) 46%, rgba(255, 255, 255, 0.04))",
+ cardShadow:
+ "0 18px 46px rgba(2, 6, 23, 0.52), 0 10px 26px rgba(15, 23, 42, 0.36)",
+ elevatedBg: "rgba(10, 19, 34, 0.92)",
+ footerText: "#8ea2c5",
+ headerBg: "rgba(6, 14, 26, 0.82)",
+ heroGradient:
+ "linear-gradient(135deg, rgba(7, 18, 33, 0.98), rgba(17, 31, 53, 0.96) 52%, rgba(255, 255, 255, 0.04))",
+ hoverCardBg: "rgba(8, 18, 32, 0.98)",
+ iconPanelShadow:
+ "0 12px 28px rgba(2, 6, 23, 0.44), 0 0 0 1px rgba(255, 255, 255, 0.04)",
+ inputBg: "rgba(7, 16, 30, 0.9)",
+ locationText: "#8ea2c5",
+ muted: "rgba(255, 255, 255, 0.08)",
+ sectionNote: "#8ea2c5",
+ surface: "#0b1627",
+ text: "#edf4ff",
+ border: "rgba(152, 177, 214, 0.22)",
+ };
+}
+
function SectionHeading({ eyebrow, title, palette }) {
return (
@@ -67,10 +115,10 @@ function ProjectActionHoverCard({ children, label, note, palette, url }) {
{children}
{note ? (
-
+
{note}
) : null}
@@ -98,8 +146,19 @@ function ProjectActionHoverCard({ children, label, note, palette, url }) {
function App() {
const { i18n, t } = useTranslation();
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
+ const [appearance, setAppearance] = useState(() => {
+ if (typeof window === "undefined") return "light";
+
+ const storedAppearance = window.localStorage.getItem("portfolioAppearance");
+ if (storedAppearance === "light" || storedAppearance === "dark") return storedAppearance;
+
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
+ });
const currentLanguage = i18n.language?.slice(0, 2) || "en";
- const palette = languageThemes[currentLanguage] || languageThemes.en;
+ const palette = createAppearancePalette(
+ languageThemes[currentLanguage] || languageThemes.en,
+ appearance === "dark",
+ );
const nav = t("nav", { returnObjects: true });
const skillGroups = t("skills.groups", { returnObjects: true });
const experienceItems = t("experience.items", { returnObjects: true });
@@ -134,6 +193,22 @@ function App() {
transform: "translateY(0)",
},
};
+ const formFieldStyles = {
+ bg: palette.inputBg,
+ borderColor: palette.border,
+ color: palette.text,
+ _placeholder: {
+ color: palette.footerText,
+ },
+ _focusVisible: {
+ borderColor: palette.primary,
+ boxShadow: `0 0 0 1px ${palette.primary}`,
+ },
+ };
+
+ useEffect(() => {
+ window.localStorage.setItem("portfolioAppearance", appearance);
+ }, [appearance]);
const changeLanguage = (languageCode) => {
window.localStorage.setItem("portfolioLanguage", languageCode);
@@ -141,8 +216,15 @@ function App() {
setIsMobileMenuOpen(false);
};
+ const toggleAppearance = () => {
+ setAppearance((currentAppearance) =>
+ currentAppearance === "dark" ? "light" : "dark",
+ );
+ };
+
return (
-
+
+
+
+ {appearance === "dark" ? : }
+
-
+
{t("hero.body")}
@@ -317,7 +413,7 @@ function App() {
>
-
+
Krakow, Poland
@@ -332,7 +428,7 @@ function App() {
-
+
{t("about.body")}
@@ -341,7 +437,7 @@ function App() {
bg={palette.cardGradient}
border="1px solid"
borderColor={palette.border}
- boxShadow="0 16px 40px rgba(31, 41, 55, 0.08)"
+ boxShadow={palette.cardShadow}
key={highlight}
p="5"
rounded="xl"
@@ -369,7 +465,7 @@ function App() {
p={{ base: "6", md: "8" }}
rounded="2xl"
>
-
+
{t("experience.body")}
@@ -378,10 +474,10 @@ function App() {
const ExperienceIcon = experienceIcons[index] || Briefcase;
return (
{item.title}
-
+
{item.description}
@@ -422,7 +518,7 @@ function App() {
bg={palette.cardGradient}
border="1px solid"
borderColor={palette.border}
- boxShadow="0 16px 40px rgba(31, 41, 55, 0.08)"
+ boxShadow={palette.cardShadow}
key={group.title}
p="6"
rounded="2xl"
@@ -447,7 +543,7 @@ function App() {
-
+
{t("projects.note")}
@@ -461,7 +557,7 @@ function App() {
bg={palette.cardGradient}
border="1px solid"
borderColor={palette.border}
- boxShadow="0 16px 40px rgba(31, 41, 55, 0.08)"
+ boxShadow={palette.cardShadow}
gap="5"
key={project.title}
p="6"
@@ -477,7 +573,7 @@ function App() {
{project.focus}
-
+
{project.description}
@@ -541,7 +637,7 @@ function App() {
>
-
+
{t("contact.body")}
@@ -561,10 +657,10 @@ function App() {
-
-
-
-
+
+
+
+
@@ -579,12 +675,13 @@ function App() {
-
+
{t("footer")}
-
+
+
);
}
diff --git a/src/i18n/resources.js b/src/i18n/resources.js
index 6b4c1e3..ee898c5 100644
--- a/src/i18n/resources.js
+++ b/src/i18n/resources.js
@@ -18,7 +18,7 @@ export const resources = {
subtitle:
"Software Engineer focused on Kubernetes, cloud infrastructure, security, and automation.",
body: "I build and operate reliable cloud platforms with Terraform, Kubernetes, Go, Python, and a security-first mindset shaped by enterprise support and compliance experience.",
- resume: "Resume",
+ resume: "CV",
github: "GitHub",
linkedin: "LinkedIn",
},
@@ -180,7 +180,7 @@ export const resources = {
subtitle:
"Software Engineer з фокусом на Kubernetes, хмарну інфраструктуру, безпеку та автоматизацію.",
body: "Я створюю та підтримую надійні cloud-платформи з Terraform, Kubernetes, Go і Python, використовуючи security-first підхід, сформований досвідом enterprise support та compliance.",
- resume: "Резюме",
+ resume: "CV",
github: "GitHub",
linkedin: "LinkedIn",
},