Add pseudo-dark mode while maintaining XP aesthetic
- Create CSS variables for theme customization - Define light and dark XP color schemes - Dark mode uses darker backgrounds, lighter text - Maintain classic XP beveled borders and shadows - Add moon/sun toggle button in title bar - Implement theme switching with localStorage - Support system color scheme preference - Smooth transitions between themes The dark mode keeps the Windows XP look with: - Dark teal/navy desktop background - Dark gray window and button faces - Lighter text colors - Darker gradient title bars - All original XP styling preserved 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
60e2c49811
commit
c4e9e952a5
@ -1,4 +1,45 @@
|
||||
(() => {
|
||||
// Theme management
|
||||
const themeToggle = document.getElementById("themeToggle");
|
||||
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)");
|
||||
|
||||
function getTheme() {
|
||||
const saved = localStorage.getItem("xp-theme");
|
||||
if (saved) return saved;
|
||||
return prefersDark.matches ? "dark" : "light";
|
||||
}
|
||||
|
||||
function setTheme(theme) {
|
||||
if (theme === "dark") {
|
||||
document.documentElement.setAttribute("data-theme", "dark");
|
||||
if (themeToggle) themeToggle.textContent = "☀️";
|
||||
} else {
|
||||
document.documentElement.removeAttribute("data-theme");
|
||||
if (themeToggle) themeToggle.textContent = "🌙";
|
||||
}
|
||||
localStorage.setItem("xp-theme", theme);
|
||||
}
|
||||
|
||||
function toggleTheme() {
|
||||
const current = document.documentElement.getAttribute("data-theme") === "dark" ? "dark" : "light";
|
||||
setTheme(current === "dark" ? "light" : "dark");
|
||||
}
|
||||
|
||||
// Initialize theme
|
||||
setTheme(getTheme());
|
||||
|
||||
// Listen for theme toggle
|
||||
if (themeToggle) {
|
||||
themeToggle.addEventListener("click", toggleTheme);
|
||||
}
|
||||
|
||||
// Listen for system theme changes
|
||||
prefersDark.addEventListener("change", (e) => {
|
||||
if (!localStorage.getItem("xp-theme")) {
|
||||
setTheme(e.matches ? "dark" : "light");
|
||||
}
|
||||
});
|
||||
|
||||
let qs = new URLSearchParams(window.location.search);
|
||||
const qInput = document.getElementById("q");
|
||||
const channelDropdown = document.getElementById("channelDropdown");
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
<div class="title-bar">
|
||||
<div class="title-bar-text">This Little Corner — Elastic Search</div>
|
||||
<div class="title-bar-controls">
|
||||
<button id="themeToggle" aria-label="Toggle theme" title="Toggle dark mode" style="margin-right: 4px; min-width: 24px; font-size: 14px;">🌙</button>
|
||||
<button aria-label="Minimize"></button>
|
||||
<button aria-label="Maximize"></button>
|
||||
<button aria-label="Close"></button>
|
||||
|
||||
156
static/style.css
156
static/style.css
@ -1,5 +1,101 @@
|
||||
/* Custom styles for XP.css integration */
|
||||
|
||||
/* Theme variables - Light mode (default) */
|
||||
:root {
|
||||
--xp-bg-desktop: teal;
|
||||
--xp-bg-window: #ece9d8;
|
||||
--xp-bg-white: white;
|
||||
--xp-text-primary: black;
|
||||
--xp-text-secondary: #666;
|
||||
--xp-border-light: white;
|
||||
--xp-border-dark: #0a0a0a;
|
||||
--xp-border-shadow: grey;
|
||||
--xp-border-highlight: #dfdfdf;
|
||||
--xp-button-face: #ece9d8;
|
||||
--xp-titlebar-bg: linear-gradient(to right, #0054e3, #1591e6);
|
||||
--xp-titlebar-text: white;
|
||||
--xp-selection-bg: #0a246a;
|
||||
--xp-selection-text: white;
|
||||
--xp-field-bg: white;
|
||||
--xp-field-border: #7f9db9;
|
||||
}
|
||||
|
||||
/* Dark mode theme */
|
||||
[data-theme="dark"] {
|
||||
--xp-bg-desktop: #1a1a2e;
|
||||
--xp-bg-window: #2d2d44;
|
||||
--xp-bg-white: #1e1e2e;
|
||||
--xp-text-primary: #e0e0e0;
|
||||
--xp-text-secondary: #a0a0a0;
|
||||
--xp-border-light: #4a4a5e;
|
||||
--xp-border-dark: #0a0a0a;
|
||||
--xp-border-shadow: #1a1a1a;
|
||||
--xp-border-highlight: #3a3a4e;
|
||||
--xp-button-face: #2d2d44;
|
||||
--xp-titlebar-bg: linear-gradient(to right, #1a3a5e, #2a4a6e);
|
||||
--xp-titlebar-text: #e0e0e0;
|
||||
--xp-selection-bg: #2a4a7e;
|
||||
--xp-selection-text: white;
|
||||
--xp-field-bg: #1e1e2e;
|
||||
--xp-field-border: #4a5a6e;
|
||||
}
|
||||
|
||||
/* Apply theme variables */
|
||||
body {
|
||||
background: var(--xp-bg-desktop);
|
||||
color: var(--xp-text-primary);
|
||||
}
|
||||
|
||||
.window {
|
||||
background: var(--xp-bg-window);
|
||||
}
|
||||
|
||||
.window-body {
|
||||
background: var(--xp-bg-window);
|
||||
color: var(--xp-text-primary);
|
||||
}
|
||||
|
||||
.title-bar {
|
||||
background: var(--xp-titlebar-bg);
|
||||
color: var(--xp-titlebar-text);
|
||||
}
|
||||
|
||||
button {
|
||||
background: var(--xp-button-face);
|
||||
color: var(--xp-text-primary);
|
||||
box-shadow: inset -1px -1px var(--xp-border-dark),
|
||||
inset 1px 1px var(--xp-border-light),
|
||||
inset -2px -2px var(--xp-border-shadow),
|
||||
inset 2px 2px var(--xp-border-highlight);
|
||||
}
|
||||
|
||||
button:active {
|
||||
box-shadow: inset -1px -1px var(--xp-border-light),
|
||||
inset 1px 1px var(--xp-border-dark),
|
||||
inset -2px -2px var(--xp-border-highlight),
|
||||
inset 2px 2px var(--xp-border-shadow);
|
||||
}
|
||||
|
||||
input[type="text"],
|
||||
textarea,
|
||||
select {
|
||||
background: var(--xp-field-bg);
|
||||
color: var(--xp-text-primary);
|
||||
border-color: var(--xp-field-border);
|
||||
}
|
||||
|
||||
fieldset {
|
||||
border-color: var(--xp-border-shadow) var(--xp-border-light) var(--xp-border-light) var(--xp-border-shadow);
|
||||
}
|
||||
|
||||
.status-bar {
|
||||
background: var(--xp-bg-window);
|
||||
}
|
||||
|
||||
.status-bar-field {
|
||||
color: var(--xp-text-primary);
|
||||
}
|
||||
|
||||
/* Fix blurry text rendering - override XP.css font smoothing */
|
||||
.window,
|
||||
.window *,
|
||||
@ -33,10 +129,18 @@ label {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
body {
|
||||
background: teal;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
/* Smooth theme transitions */
|
||||
body,
|
||||
.window,
|
||||
.window-body,
|
||||
button,
|
||||
input,
|
||||
select,
|
||||
textarea,
|
||||
.status-bar,
|
||||
.channel-dropdown summary,
|
||||
.channel-options {
|
||||
transition: background 0.3s ease, color 0.3s ease, border-color 0.3s ease;
|
||||
}
|
||||
|
||||
/* Channel dropdown custom styling */
|
||||
@ -49,9 +153,10 @@ body {
|
||||
list-style: none;
|
||||
cursor: pointer;
|
||||
padding: 3px 4px;
|
||||
background: ButtonFace;
|
||||
background: var(--xp-button-face);
|
||||
color: var(--xp-text-primary);
|
||||
border: 1px solid;
|
||||
border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;
|
||||
border-color: var(--xp-border-light) var(--xp-border-shadow) var(--xp-border-shadow) var(--xp-border-light);
|
||||
min-width: 180px;
|
||||
text-align: left;
|
||||
}
|
||||
@ -74,12 +179,13 @@ body {
|
||||
position: absolute;
|
||||
margin-top: 2px;
|
||||
padding: 4px;
|
||||
background: ButtonFace;
|
||||
background: var(--xp-bg-window);
|
||||
color: var(--xp-text-primary);
|
||||
border: 1px solid;
|
||||
border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;
|
||||
border-color: var(--xp-border-light) var(--xp-border-shadow) var(--xp-border-shadow) var(--xp-border-light);
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.2);
|
||||
box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.3);
|
||||
z-index: 100;
|
||||
min-width: 220px;
|
||||
}
|
||||
@ -116,7 +222,7 @@ body {
|
||||
|
||||
/* Results styling */
|
||||
#results .item {
|
||||
border-bottom: 1px solid ButtonShadow;
|
||||
border-bottom: 1px solid var(--xp-border-shadow);
|
||||
padding: 12px 0;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
@ -144,9 +250,10 @@ body {
|
||||
|
||||
/* Transcript and highlights */
|
||||
.transcript {
|
||||
background: Window;
|
||||
background: var(--xp-field-bg);
|
||||
color: var(--xp-text-primary);
|
||||
border: 1px solid;
|
||||
border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;
|
||||
border-color: var(--xp-border-shadow) var(--xp-border-light) var(--xp-border-light) var(--xp-border-shadow);
|
||||
padding: 8px;
|
||||
margin-top: 6px;
|
||||
max-height: 200px;
|
||||
@ -169,9 +276,9 @@ body {
|
||||
}
|
||||
|
||||
.highlight-row:hover {
|
||||
background: Highlight;
|
||||
color: HighlightText;
|
||||
border: 1px dotted WindowText;
|
||||
background: var(--xp-selection-bg);
|
||||
color: var(--xp-selection-text);
|
||||
border: 1px dotted var(--xp-text-primary);
|
||||
}
|
||||
|
||||
mark {
|
||||
@ -187,9 +294,10 @@ mark {
|
||||
.full-transcript {
|
||||
margin-top: 12px;
|
||||
padding: 8px;
|
||||
background: Window;
|
||||
background: var(--xp-field-bg);
|
||||
color: var(--xp-text-primary);
|
||||
border: 2px solid;
|
||||
border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;
|
||||
border-color: var(--xp-border-shadow) var(--xp-border-light) var(--xp-border-light) var(--xp-border-shadow);
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
font-size: 11px;
|
||||
@ -198,7 +306,7 @@ mark {
|
||||
.transcript-segment {
|
||||
margin-bottom: 10px;
|
||||
padding-bottom: 6px;
|
||||
border-bottom: 1px solid ButtonShadow;
|
||||
border-bottom: 1px solid var(--xp-border-shadow);
|
||||
}
|
||||
|
||||
.transcript-segment:last-child {
|
||||
@ -241,7 +349,7 @@ mark {
|
||||
}
|
||||
|
||||
.transcript-text {
|
||||
color: WindowText;
|
||||
color: var(--xp-text-primary);
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
@ -251,8 +359,8 @@ mark {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background: ActiveCaption;
|
||||
color: CaptionText;
|
||||
background: var(--xp-titlebar-bg);
|
||||
color: var(--xp-titlebar-text);
|
||||
padding: 2px 4px;
|
||||
}
|
||||
|
||||
@ -264,8 +372,8 @@ mark {
|
||||
}
|
||||
|
||||
.transcript-close:hover {
|
||||
background: Highlight;
|
||||
color: HighlightText;
|
||||
background: var(--xp-selection-bg);
|
||||
color: var(--xp-selection-text);
|
||||
}
|
||||
|
||||
/* Chart styling */
|
||||
@ -283,7 +391,7 @@ mark {
|
||||
}
|
||||
|
||||
#frequencyChart .axis text {
|
||||
fill: WindowText;
|
||||
fill: var(--xp-text-primary);
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user