Skip to content

Commit 8470c87

Browse files
authored
Theme selector and snow mode perf
Simpler theme button design
2 parents 5d3bca9 + dc06730 commit 8470c87

4 files changed

Lines changed: 105 additions & 36 deletions

File tree

frontend/src/css/main.css

Lines changed: 65 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ input:focus-visible {
153153
top: 0;
154154
z-index: 100;
155155
box-shadow: 2px 0px 10px rgba(00, 00, 00, 0.4);
156+
overflow: hidden;
156157
}
157158

158159
.hero__container {
@@ -191,6 +192,13 @@ input:focus-visible {
191192
font-size: var(--font-size-2xl);
192193
}
193194

195+
.hero__tagline {
196+
display: flex;
197+
align-items: center;
198+
gap: var(--spacing-sm);
199+
flex-wrap: wrap;
200+
}
201+
194202
.hero__description {
195203
font-size: var(--font-size-lg);
196204
opacity: 0.9;
@@ -204,37 +212,55 @@ input:focus-visible {
204212

205213
/* Theme Toggle Buttons */
206214
.theme-buttons {
207-
display: flex;
208-
gap: 0.25rem;
209-
background: rgba(255, 255, 255, 0.15);
210-
border-radius: var(--border-radius);
211-
padding: 0.25rem;
215+
display: inline-flex;
216+
align-items: center;
217+
align-self: center;
218+
background: rgba(0, 0, 0, 0.5);
219+
border: 1px solid rgba(255, 255, 255, 0.6);
220+
border-radius: 1rem;
212221
}
213222

214223
.theme-button {
215224
display: flex;
216225
align-items: center;
217226
justify-content: center;
218-
width: 2rem;
219-
height: 2rem;
227+
padding: 0.25rem 0.375rem;
220228
background: transparent;
221229
border: none;
222-
border-radius: calc(var(--border-radius) - 0.125rem);
230+
border-right: 1px solid rgba(255, 255, 255, 0.3);
223231
cursor: pointer;
224-
font-size: 1rem;
225232
line-height: 1;
226233
transition: var(--transition);
227-
opacity: 0.7;
234+
}
235+
236+
.theme-button svg {
237+
width: 0.75rem;
238+
height: 0.75rem;
239+
display: block;
240+
}
241+
242+
.theme-button:last-child {
243+
border-right: none;
244+
}
245+
246+
.theme-button:first-child {
247+
border-radius: 1rem 0 0 1rem;
248+
}
249+
250+
.theme-button:last-child {
251+
border-radius: 0 1rem 1rem 0;
228252
}
229253

230254
.theme-button:hover {
231-
background: rgba(255, 255, 255, 0.2);
232-
opacity: 1;
255+
background: rgba(255, 255, 255, 0.15);
256+
}
257+
258+
.theme-button:focus {
259+
outline: none;
233260
}
234261

235262
.theme-button.active {
236-
background: rgba(255, 255, 255, 0.3);
237-
opacity: 1;
263+
background: rgba(255, 255, 255, 0.25);
238264
}
239265

240266
.hero__search-toggle {
@@ -299,7 +325,32 @@ input:focus-visible {
299325
}
300326

301327
.hero__header {
328+
display: flex;
302329
justify-content: space-between;
330+
align-items: flex-start;
331+
}
332+
333+
.hero__actions {
334+
flex-shrink: 0;
335+
}
336+
337+
.theme-button {
338+
padding: 0.125rem 0.25rem;
339+
min-width: 32px;
340+
min-height: 16px;
341+
}
342+
343+
.theme-button:hover {
344+
background: transparent;
345+
}
346+
347+
.theme-button.active {
348+
background: rgba(255, 255, 255, 0.25);
349+
}
350+
351+
.theme-button svg {
352+
width: 0.625rem;
353+
height: 0.625rem;
303354
}
304355

305356
.hero__search-toggle {

frontend/src/index.njk

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,30 @@ title: Accueil
66
<section class="hero">
77
<div class="hero__container">
88
<div class="hero__header">
9-
<div>
9+
<div class="hero__text">
1010
<h2 class="hero__title">Trombi Maisons-Doggo</h2>
11-
<p class="hero__description">Ils sont tous beaux.</p>
11+
<p class="hero__tagline">
12+
<span class="hero__description">Ils sont tous beaux.</span>
13+
<span class="theme-buttons">
14+
<button type="button" class="theme-button" data-theme="light" aria-label="Light mode" title="Light mode">
15+
<svg viewBox="0 0 640 640" xmlns="http://www.w3.org/2000/svg">
16+
<path fill="white" d="M64 176C80.6 176 94.2 188.6 95.8 204.7L96.1 211.3C97.8 227.4 111.4 240 128 240L307.1 240L448 300.4L448 544C448 561.7 433.7 576 416 576L384 576C366.3 576 352 561.7 352 544L352 412.7C328 425 300.8 432 272 432C243.2 432 216 425 192 412.7L192 544C192 561.7 177.7 576 160 576L128 576C110.3 576 96 561.7 96 544L96 298.4C58.7 285.2 32 249.8 32 208C32 190.3 46.3 176 64 176zM387.8 32C395.5 32 402.7 35.6 407.4 41.8L424 64L476.1 64C488.8 64 501 69.1 510 78.1L528 96L584 96C597.3 96 608 106.7 608 120L608 144C608 188.2 572.2 224 528 224L464 224L457 252L332.3 198.6L363.9 51.4C366.3 40.1 376.2 32 387.8 32zM480 108C469 108 460 117 460 128C460 139 469 148 480 148C491 148 500 139 500 128C500 117 491 108 480 108z"/>
17+
</svg>
18+
</button>
19+
<button type="button" class="theme-button" data-theme="dark" aria-label="Dark mode" title="Dark mode">
20+
<svg viewBox="0 0 640 640" xmlns="http://www.w3.org/2000/svg">
21+
<path fill="black" stroke="white" stroke-width="24" d="M64 176C80.6 176 94.2 188.6 95.8 204.7L96.1 211.3C97.8 227.4 111.4 240 128 240L307.1 240L448 300.4L448 544C448 561.7 433.7 576 416 576L384 576C366.3 576 352 561.7 352 544L352 412.7C328 425 300.8 432 272 432C243.2 432 216 425 192 412.7L192 544C192 561.7 177.7 576 160 576L128 576C110.3 576 96 561.7 96 544L96 298.4C58.7 285.2 32 249.8 32 208C32 190.3 46.3 176 64 176zM387.8 32C395.5 32 402.7 35.6 407.4 41.8L424 64L476.1 64C488.8 64 501 69.1 510 78.1L528 96L584 96C597.3 96 608 106.7 608 120L608 144C608 188.2 572.2 224 528 224L464 224L457 252L332.3 198.6L363.9 51.4C366.3 40.1 376.2 32 387.8 32zM480 108C469 108 460 117 460 128C460 139 469 148 480 148C491 148 500 139 500 128C500 117 491 108 480 108z"/>
22+
</svg>
23+
</button>
24+
<button type="button" class="theme-button" data-theme="snow" aria-label="Snow mode" title="Snow mode">
25+
<svg viewBox="0 0 640 640" xmlns="http://www.w3.org/2000/svg">
26+
<path fill="white" d="M344.1 56C344.1 42.7 333.4 32 320.1 32C306.8 32 296.1 42.7 296.1 56L296.1 134.1L273.1 111.1C263.7 101.7 248.5 101.7 239.2 111.1C229.9 120.5 229.8 135.7 239.2 145L296.2 202L296.2 278.5L230 240.3L209.1 162.5C205.7 149.7 192.5 142.1 179.7 145.5C166.9 148.9 159.2 162 162.7 174.8L171.1 206.3L103.5 167.3C92 160.6 77.3 164.5 70.7 176C64.1 187.5 68 202.2 79.5 208.8L147.1 247.8L115.6 256.2C102.8 259.6 95.2 272.8 98.6 285.6C102 298.4 115.2 306 128 302.6L205.8 281.7L272 319.9L205.8 358.1L128 337.2C115.2 333.8 102 341.4 98.6 354.2C95.2 367 102.8 380.2 115.6 383.6L147.1 392L79.5 431C68 437.8 64.1 452.5 70.7 464C77.3 475.5 92 479.4 103.5 472.8L171.1 433.8L162.7 465.3C159.3 478.1 166.9 491.3 179.7 494.7C192.5 498.1 205.7 490.5 209.1 477.7L230 399.9L296.2 361.7L296.2 438.2L239.2 495.2C229.8 504.6 229.8 519.8 239.2 529.1C248.6 538.4 263.8 538.5 273.1 529.1L296.1 506.1L296.1 584.2C296.1 597.5 306.8 608.2 320.1 608.2C333.4 608.2 344.1 597.5 344.1 584.2L344.1 506.1L367.1 529.1C376.5 538.5 391.7 538.5 401 529.1C410.3 519.7 410.4 504.5 401 495.2L344 438.2L344 361.7L410.2 399.9L431.1 477.7C434.5 490.5 447.7 498.1 460.5 494.7C473.3 491.3 480.9 478.1 477.5 465.3L469.1 433.8L536.7 472.8C548.2 479.4 562.9 475.5 569.5 464C576.1 452.5 572.2 437.8 560.7 431.2L493.1 392.2L524.6 383.8C537.4 380.4 545 367.2 541.6 354.4C538.2 341.6 525 334 512.2 337.4L434.4 358.3L368.2 320.1L434.4 281.9L512.2 302.8C525 306.2 538.2 298.6 541.6 285.8C545 273 537.4 259.8 524.6 256.4L493.1 248L560.7 209C572.2 202.4 576.1 187.7 569.5 176.2C562.9 164.7 548.2 160.8 536.7 167.4L469.1 206.4L477.5 174.9C480.9 162.1 473.3 148.9 460.5 145.5C447.7 142.1 434.5 149.7 431.1 162.5L410.2 240.3L344 278.5L344 202L401 145C410.4 135.6 410.4 120.4 401 111.1C391.6 101.8 376.4 101.7 367.1 111.1L344.1 134.1L344.1 56z"/>
27+
</svg>
28+
</button>
29+
</span>
30+
</p>
1231
</div>
1332
<div class="hero__actions">
14-
<div class="theme-buttons">
15-
<button type="button" class="theme-button" data-theme="light" aria-label="Light mode" title="Light mode">☀︎</button>
16-
<button type="button" class="theme-button" data-theme="dark" aria-label="Dark mode" title="Dark mode">☽︎</button>
17-
<button type="button" class="theme-button" data-theme="snow" aria-label="Snow mode" title="Snow mode">❄︎</button>
18-
</div>
1933
<button
2034
type="button"
2135
class="hero__magic-toggle magic-indicator"

frontend/src/js/main.js

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,10 @@
5151
var isHomePage = !!document.getElementById('dogs-grid');
5252
var themeButtons = document.querySelectorAll('.theme-button');
5353

54-
// Load saved theme or detect from system
54+
// Load saved theme (no active state if using system default)
5555
var savedTheme = localStorage.getItem('theme');
5656
if (savedTheme) {
57-
applyTheme(savedTheme, false);
58-
} else {
59-
// Mark the appropriate button based on system preference
60-
var prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
61-
updateActiveButton(prefersDark ? 'dark' : 'light');
57+
applyTheme(savedTheme);
6258
}
6359

6460
// Add click handlers if buttons exist
@@ -76,12 +72,14 @@
7672
snowInstance.stop();
7773
snowInstance = null;
7874
}
79-
var prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
80-
updateActiveButton(prefersDark ? 'dark' : 'light');
75+
updateActiveButton(null);
8176
} else {
82-
applyTheme(theme, true);
77+
applyTheme(theme);
8378
localStorage.setItem('theme', theme);
8479
}
80+
81+
// Remove focus to clear any visual state
82+
this.blur();
8583
});
8684
});
8785
}
@@ -114,7 +112,7 @@
114112

115113
function updateActiveButton(theme) {
116114
themeButtons.forEach(function(btn) {
117-
btn.classList.toggle('active', btn.dataset.theme === theme);
115+
btn.classList.toggle('active', theme && btn.dataset.theme === theme);
118116
});
119117
}
120118
}

frontend/src/js/snow.js

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,14 @@
77
var PureSnow = (function() {
88
'use strict';
99

10-
var snowflakesCount = 150;
1110
var styleElement = null;
1211
var snowContainer = null;
1312

13+
function getSnowflakeCount() {
14+
// Fewer snowflakes on small screens for performance
15+
return window.innerWidth < 768 ? 25 : 150;
16+
}
17+
1418
function randomInt(value) {
1519
return Math.floor(Math.random() * value) + 1;
1620
}
@@ -24,7 +28,7 @@ var PureSnow = (function() {
2428
function createSnowContainer() {
2529
var container = document.createElement('div');
2630
container.id = 'snow';
27-
container.style.cssText = 'position: fixed; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 9999; overflow: hidden;';
31+
container.style.cssText = 'position: fixed; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 50; overflow: hidden; will-change: transform; transform: translateZ(0);';
2832
document.body.appendChild(container);
2933
return container;
3034
}
@@ -49,7 +53,7 @@ var PureSnow = (function() {
4953
var bodyHeightPx = Math.max(document.body.offsetHeight, window.innerHeight);
5054
var pageHeightVH = (100 * bodyHeightPx / window.innerHeight);
5155

52-
var baseCss = '.snowflake { position: absolute; width: 8px; height: 8px; background: white; border-radius: 50%; filter: drop-shadow(0 0 8px white); pointer-events: none; }';
56+
var baseCss = '.snowflake { position: absolute; width: 8px; height: 8px; background: white; border-radius: 50%; filter: drop-shadow(0 0 8px white); will-change: transform; }';
5357

5458
var rule = baseCss;
5559

@@ -77,15 +81,17 @@ var PureSnow = (function() {
7781
// Remove any existing snow
7882
this.stop();
7983

84+
var count = getSnowflakeCount();
85+
8086
// Create container
8187
snowContainer = createSnowContainer();
8288

8389
// Generate and add CSS
84-
var css = generateSnowCSS(snowflakesCount);
90+
var css = generateSnowCSS(count);
8591
styleElement = addCss(css);
8692

8793
// Spawn snowflakes
88-
spawnSnow(snowContainer, snowflakesCount);
94+
spawnSnow(snowContainer, count);
8995

9096
return this;
9197
},

0 commit comments

Comments
 (0)