Skip to content

Commit 2301bd6

Browse files
Support responsive mode
1 parent ad1fa3d commit 2301bd6

3 files changed

Lines changed: 179 additions & 58 deletions

File tree

public/css/style.css

Lines changed: 153 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -7,36 +7,39 @@
77
@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap');
88

99
/* ---- Réinitialisation et variables ---- */
10-
*, *::before, *::after {
10+
*,
11+
*::before,
12+
*::after {
1113
box-sizing: border-box;
1214
margin: 0;
1315
padding: 0;
1416
}
1517

1618
:root {
17-
--bg: #080c14;
18-
--bg-panel: rgba(8, 14, 28, 0.92);
19-
--bg-code: #0b1120;
20-
--border: rgba(0, 212, 255, 0.18);
19+
--bg: #080c14;
20+
--bg-panel: rgba(8, 14, 28, 0.92);
21+
--bg-code: #0b1120;
22+
--border: rgba(0, 212, 255, 0.18);
2123
--border-glow: rgba(0, 212, 255, 0.45);
22-
--cyan: #00d4ff;
23-
--cyan-dim: rgba(0, 212, 255, 0.6);
24-
--green: #00ff9f;
25-
--purple: #9d4edd;
26-
--text: #cdd6f4;
27-
--text-dim: #6b7a99;
24+
--cyan: #00d4ff;
25+
--cyan-dim: rgba(0, 212, 255, 0.6);
26+
--green: #00ff9f;
27+
--purple: #9d4edd;
28+
--text: #cdd6f4;
29+
--text-dim: #6b7a99;
2830
--text-bright: #e8eeff;
29-
--font-ui: 'Space Grotesk', system-ui, sans-serif;
30-
--font-code: 'JetBrains Mono', 'Fira Code', monospace;
31-
--radius: 8px;
32-
--radius-lg: 14px;
33-
--sidebar-w: 380px;
34-
--header-h: 48px;
35-
--controls-h: 64px;
36-
--transition: 0.25s ease;
37-
}
38-
39-
html, body {
31+
--font-ui: 'Space Grotesk', system-ui, sans-serif;
32+
--font-code: 'JetBrains Mono', 'Fira Code', monospace;
33+
--radius: 8px;
34+
--radius-lg: 14px;
35+
--sidebar-w: 380px;
36+
--header-h: 48px;
37+
--controls-h: 64px;
38+
--transition: 0.25s ease;
39+
}
40+
41+
html,
42+
body {
4043
height: 100%;
4144
overflow: hidden;
4245
background: var(--bg);
@@ -71,6 +74,7 @@ html, body {
7174
padding: 0 20px;
7275
background: rgba(8, 12, 22, 0.98);
7376
border-bottom: 1px solid var(--border);
77+
-webkit-backdrop-filter: blur(10px);
7478
backdrop-filter: blur(10px);
7579
z-index: 10;
7680
}
@@ -139,7 +143,9 @@ html, body {
139143
transition: opacity var(--transition);
140144
}
141145

142-
#render-status.hidden { opacity: 0; }
146+
#render-status.hidden {
147+
opacity: 0;
148+
}
143149

144150
/* Coordonnées du curseur */
145151
#coords-display {
@@ -163,6 +169,7 @@ html, body {
163169
flex-direction: column;
164170
background: var(--bg-panel);
165171
border-left: 1px solid var(--border);
172+
-webkit-backdrop-filter: blur(12px);
166173
backdrop-filter: blur(12px);
167174
overflow: hidden;
168175
transition: width var(--transition);
@@ -214,7 +221,7 @@ html, body {
214221
font-size: 12px;
215222
}
216223

217-
.badge-row + .badge-row {
224+
.badge-row+.badge-row {
218225
margin-top: 5px;
219226
}
220227

@@ -299,7 +306,11 @@ html, body {
299306
width: 5px;
300307
height: 5px;
301308
}
302-
.code-scroll::-webkit-scrollbar-track { background: transparent; }
309+
310+
.code-scroll::-webkit-scrollbar-track {
311+
background: transparent;
312+
}
313+
303314
.code-scroll::-webkit-scrollbar-thumb {
304315
background: var(--border);
305316
border-radius: 3px;
@@ -315,13 +326,43 @@ pre {
315326
}
316327

317328
/* Coloration syntaxique */
318-
.kw { color: #c792ea; font-weight: 500; } /* violet — mots-clés */
319-
.fn { color: #82aaff; } /* bleu — fonctions */
320-
.num { color: #f78c6c; } /* orange — nombres */
321-
.str { color: #c3e88d; } /* vert — chaînes */
322-
.cmt { color: #546e7a; font-style: italic; } /* gris — commentaires */
323-
.op { color: #89ddff; } /* cyan — opérateurs */
324-
.param { color: #ffcb6b; } /* jaune — paramètres */
329+
.kw {
330+
color: #c792ea;
331+
font-weight: 500;
332+
}
333+
334+
/* violet — mots-clés */
335+
.fn {
336+
color: #82aaff;
337+
}
338+
339+
/* bleu — fonctions */
340+
.num {
341+
color: #f78c6c;
342+
}
343+
344+
/* orange — nombres */
345+
.str {
346+
color: #c3e88d;
347+
}
348+
349+
/* vert — chaînes */
350+
.cmt {
351+
color: #546e7a;
352+
font-style: italic;
353+
}
354+
355+
/* gris — commentaires */
356+
.op {
357+
color: #89ddff;
358+
}
359+
360+
/* cyan — opérateurs */
361+
.param {
362+
color: #ffcb6b;
363+
}
364+
365+
/* jaune — paramètres */
325366

326367
/* ---- Barre de contrôles ---- */
327368
#controls {
@@ -332,6 +373,7 @@ pre {
332373
padding: 0 20px;
333374
background: rgba(8, 12, 22, 0.98);
334375
border-top: 1px solid var(--border);
376+
-webkit-backdrop-filter: blur(10px);
335377
backdrop-filter: blur(10px);
336378
z-index: 10;
337379
}
@@ -410,7 +452,8 @@ select {
410452
transition: border-color var(--transition);
411453
}
412454

413-
select:hover, select:focus {
455+
select:hover,
456+
select:focus {
414457
border-color: var(--border-glow);
415458
}
416459

@@ -484,9 +527,16 @@ select:hover, select:focus {
484527
opacity: 0;
485528
}
486529

530+
/* ---- Bouton fermeture sidebar (mobile uniquement) ---- */
531+
.sidebar-close-btn {
532+
display: none;
533+
}
534+
487535
/* ============================================================
488-
RESPONSIVE : masquer sidebar sur petits écrans
536+
RESPONSIVE
489537
============================================================ */
538+
539+
/* ≤ 820 px : sidebar en overlay flottant */
490540
@media (max-width: 820px) {
491541
:root {
492542
--sidebar-w: 0px;
@@ -500,33 +550,90 @@ select:hover, select:focus {
500550
"controls";
501551
}
502552

553+
/* Sidebar cachée par défaut, s'affiche en overlay plein-écran sous le header */
503554
#sidebar {
504555
display: none;
556+
position: fixed;
557+
top: var(--header-h);
558+
left: 0;
559+
right: 0;
560+
bottom: 0;
561+
z-index: 50;
562+
width: 100%;
563+
border-left: none;
564+
border-top: 1px solid var(--border);
505565
}
506566

567+
#sidebar.mobile-open {
568+
display: flex;
569+
}
570+
571+
#sidebar-inner {
572+
width: 100%;
573+
}
574+
575+
/* Bouton toggle reste visible pour ouvrir/fermer l'overlay */
507576
#btn-toggle-sidebar {
508-
display: none;
577+
display: inline-flex;
578+
}
579+
580+
/* Bouton ✕ visible uniquement sur mobile */
581+
.sidebar-close-btn {
582+
display: inline-flex;
583+
padding: 4px 10px;
584+
font-size: 13px;
585+
margin-left: auto;
586+
}
587+
588+
.sidebar-header {
589+
display: flex;
590+
align-items: center;
509591
}
510592
}
511593

594+
/* ≤ 540 px : barre de contrôles sur 2 lignes */
512595
@media (max-width: 540px) {
596+
:root {
597+
--controls-h: 116px;
598+
}
599+
513600
#controls {
514-
gap: 8px;
515-
padding: 0 10px;
516-
overflow-x: auto;
601+
flex-wrap: wrap;
602+
gap: 6px 10px;
603+
padding: 8px 12px;
604+
align-content: center;
605+
overflow-x: unset;
606+
}
607+
608+
.ctrl-sep {
609+
display: none;
517610
}
518611

519612
input[type="range"] {
520613
width: 90px;
521614
}
522615
}
523616

617+
/* ≤ 400 px : masquer le sous-titre du header */
618+
@media (max-width: 400px) {
619+
.header-subtitle {
620+
display: none;
621+
}
622+
}
623+
524624
/* ============================================================
525625
ANIMATION DE CHARGEMENT INITIAL
526626
============================================================ */
527627
@keyframes pulse-glow {
528-
0%, 100% { opacity: 0.5; }
529-
50% { opacity: 1.0; }
628+
629+
0%,
630+
100% {
631+
opacity: 0.5;
632+
}
633+
634+
50% {
635+
opacity: 1.0;
636+
}
530637
}
531638

532639
.loading-pulse {
@@ -538,13 +645,11 @@ select:hover, select:focus {
538645
content: '';
539646
position: absolute;
540647
inset: 0;
541-
background: repeating-linear-gradient(
542-
0deg,
543-
transparent,
544-
transparent 2px,
545-
rgba(0, 0, 0, 0.03) 2px,
546-
rgba(0, 0, 0, 0.03) 4px
547-
);
648+
background: repeating-linear-gradient(0deg,
649+
transparent,
650+
transparent 2px,
651+
rgba(0, 0, 0, 0.03) 2px,
652+
rgba(0, 0, 0, 0.03) 4px);
548653
pointer-events: none;
549654
z-index: 1;
550-
}
655+
}

public/index.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
<line x1="1" y1="14" x2="27" y2="14" stroke="#00d4ff" stroke-width="0.5" opacity="0.3" />
3636
</svg>
3737
Explorateur de <span>Fractales</span>
38-
<span style="color:var(--text-dim);font-weight:400;font-size:12px;margin-left:4px">
38+
<span class="header-subtitle" style="color:var(--text-dim);font-weight:400;font-size:12px;margin-left:4px">
3939
· multilingual → WebAssembly
4040
</span>
4141
</div>
@@ -85,6 +85,7 @@
8585
<!-- Titre -->
8686
<div class="sidebar-header">
8787
<h2>Source &amp; Performances</h2>
88+
<button id="btn-close-sidebar" type="button" class="btn sidebar-close-btn" aria-label="Fermer le panneau"></button>
8889
</div>
8990

9091
<!-- Badge benchmark -->

public/js/renderer.js

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,9 @@ const fractalSelect = document.getElementById("fractal-select");
8989
const multibrotPower = document.getElementById("multibrot-power");
9090
const paletteSelect = document.getElementById("palette-select");
9191
const btnReset = document.getElementById("btn-reset");
92-
const btnToggle = document.getElementById("btn-toggle-sidebar");
93-
const sidebar = document.getElementById("sidebar");
92+
const btnToggle = document.getElementById("btn-toggle-sidebar");
93+
const btnCloseSidebar = document.getElementById("btn-close-sidebar");
94+
const sidebar = document.getElementById("sidebar");
9495
const zoomHint = document.getElementById("zoom-hint");
9596
const badgeDiv = document.getElementById("benchmark-badge");
9697
const badgeLoading = document.getElementById("badge-loading");
@@ -625,13 +626,22 @@ paletteSelect.addEventListener("change", () => {
625626
btnReset.addEventListener("click", resetView);
626627

627628
btnToggle.addEventListener("click", () => {
628-
sidebar.classList.toggle("collapsed");
629-
// Recalculer le pixelSize après changement de taille
630-
setTimeout(() => {
631-
const newW = canvas.parentElement.clientWidth;
632-
view.pixelSize = view.pixelSize * (canvas.width / Math.max(newW, 1));
633-
render();
634-
}, 280);
629+
if (window.innerWidth <= 820) {
630+
// Mobile : overlay plein-écran, le canvas ne change pas de taille
631+
sidebar.classList.toggle("mobile-open");
632+
} else {
633+
sidebar.classList.toggle("collapsed");
634+
// Recalculer le pixelSize après changement de taille
635+
setTimeout(() => {
636+
const newW = canvas.parentElement.clientWidth;
637+
view.pixelSize = view.pixelSize * (canvas.width / Math.max(newW, 1));
638+
render();
639+
}, 280);
640+
}
641+
});
642+
643+
btnCloseSidebar.addEventListener("click", () => {
644+
sidebar.classList.remove("mobile-open");
635645
});
636646

637647
window.addEventListener("resize", () => {
@@ -921,6 +931,11 @@ async function init() {
921931
// Charger sources et benchmark en parallèle
922932
await Promise.all([loadSources(params.fractal), loadBenchmark()]);
923933

934+
// Adapter le texte de l'astuce selon le dispositif
935+
if (zoomHint && ('ontouchstart' in window || navigator.maxTouchPoints > 0)) {
936+
zoomHint.textContent = "Toucher : zoom ×2 · Double toucher : dézoom · Pincer : zoom libre";
937+
}
938+
924939
showZoomHint();
925940
}
926941

0 commit comments

Comments
 (0)