Skip to content

Commit 41c1f09

Browse files
fix(ui): early theme apply and safer search/sidebar click handlers
1 parent 46452dd commit 41c1f09

4 files changed

Lines changed: 31 additions & 3 deletions

File tree

static/css/style.css

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@
8282
color-scheme: light;
8383
}
8484

85+
/* Theme toggle icons (set before JS module loads; applyTheme keeps them in sync) */
86+
[data-theme="dark"] #icon-moon { display: block; }
87+
[data-theme="dark"] #icon-sun { display: none; }
88+
[data-theme="light"] #icon-moon { display: none; }
89+
[data-theme="light"] #icon-sun { display: block; }
90+
8591
/* ---------- Reset & Base ---------- */
8692
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
8793

static/index.html

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
11
<!DOCTYPE html>
2-
<html lang="en" data-theme="dark">
2+
<html lang="en">
33
<head>
44
<meta charset="UTF-8">
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
66
<title>Claude Code Chat Browser</title>
7+
<script>
8+
/* Apply saved theme before first paint (avoids dark flash in light mode).
9+
hljs URLs/integrity must match HLJS_THEME_SHEETS in static/js/shared/theme.js */
10+
(function () {
11+
var t = localStorage.getItem('theme');
12+
if (t !== 'light' && t !== 'dark') t = 'dark';
13+
document.documentElement.setAttribute('data-theme', t);
14+
})();
15+
</script>
716
<link rel="stylesheet" href="/static/css/style.css">
817
<!-- SRI hashes pin each CDN asset to a specific known-good payload; the
918
browser refuses anything whose hash does not match (issue #19).
@@ -17,6 +26,16 @@
1726
integrity="sha512-mtXspRdOWHCYp+f4c7CkWGYPPRAhq9X+xCvJMUBVAb6pqA4U8pxhT3RWT3LP3bKbiolYL2CkL1bSKZZO4eeTew=="
1827
crossorigin="anonymous"
1928
id="hljs-theme">
29+
<script>
30+
(function () {
31+
var t = document.documentElement.getAttribute('data-theme') || 'dark';
32+
if (t !== 'light') return;
33+
var link = document.getElementById('hljs-theme');
34+
if (!link) return;
35+
link.integrity = 'sha512-0aPQyyeZrWgKOP0mUipLQ6OZXu8l4IcAmD2u31EPEy9VcIMvl7SoAaKe8bLXZhYoMaE/in+gcgA==';
36+
link.href = 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github.min.css';
37+
})();
38+
</script>
2039
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"
2140
integrity="sha512-D9gUyxqja7hBtkWpPWGt9wfbfaMGVt9gnyCvYa+jojwwPHLCzUm5i8rpk7vD7wNee9bA35eYIjobYPaQuKS1MQ=="
2241
crossorigin="anonymous"></script>
@@ -44,7 +63,7 @@
4463
</a>
4564
<button id="theme-toggle" class="nav-link" title="Toggle theme" onclick="toggleTheme()">
4665
<svg id="icon-moon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>
47-
<svg id="icon-sun" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:none"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></svg>
66+
<svg id="icon-sun" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></svg>
4867
</button>
4968
</div>
5069
</div>

static/js/search.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,12 @@ export function showSearchPage() {
2828
<div id="search-results"></div>
2929
</div>`;
3030
document.getElementById('search-results').addEventListener('click', (e) => {
31+
if (!(e.target instanceof Element)) return;
3132
const result = e.target.closest('.search-result[data-project]');
3233
if (!result) return;
3334
const project = result.getAttribute('data-project');
3435
const sessionId = result.getAttribute('data-session-id');
36+
if (!project || !sessionId) return;
3537
window.location.hash = `#project/${encodeURIComponent(project)}/${encodeURIComponent(sessionId)}`;
3638
});
3739
document.getElementById('search-input').focus();

static/js/sessions.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,12 @@ function bindSidebarSessionClicks() {
100100
const sidebar = document.getElementById('sidebar');
101101
if (!sidebar) return;
102102
sidebar.addEventListener('click', (e) => {
103+
if (!(e.target instanceof Element)) return;
103104
const btn = e.target.closest('button.sidebar-item[data-session-id]');
104105
if (!btn) return;
105106
const project = btn.getAttribute('data-project');
106107
const sessionId = btn.getAttribute('data-session-id');
107-
if (project == null || sessionId == null) return;
108+
if (!project || !sessionId) return;
108109
selectSession(project, sessionId);
109110
});
110111
}

0 commit comments

Comments
 (0)