A.4 cont.: card-deck icon placeholder mode (no-deck-equipped) styled like empty dice slot — TDD. User polish 2026-05-25 PM after browser-verifying the kit-bag dialog: when no deck is equipped (kit-bag-placeholder branch fires) the new card-stack icon should not animate + should render w. the same dimmed rgba(--quaUser, 0.x) palette as the existing fa-dice empty slot next to it, not the bright --terUser stroke / --priUser fill of an equipped-deck icon. Two SCSS changes: (1) Removed .deck-stack-icon:hover + .deck-stack-icon:active from the splay-trigger selector list — only wrapper-based selectors (.token.deck-variant, .kit-bag-deck) fire the fan-out now. Placeholder icons land inside .kit-bag-placeholder (or game_kit applet's .kit-item empty-state) which aren't in the trigger list, so they stay static no matter where the user hovers. (2) New .kit-bag-placeholder .deck-stack-icon + .kit-item .deck-stack-icon descendant-selector rule: drops color (= stroke via currentColor) to rgba(--quaUser, 0.3) matching the existing .kit-bag-placeholder color (_game-kit.scss:143); drops .deck-stack-icon__card fill to rgba(--quaUser, 0.15) (lower than the stroke alpha — user-dialed 2026-05-25 PM for a subtler look, the cards read as faintly-present "absence" rather than bright-but-grey). 1 new IT in KitBagViewTest (clears equipped_deck → asserts .kit-bag-deck absent, .kit-bag-placeholder present + carries svg.deck-stack-icon + lacks fa-id-badge). Tests: 1 new green; 1298/1298 IT+UT total green (71s; +1 from d26c45b's 1297). Visual verify pending: refresh /gameboard/ + clear equipped deck → kit-bag dialog Deck slot should show a dimmed static card-stack icon matching the dice slot's washed-out look

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Disco DeDisco
2026-05-25 01:07:24 -04:00
parent d26c45bf77
commit 750fef890e
2 changed files with 48 additions and 10 deletions

View File

@@ -517,6 +517,34 @@ class KitBagViewTest(TestCase):
"fa-regular fa-id-badge must be gone from kit-bag-deck",
)
def test_no_deck_equipped_renders_placeholder_card_stack_icon(self):
"""Sprint A.4 follow-up — when the user has no equipped_deck, the
kit-bag Deck section renders the same .deck-stack-icon SVG inside a
.kit-bag-placeholder wrapper (no fan-out trigger; CSS dims it to
--quaUser at 0.3 alpha to match the empty dice slot)."""
import lxml.html
# Clear the auto-equipped Earthman to land in the placeholder branch.
self.user.equipped_deck = None
self.user.save(update_fields=["equipped_deck"])
response = self.client.get(self.url)
parsed = lxml.html.fromstring(response.content)
# equipped-deck branch is skipped → placeholder branch fires.
self.assertEqual(
len(parsed.cssselect(".kit-bag-deck")), 0,
"No equipped deck → no .kit-bag-deck wrapper",
)
placeholders = parsed.cssselect(".kit-bag-section .kit-bag-placeholder")
# First placeholder is the Deck slot (Dice + Trinket slots also use
# .kit-bag-placeholder when empty); assert at least one carries the
# card-stack SVG.
deck_placeholder = placeholders[0]
[_] = deck_placeholder.cssselect("svg.deck-stack-icon")
# Old fa-id-badge must be gone.
self.assertEqual(
len(deck_placeholder.cssselect("i.fa-id-badge")), 0,
"fa-regular fa-id-badge must be gone from kit-bag-placeholder",
)
def test_polarized_equipped_deck_tooltip_has_x2_decoration(self):
"""Same (x2) decoration as the gameboard applet — polarized decks
signal segment-doubling in the tooltip card-count line via --terUser

View File

@@ -123,16 +123,14 @@ body.page-gameboard {
.deck-stack-icon__card--3 { transform: translateY( 0.4px); }
}
// Sprint A.4 — fan-out trigger lives at the icon level (not nested in
// #id_applet_game_kit) so the same `.deck-stack-icon` works wherever it's
// dropped: gameboard's .token.deck-variant, kit-bag dialog's .kit-bag-deck,
// future room.html pile + deck-bag. Hover/active/focus on the icon itself
// OR any of its known wrappers triggers the splay; cards 2 + 3 fan out from
// under card 1, card 1 stays put. Tooltip portal is wired to the same
// `.token:hover` / `.kit-bag-deck:hover` triggers via JS so the splay +
// tooltip-appearance co-activate.
.deck-stack-icon:hover,
.deck-stack-icon:active,
// Sprint A.4 — fan-out trigger is wrapper-only (NOT self-triggered on the
// SVG itself) so placeholder-mode icons inside .kit-bag-placeholder stay
// static + dim like the empty dice slot. Real-deck wrappers (.token.deck-
// variant on gameboard, .kit-bag-deck in kit-bag dialog, future room.html
// pile + deck-bag) drive the splay; cards 2 + 3 fan out from under card 1,
// card 1 stays put. Tooltip portal is wired to the same `.token:hover` /
// `.kit-bag-deck:hover` triggers via JS so splay + tooltip-appearance
// co-activate.
.token.deck-variant:hover .deck-stack-icon,
.token.deck-variant:active .deck-stack-icon,
.token.deck-variant:focus .deck-stack-icon,
@@ -143,6 +141,18 @@ body.page-gameboard {
.deck-stack-icon__card--3 { transform: translate( 5px, -2px) rotate( 12deg); }
}
// Sprint A.4 — placeholder-mode dim styling. When the icon is inside a
// .kit-bag-placeholder (no deck equipped) or game_kit applet's empty-state
// .kit-item (no decks unlocked), color + fill drop to `--quaUser` at 0.3
// alpha to match the existing empty-slot treatment (`.kit-bag-placeholder`
// at `_game-kit.scss:143`, `.kit-item { opacity: 0.6 }` here). No animation
// since the wrapper isn't in the splay-trigger list above.
.kit-bag-placeholder .deck-stack-icon,
.kit-item .deck-stack-icon {
color: rgba(var(--quaUser), 0.15);
.deck-stack-icon__card { fill: rgba(var(--quiUser), 0.15); }
}
#id_applet_new_game {
display: flex;
flex-direction: column;