feat(cv): add light/dark theme toggle

Introduce CSS custom properties for all colors and a .light-theme class
on <html> that overrides them. Toggle button (sun/moon) next to the
language switcher in the sidebar header. White text on accent backgrounds
(titles, captcha prompt) in light mode via --on-accent-color variable.

Made-with: Cursor
master
sii42400 2026-04-17 13:18:31 +02:00
parent 319a6a705c
commit 0c8d7642d9
2 changed files with 75 additions and 29 deletions

View File

@ -521,6 +521,12 @@ const IndexPage = () => {
const [content_swapper, set_content_swap] = React.useState(pol_); const [content_swapper, set_content_swap] = React.useState(pol_);
const [content, set_content] = React.useState(content_en); const [content, set_content] = React.useState(content_en);
const [isDark, setIsDark] = React.useState(true);
const toggleTheme = () => {
setIsDark(!isDark);
document.documentElement.classList.toggle("light-theme");
};
const swap_content = (event) => { const swap_content = (event) => {
event.preventDefault() event.preventDefault()
@ -545,6 +551,9 @@ const IndexPage = () => {
{content_swapper} {content_swapper}
</div> </div>
</div> </div>
<div className="theme_toggle" onClick={toggleTheme}>
{isDark ? "☀️" : "🌙"}
</div>
</div> </div>
<SegmentGeneral <SegmentGeneral
key="general_sidebar" key="general_sidebar"

View File

@ -15,9 +15,36 @@ $regular_image_font_size: 10.5pt;
$foot_font_size: 9.8pt; $foot_font_size: 9.8pt;
:root {
--bg-color: #{$background_color};
--text-color: #{$color};
--text-visited: #{$color_visited};
--text-hover: #{$color_hover};
--text-active: #{$color_active};
--div-bg-color: #{$div_background_color};
--sidebar-bg: #1e1e1e;
--sidebar-border: rgba(166, 166, 166, 0.1);
--segment-bg: #{$background_color};
--on-accent-color: #{$color};
}
.light-theme {
--bg-color: #f5f5f5;
--text-color: #333333;
--text-visited: #555555;
--text-hover: #111111;
--text-active: #333333;
--div-bg-color: #1a56db;
--sidebar-bg: #e8e8e8;
--sidebar-border: rgba(0, 0, 0, 0.1);
--segment-bg: #f5f5f5;
--on-accent-color: #ffffff;
}
body { body {
background-color: $background_color; background-color: var(--bg-color);
color: $color; color: var(--text-color);
transition: background-color 0.3s, color 0.3s;
} }
@font-face { @font-face {
@ -43,11 +70,12 @@ body {
bottom: 0; bottom: 0;
width: 280px; width: 280px;
overflow-y: auto; overflow-y: auto;
background-color: darken($background_color, 3%); background-color: var(--sidebar-bg);
padding: 20px 15px; padding: 20px 15px;
box-sizing: border-box; box-sizing: border-box;
z-index: 10; z-index: 10;
border-right: 1px solid rgba($color, 0.1); border-right: 1px solid var(--sidebar-border);
transition: background-color 0.3s, border-color 0.3s;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -75,7 +103,7 @@ body {
text-align: left; text-align: left;
font-family: $title_font_family; font-family: $title_font_family;
font-size: 18pt; font-size: 18pt;
color: $color; color: var(--text-color);
} }
.language_bar { .language_bar {
@ -84,6 +112,13 @@ body {
cursor: pointer; cursor: pointer;
} }
.theme_toggle {
font-size: 16pt;
cursor: pointer;
margin-left: 10px;
user-select: none;
}
.segment_general { .segment_general {
float: none; float: none;
margin-top: 0; margin-top: 0;
@ -162,8 +197,8 @@ body {
font-size: $regular_image_font_size; font-size: $regular_image_font_size;
font-family: $regular_font_family; font-family: $regular_font_family;
font-weight: bold; font-weight: bold;
background-color: $div_background_color; background-color: var(--div-bg-color);
color: $color; color: var(--text-color);
.segment_image_item { .segment_image_item {
margin-top: 5px; margin-top: 5px;
@ -179,19 +214,19 @@ body {
box-sizing: border-box; box-sizing: border-box;
a:link { a:link {
color: $background_color; color: var(--bg-color);
} }
a:visited { a:visited {
color: $color_visited; color: var(--text-visited);
} }
a:hover { a:hover {
color: $color_hover; color: var(--text-hover);
} }
a:active { a:active {
color: $color_active; color: var(--text-active);
} }
ul { ul {
@ -213,9 +248,9 @@ body {
float: left; float: left;
width: 210px; width: 210px;
height:250px; height:250px;
color: $color; color: var(--text-color);
font-weight: bold; font-weight: bold;
background-color: $div_background_color; background-color: var(--div-bg-color);
} }
.cover { .cover {
@ -232,11 +267,11 @@ body {
padding: 15px; padding: 15px;
width: 180px; width: 180px;
height:220px; height:220px;
color: $color; color: var(--text-color);
font-size: $regular_image_font_size; font-size: $regular_image_font_size;
font-family: $regular_font_family; font-family: $regular_font_family;
font-weight: bold; font-weight: bold;
background-color: $div_background_color; background-color: var(--div-bg-color);
.segment_image_item { .segment_image_item {
margin-top: 5px; margin-top: 5px;
@ -265,11 +300,11 @@ body {
width: 250px; width: 250px;
padding-top: 12px; padding-top: 12px;
height: 45px; height: 45px;
color: $color; color: var(--on-accent-color);
font-family: $title_font_family; font-family: $title_font_family;
font-size: $title_font_size; font-size: $title_font_size;
text-align: center; text-align: center;
background-color: $div_background_color; background-color: var(--div-bg-color);
} }
.segment_content_normal { .segment_content_normal {
@ -288,7 +323,7 @@ body {
ul li::before { ul li::before {
content: ">> "; content: ">> ";
color: $div_background_color; color: var(--div-bg-color);
font-weight: bold; font-weight: bold;
display: inline-block; display: inline-block;
width: 2em; width: 2em;
@ -323,7 +358,7 @@ body {
ul li::before { ul li::before {
content: "+ >"; content: "+ >";
color: inherit; color: inherit;
background-color: $background_color; background-color: var(--bg-color);
font-weight: bold; font-weight: bold;
display: inline-block; display: inline-block;
width: 2em; width: 2em;
@ -359,7 +394,8 @@ body {
font-family: $regular_font_family; font-family: $regular_font_family;
font-size: 10pt; font-size: 10pt;
font-style: italic; font-style: italic;
color: darken($color, 15%); color: var(--text-color);
opacity: 0.75;
text-align: justify; text-align: justify;
margin: 4px 0 10px 18px; margin: 4px 0 10px 18px;
} }
@ -391,7 +427,7 @@ body {
float: right; float: right;
.captcha-form { .captcha-form {
background-color: $div_background_color; background-color: var(--div-bg-color);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
@ -404,6 +440,7 @@ body {
text-align: center; text-align: center;
margin-top: 15px; margin-top: 15px;
margin-bottom: 15px; margin-bottom: 15px;
color: var(--on-accent-color);
} }
form { form {
@ -415,7 +452,7 @@ body {
} }
a { a {
color: $color; color: var(--text-color);
cursor: pointer; cursor: pointer;
padding-top: 20px; padding-top: 20px;
padding-bottom: 5px; padding-bottom: 5px;
@ -427,9 +464,9 @@ body {
width: 100%; width: 100%;
padding: 8px; padding: 8px;
margin-bottom: 10px; margin-bottom: 10px;
border: 1px solid $color; border: 1px solid var(--text-color);
background-color: $background_color; background-color: var(--bg-color);
color: $color; color: var(--text-color);
font-size: 9pt; font-size: 9pt;
box-sizing: border-box; box-sizing: border-box;
} }
@ -437,15 +474,15 @@ body {
.captcha-button { .captcha-button {
width: 100%; width: 100%;
padding: 8px; padding: 8px;
background-color: $background_color; background-color: var(--bg-color);
color: $color; color: var(--text-color);
border: 1px solid $color; border: 1px solid var(--text-color);
box-sizing: border-box; box-sizing: border-box;
cursor: pointer; cursor: pointer;
font-size: 9pt; font-size: 9pt;
&:hover { &:hover {
background-color: darken($background_color, 5%); opacity: 0.85;
} }
} }