Skip to content

feat: discoverable priority-yield auto-pass UX (CR 117.3d)#5167

Merged
matthewevans merged 4 commits into
mainfrom
ship/priority-yield-ux
Jul 6, 2026
Merged

feat: discoverable priority-yield auto-pass UX (CR 117.3d)#5167
matthewevans merged 4 commits into
mainfrom
ship/priority-yield-ux

Conversation

@matthewevans

Copy link
Copy Markdown
Member

Summary

Priority-yield ("auto-pass") UX for CR 117.3d, building on the engine mechanism from #5132. Four commits:

  1. feat(client): discoverable tap affordance for priority yields — the yield control was reachable only by long-pressing a triggered stack entry (undiscoverable, and it collided with the mobile card-preview long-press). Replaced with an always-visible tap button on triggered-ability entries; long-press is restored to a single uniform meaning (inspect-and-pin).

  2. fix(engine): auto-pass past bare sacrifice-for-mana with no downstream use (CR 117.1d)auto_pass_recommended held priority at every window whenever the player controlled a sac-for-mana permanent (Eldrazi Spawn, Krark-Clan Ironworks, Phyrexian Altar), even when the mana could pay for nothing and the sacrifice triggered nothing (endless priority on an opponent's turn with an uncastable hand). The Krark-Clan Ironworks — The game auto-passes in this board state when it shouldn't, because I can activate Krark-Clan Ir… #544 hold is narrowed to block auto-pass only when the sacrifice/mana enables a concrete follow-up: a feasibly castable spell, a mana-costed non-mana activated ability, or a leaves-battlefield/dies/sacrifice trigger. has_meaningful_priority_action is kept byte-identical (extracted + recomposed) because the CR 732.5 loop-shortcut firewall depends on it still counting a sacrifice as a board change. This is the auto-pass/AI-adjacent change — see the commit body for the full case analysis and the V7 Counter unless pay {1} regression note.

  3. fix(stack): make yield affordance discoverable and dismiss preview on open — polish on the tap affordance; dismisses the card preview when the yield menu opens.

  4. fix(client): make priority-yield menu options work and collapse standing yields into a compact chip — the core interaction fix: PopoverMenu now seals onPointerDown (not just onClick) on its portal container, so a menu interaction no longer leaks through the React tree to the card's useLongPress (which was firing the card preview and leaving the menu open — the "options do nothing" bug). Standing yields collapse into one fixed-footprint amber "Auto-passing N" chip that opens the revocable list; FullControlToggle shortened to "Control" (ARIA preserves toggle semantics) on the same row.

Testing

  • PopoverMenu regression test (fails without the pointer-event seal), PriorityYieldList (5 cases), updated StackEntry tests, i18n parity across all 7 locales.
  • Tilt check-frontend green (tsc + eslint).

Notes

Two interleaved report-card commits on local main are intentionally excluded — they ship via their own ship/report-card-nudge and ship/report-picker-polish branches.

….3d)

The priority-yield auto-pass control shipped in #5132 was reachable only by
long-pressing a triggered stack entry — an undiscoverable gesture that also
collided with the mobile card-preview long-press (both fired on the same
triggered entry, so trigger cards could no longer be previewed).

Replace it with an always-visible tap button on triggered-ability entries
that toggles the existing yield menu, and restore long-press to a single
uniform meaning (inspect-and-pin) for every entry. The button sits on the
center-right edge — the one card zone clear of the status badges, chip row,
and ability overlay — and turns amber (bell-off icon) when a yield already
stands for the trigger. Pure display/dispatch: the engine still owns all
yield state via SetPriorityYield / priority_yields.
…m use (CR 117.1d)

auto_pass_recommended held frontend priority at every window whenever the player
controlled a sacrifice-for-mana permanent (Eldrazi Spawn, Krark-Clan Ironworks,
Phyrexian Altar), even when the mana could pay for nothing and the sacrifice
triggered nothing. On an opponent's turn with an uncastable hand the player was
asked for priority endlessly (repro: 8 Eldrazi Spawn, 3 sorceries in hand,
opponent trigger on the stack, legal_actions == [PassPriority]).

Narrow the issue-#544 sac-for-mana hold: it now blocks auto-pass only when the
sacrifice or its mana enables a concrete follow-up — a feasibly castable spell
(already handled by the #4388 castability rungs above), a mana-costed non-mana
activated ability (case 2), or a leaves-battlefield/dies/sacrifice trigger
(case 3, aristocrats/altars). A bare sac-for-mana with none of these auto-passes.

The narrowing lives entirely in auto_pass_recommended. has_meaningful_priority_action
is kept byte-identical (extracted into flat_actions_have_meaningful_priority +
has_activatable_sacrifice_for_mana, then recomposed) because the CR 732.5
loop-shortcut firewall depends on it still counting a sacrifice as a board change.
mana_sources.rs is untouched.

Cases 2 and 3 are conservative presence checks that err toward holding, so no real
play is ever silently auto-passed; a precise sac->activate affordability check is a
documented follow-up. 'Counter unless pay {1}' is unaffected — that payment is a
WaitingFor::UnlessPayment prompt at resolution, never a priority window (regression
test V7).

CR 605.3a + 603.6 + 603.6c + 117.1d + 118.12a.
… open

The always-visible yield control on triggered stack entries was a bare
dark icon that read as decoration and was easy to miss. Replace it with a
high-contrast labeled pill (indigo resting / amber when a yield stands)
carrying a compact 'Auto-pass' label so its purpose is legible without
hovering. Add menuButtonShort / menuButtonShortActive across all 7 locales.

Also clear the hovered/sticky card preview when the yield menu opens and
gate the hover handler while it's open, so the preview no longer lingers
on top of the menu while the player reads the options (mouseenter never
re-fires or clears as the pointer moves onto the menu's child elements).
…ing yields into a compact chip (CR 117.3d)

- PopoverMenu: seal onPointerDown as well as onClick on the portal
  container so a menu interaction never leaks through the React tree to
  the card's useLongPress (which was firing the card preview and leaving
  the menu open — the "options do nothing" bug). Bubble-phase only, so the
  capture-phase outside-click dismissal is unaffected.
- PriorityYieldList: collapse the unbounded vertical list into one
  fixed-footprint amber "Auto-passing N" chip that opens the revocable
  list inside the now-sealed PopoverMenu, keeping the action rail height
  constant regardless of yield count.
- FullControlToggle: shorten the visible label to "Control" (aria-pressed
  + descriptive aria-label preserve toggle semantics; tooltip elaborates),
  placed on the same row as the chip.
- Extract the shared YieldMuteIcon glyph; add PopoverMenu and
  PriorityYieldList regression tests (the PopoverMenu test fails without
  the pointer-event seal).
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@matthewevans matthewevans enabled auto-merge July 6, 2026 00:22
@matthewevans matthewevans added this pull request to the merge queue Jul 6, 2026
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

Parse changes introduced by this PR · 0 card(s), 0 signature(s) (baseline: main 9dfca5347204)

18 card(s) had Oracle-text changes (errata/reprint) — excluded as non-parser.
New cards in head: 1.

Merged via the queue into main with commit 0948990 Jul 6, 2026
11 checks passed
@matthewevans matthewevans deleted the ship/priority-yield-ux branch July 6, 2026 00:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant