Skip to content

Commit 694e291

Browse files
jt14denclaude
andcommitted
UI: Implement official UCLA Dark Mode theme
- Create src/styles/_sass/base/_dark-mode.scss: Comprehensive dark theme using official UCLA Brand colors (Darkest Blue #003B5C, UCLA Gold #FFD100). - Add theme toggle switch to Navbar with persistence via localStorage. - Implement no-flash theme detection in Layout.astro to prevent white flickering on load. - Specific overrides for: - Hero sections (dimmed with dark overlays) - Lesson cards (handling inline white gradients) - Lesson status dashboard and tables - Pilot recruitment banner and cards - Callout boxes and benefit sections - Footer and navbar components - Ensures WCAG AA accessibility compliance for text contrast in dark mode. Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
1 parent 1d66792 commit 694e291

File tree

4 files changed

+549
-0
lines changed

4 files changed

+549
-0
lines changed

src/components/Navbar.astro

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,44 @@ const navLinks = (navData as any)[siteConfig.locale]?.nav || [];
3939
)}
4040
</li>
4141
))}
42+
<!-- Dark Mode Toggle -->
43+
<li class="nav-item d-flex align-items-center">
44+
<div class="theme-switch-wrapper ml-3">
45+
<label class="theme-switch" for="checkbox" style="margin-bottom: 0;">
46+
<input type="checkbox" id="checkbox" />
47+
<div class="slider round"></div>
48+
</label>
49+
</div>
50+
</li>
4251
</ul>
4352
</div>
4453
</div>
4554
</nav>
55+
56+
<script>
57+
function initToggle() {
58+
const toggleSwitch = document.querySelector('.theme-switch input[type="checkbox"]');
59+
if (!toggleSwitch) return;
60+
61+
// Sync toggle with current document state
62+
const currentTheme = document.documentElement.getAttribute('data-theme');
63+
if (currentTheme === 'dark') {
64+
(toggleSwitch as HTMLInputElement).checked = true;
65+
}
66+
67+
// Handle clicks
68+
toggleSwitch.addEventListener('change', (e) => {
69+
const isChecked = (e.target as HTMLInputElement).checked;
70+
const newTheme = isChecked ? 'dark' : 'light';
71+
72+
document.documentElement.setAttribute('data-theme', newTheme);
73+
localStorage.setItem('theme', newTheme);
74+
});
75+
}
76+
77+
// Run on load
78+
initToggle();
79+
80+
// Run on Astro navigation
81+
document.addEventListener('astro:after-swap', initToggle);
82+
</script>

src/layouts/Layout.astro

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,28 @@ const { title, description } = Astro.props;
2525
<!-- Bootstrap & FontAwesome -->
2626
<link href="/assets/css/bootstrap.min.css" rel="stylesheet" />
2727
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css" integrity="sha512-1ycn6IcaQQ40/MKBW2W4Rhis/DbILU74C1vSrLJxCq57o941Ym01SwNsOMqvEBFlcgUa6xLiPY/NS5R+E6ztJQ==" crossorigin="anonymous" referrerpolicy="no-referrer" />
28+
29+
<!-- Theme Script (Prevent FOUC) -->
30+
<script is:inline>
31+
(function() {
32+
try {
33+
const localTheme = localStorage.getItem('theme');
34+
const supportDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches === true;
35+
36+
// Determine theme: localStorage > system preference > default (light)
37+
let theme = localTheme;
38+
if (!theme && supportDarkMode) {
39+
theme = 'dark';
40+
}
41+
42+
if (theme) {
43+
document.documentElement.setAttribute('data-theme', theme);
44+
}
45+
} catch (e) {
46+
console.error("Theme init failed", e);
47+
}
48+
})();
49+
</script>
2850
</head>
2951
<body id="page-top">
3052
<Navbar />

0 commit comments

Comments
 (0)