From db443b753365a1392c63f15686e1b3b8a64be1d7 Mon Sep 17 00:00:00 2001 From: Disco DeDisco Date: Wed, 20 May 2026 09:56:19 -0400 Subject: [PATCH] =?UTF-8?q?Revert=20universal=20`.btn-disabled`=20?= =?UTF-8?q?=E2=86=92=20=C3=97=20pseudo-element=20overlay=20(iter-4c);=20re?= =?UTF-8?q?store=20case-by-case=20`×`=20rendering=20convention.=20My?= =?UTF-8?q?=20Sea=20DEL=20btn=20now=20swaps=20`DEL`=20=E2=86=94=20`=C3=97`?= =?UTF-8?q?=20in=20lockstep=20w.=20its=20`.btn-disabled`=20toggle=20(match?= =?UTF-8?q?es=20game-kit=20tooltip=20+=20DON/DOFF=20pattern).=20User-spec?= =?UTF-8?q?=202026-05-20.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The iter-4c bundle added a universal `&::before { content: "\00d7"; ... }` overlay on every `.btn-disabled` button + hid native text via `> * { visibility: hidden }` + `color: transparent`. Visually flattened every disabled state across the app (DEL, FLIP, DON/DOFF, palette swatches, etc.) onto a single × glyph — user-rejected: "ruined the old UX appearance". Revert restores `_button-pad.scss` to its pre-iter-4c shape: `color: rgba(--secUser, 0.25)` dims native text in place; no overlay, no inner-content hiding. Templates that want a × on disabled buttons render it explicitly in their own markup (game-kit tooltip ``, my_notes DON/DOFF, etc.). My Sea DEL btn picks up the case-by-case convention: template renders `{% if hand_complete %}DEL{% else %}×{% endif %}`; the picker's `_setComplete(on)` JS handler swaps `delBtn.innerHTML` between `DEL` and `×` in lockstep w. the `.btn-disabled` class toggle so visual + label always agree post-hand-completion. FT `test_form_col_renders_decks_lock_hand_del_and_reversal_pct` now asserts `delbtn.text == "×"` instead of relying on the (now-removed) pseudo-element comment. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/functional_tests/test_game_my_sea.py | 8 ++++---- src/static_src/scss/_button-pad.scss | 24 +----------------------- src/templates/apps/gameboard/my_sea.html | 22 +++++++++++++++++----- 3 files changed, 22 insertions(+), 32 deletions(-) diff --git a/src/functional_tests/test_game_my_sea.py b/src/functional_tests/test_game_my_sea.py index 33cb841..9544783 100644 --- a/src/functional_tests/test_game_my_sea.py +++ b/src/functional_tests/test_game_my_sea.py @@ -894,12 +894,12 @@ class MySeaCardDrawTest(FunctionalTest): self.assertIn("btn-primary", action_btn.get_attribute("class")) self.assertEqual(action_btn.get_attribute("data-state"), "auto-draw") delbtn = picker.find_element(By.CSS_SELECTOR, "#id_sea_del") - # DEL renders w. `.btn-disabled` pre-completion (the `×` overlay - # is CSS-only; raw text content is still "DEL" in the DOM). - # Assert on class state — `.text` returns the visible glyph - # rendered by the pseudo-element layer. + # DEL renders w. `.btn-disabled` pre-completion + inner text "×" + # (case-by-case rendering per game-kit tooltip convention; user- + # spec 2026-05-20 dropped the universal pseudo-element ×). self.assertIn("btn-danger", delbtn.get_attribute("class")) self.assertIn("btn-disabled", delbtn.get_attribute("class")) + self.assertEqual(delbtn.text, "×") # Reversal % caption — default 25 hint = picker.find_element(By.CSS_SELECTOR, ".sea-reversal-hint") self.assertIn("25", hint.text) diff --git a/src/static_src/scss/_button-pad.scss b/src/static_src/scss/_button-pad.scss index 97d5ebb..8851e85 100644 --- a/src/static_src/scss/_button-pad.scss +++ b/src/static_src/scss/_button-pad.scss @@ -515,7 +515,7 @@ pointer-events: none; font-size: 1.2rem; padding-bottom: 0.1rem; - color: transparent !important; // hide native text + color: rgba(var(--secUser), 0.25) !important; background-color: rgba(var(--priUser), 1) !important; border-color: rgba(var(--secUser), 0.25) !important; box-shadow: @@ -523,28 +523,6 @@ 0.12rem 0.12rem 0.25rem rgba(0, 0, 0, 0.25), 0.25rem 0.25rem 0.25rem rgba(var(--secUser), 0.12) ; - position: relative; - - // Universal × overlay — any `.btn-disabled` button reads as × - // regardless of its native inner text/icons (DEL → ×, FLIP → ×, - // LOCK HAND → ×, etc.). Templates that already render `×` - // explicitly (e.g. don/doff toggle pairs) just have their inner - // × hidden by `visibility: hidden` on children; the pseudo's - // glyph is the only one visible — no double-× regression. User - // spec 2026-05-20. - > * { visibility: hidden; } - - &::before { - content: "\00d7"; - position: absolute; - inset: 0; - display: flex; - align-items: center; - justify-content: center; - color: rgba(var(--secUser), 0.5); - font-size: 1.5rem; - font-weight: bold; - } &:hover { text-shadow: diff --git a/src/templates/apps/gameboard/my_sea.html b/src/templates/apps/gameboard/my_sea.html index 16945bc..8cf4876 100644 --- a/src/templates/apps/gameboard/my_sea.html +++ b/src/templates/apps/gameboard/my_sea.html @@ -229,12 +229,15 @@ {# DEL starts `.btn-disabled` until the hand is #} {# complete — per Sprint-5-iter-4c spec, the 1/day #} {# quota is committed at first-card-draw + can't be #} - {# refunded by an early DEL. #} + {# refunded by an early DEL. Case-by-case `×` #} + {# rendering matches game-kit tooltip + DON/DOFF #} + {# convention (user-spec 2026-05-20): a disabled btn #} + {# carries × in its own text node, not via a CSS #} + {# overlay. JS `_setComplete` swaps inner text in #} + {# lockstep with the `.btn-disabled` class toggle. #} + class="btn btn-danger{% if not hand_complete %} btn-disabled{% endif %}">{% if hand_complete %}DEL{% else %}×{% endif %} {# Sea stage — portaled modal that opens on FLIP click via #} @@ -439,9 +442,18 @@ // disabled when shown. The deck STACKS themselves stay // click-responsive (so the user can see the disabled // FLIP feedback) — `_locked` gates the actual draw. + // + // DEL btn text follows the game-kit tooltip convention + // (user-spec 2026-05-20): disabled state reads × (the + // template's initial render does the same), active + // state reads DEL. Lockstep w. the `.btn-disabled` + // class so the visual + label always agree. _locked = on; picker.classList.toggle('my-sea-picker--locked', on); - if (delBtn) delBtn.classList.toggle('btn-disabled', !on); + if (delBtn) { + delBtn.classList.toggle('btn-disabled', !on); + delBtn.innerHTML = on ? 'DEL' : '×'; + } if (actionBtn) { actionBtn.dataset.state = on ? 'gate-view' : 'auto-draw'; actionBtn.innerHTML = on ? 'GATE
VIEW' : 'AUTO
DRAW';