From 1f8127641de342a6a61a49c67ab6789078eb7e8b Mon Sep 17 00:00:00 2001 From: Christophe Date: Sun, 12 Apr 2026 20:28:54 +0200 Subject: [PATCH] =?UTF-8?q?Transforme=20les=20s=C3=A9lecteurs=20en=20zones?= =?UTF-8?q?=20bouton?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 35 ++++++++++++++++ styles.css | 119 ++++++++++++++++------------------------------------- 2 files changed, 70 insertions(+), 84 deletions(-) diff --git a/app.js b/app.js index d2ff3c6..310245e 100644 --- a/app.js +++ b/app.js @@ -116,6 +116,7 @@ function initSetupPage() { const loadDemoButton = document.querySelector("#loadDemoButton"); const resumeCard = document.querySelector("#resumeCard"); const refreshAppButton = document.querySelector("#refreshAppButton"); + const optionCards = Array.from(document.querySelectorAll(".option-card")); const competitionModeInput = document.querySelector("#competitionMode"); const competitionFields = Array.from(document.querySelectorAll("[data-competition-field]")); const moveSecondsField = document.querySelector("#moveSecondsField"); @@ -151,6 +152,21 @@ function initSetupPage() { }); }; + const syncOptionCardStates = () => { + optionCards.forEach((card) => { + if (!(card instanceof HTMLElement)) { + return; + } + + const input = card.querySelector('input[type="radio"], input[type="checkbox"]'); + if (!(input instanceof HTMLInputElement)) { + return; + } + + card.classList.toggle("is-selected", input.checked); + }); + }; + const renderSummary = () => { const mode = getRadioValue(form, "mode") || "twice"; const preset = getRadioValue(form, "preset") || "fast"; @@ -195,6 +211,7 @@ function initSetupPage() { } syncCompetitionFields(); + syncOptionCardStates(); summary.innerHTML = ` ${MODES[mode].label} @@ -246,6 +263,24 @@ function initSetupPage() { form.addEventListener("input", renderSummary); loadDemoButton.addEventListener("click", () => loadDemo(form, renderSummary)); + optionCards.forEach((card) => { + if (!(card instanceof HTMLElement)) { + return; + } + + const input = card.querySelector('input[type="radio"], input[type="checkbox"]'); + if (!(input instanceof HTMLInputElement)) { + return; + } + + input.addEventListener("focus", () => { + card.classList.add("is-focused"); + }); + + input.addEventListener("blur", () => { + card.classList.remove("is-focused"); + }); + }); refreshAppButton?.addEventListener("click", async () => { if (!(refreshAppButton instanceof HTMLButtonElement)) { return; diff --git a/styles.css b/styles.css index 35165fa..695b65f 100644 --- a/styles.css +++ b/styles.css @@ -456,7 +456,7 @@ textarea:focus { display: grid; gap: 0.45rem; min-height: 8.7rem; - padding: 1rem 1rem 1rem 3rem; + padding: 1rem; border-radius: 22px; border: 1px solid var(--panel-border); background: #121212; @@ -476,82 +476,51 @@ textarea:focus { .option-card input { position: absolute; - top: 1.1rem; - left: 1rem; - width: 1.1rem; - height: 1.1rem; - margin: 0; + width: 1px; + height: 1px; + margin: -1px; padding: 0; - appearance: none; - -webkit-appearance: none; - display: grid; - place-items: center; - border: 1px solid var(--panel-border-strong); - background: #0c0c0c; - box-shadow: none; - cursor: pointer; -} - -.option-card input:focus { - outline: none; -} - -.option-card input[type="radio"] { - border-radius: 999px; -} - -.option-card input[type="checkbox"] { - border-radius: 0.35rem; -} - -.option-card input::before { - content: ""; - display: block; - transition: transform 160ms ease; - transform: scale(0); -} - -.option-card input:checked { - border-color: rgba(52, 141, 255, 0.55); - background: rgba(17, 103, 255, 0.12); -} - -.option-card input[type="radio"]::before { - width: 0.52rem; - height: 0.52rem; - border-radius: 999px; - background: var(--cool); -} - -.option-card input[type="checkbox"]::before { - width: 0.6rem; - height: 0.32rem; - margin-top: -0.04rem; - border-left: 2px solid var(--cool); - border-bottom: 2px solid var(--cool); - transform: rotate(-45deg) scale(0); - transform-origin: center; -} - -.option-card input:checked::before { - transform: scale(1); -} - -.option-card input[type="checkbox"]:checked::before { - transform: rotate(-45deg) scale(1); + border: 0; + overflow: hidden; + clip: rect(0 0 0 0); + clip-path: inset(50%); + white-space: nowrap; } +.option-card.is-focused, .option-card:has(input:focus-visible) { outline: 2px solid rgba(52, 141, 255, 0.45); outline-offset: 2px; } +.option-card.is-selected, .option-card:has(input:checked) { - border-color: rgba(52, 141, 255, 0.52); - background: rgba(17, 103, 255, 0.14); + border-color: rgba(52, 141, 255, 0.58); + background: linear-gradient(180deg, rgba(17, 103, 255, 0.16), rgba(17, 103, 255, 0.1)); box-shadow: none; } +.option-card.is-selected strong, +.option-card:has(input:checked) strong { + color: #f7fbff; +} + +.option-card.is-selected span, +.option-card:has(input:checked) span { + color: #d6e5ff; +} + +.competition-option.is-selected, +.competition-option:has(input:checked) { + border-color: rgba(255, 157, 30, 0.48); + background: linear-gradient(180deg, rgba(255, 127, 0, 0.14), rgba(255, 157, 30, 0.08)); +} + +.competition-option.is-selected span, +.competition-option:has(input:checked) span { + color: #ffe6c4; +} + .competition-option { min-height: 0; gap: 0.25rem; @@ -1603,18 +1572,11 @@ body[data-page="cube"] .zone-button.cube-hold-ready::after { body[data-page="setup"] .option-card { min-height: 0; - padding: 0.75rem 0.75rem 0.75rem 2rem; + padding: 0.75rem; border-radius: 18px; gap: 0.2rem; } - body[data-page="setup"] .option-card input { - top: 0.82rem; - left: 0.75rem; - width: 0.95rem; - height: 0.95rem; - } - body[data-page="setup"] .option-card span { font-size: 0.8rem; line-height: 1.25; @@ -1627,12 +1589,6 @@ body[data-page="cube"] .zone-button.cube-hold-ready::after { align-content: center; } - body[data-page="setup"] .mode-grid .option-card input, - body[data-page="setup"] .mode-grid .option-card span { - position: static; - margin: 0 auto; - } - body[data-page="setup"] .mode-grid .option-card span { display: none; } @@ -1642,11 +1598,6 @@ body[data-page="cube"] .zone-button.cube-hold-ready::after { text-align: center; } - body[data-page="setup"] .preset-grid .option-card input { - position: static; - margin: 0 auto 0.2rem; - } - body[data-page="setup"] .setup-actions { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));