From c1d0105d12bdc613476fa298d18bfe10c2a50a39 Mon Sep 17 00:00:00 2001 From: JoshHeaps Date: Sun, 13 Sep 2026 22:41:06 -0600 Subject: [PATCH] Answer the press instead of eating it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The card picker greys out a card that is already dealt and hangs the reason off a `title`. Measured on an iPhone with three hands out: seven of the fifty-two were dead, none of them could take focus, and tapping one changed nothing at all — no toast, no text, not a byte of DOM. The tool's answer to "who has the ace of spades?" existed and was reachable only with a mouse. The header's two buttons were the same, on a new dealer's first screen, and Export CSV was greyed out with no explanation written anywhere. `disabled` is the wrong attribute whenever there is something to say: it drops the control out of the tab order, so a screen reader never lands on it to hear the description, and it eats the tap on a touch screen, where the hover that would have shown the `title` does not exist. `aria-disabled` announces the same state and leaves the control reachable, so one capture listener can turn the press into a sentence — in a toast, or inside a sheet that is standing on top of the toast. It paid for itself in the picker's keyboard too. The arrows hunted past dealt cards because a `disabled` button cannot hold focus, and the hunting did the exact thing the grid's no-wrap rule was written to prevent: Right from A-spades over a dealt A-hearts landed on A-diamonds, so the column shifted and the next press of Down walked a different suit. A cell that can hold focus needs no hunting, and the APG asks for that inside a composite widget anyway. The line that answers is one line by measurement, not by taste. Its box is 318px on a Galaxy S8 at 20px of root text; the first wording drew 332px and wrapped, shoving fifty-two targets 21px down mid-tap, and twenty-four capital Ws draw 434px whatever the wording, so the box is what holds. Two things the sweep found on the way. It opened the card picker by un-hiding an overlay whose grid had never been painted, so for its whole life it audited an empty sheet; it now opens it the way a dealer does, with cards out and the answer showing. And the slot buttons above the grid were named to a screen reader by the em dash they draw when empty. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_015bnp7xKUPFFSpwkYNFaPgb --- JoshHeaps.Net/Pages/Casino/TexasHoldem.cshtml | 9 +- JoshHeaps.Net/wwwroot/css/casino/holdem.css | 63 +++- .../wwwroot/js/casino/holdem/cardPicker.js | 66 +++-- .../wwwroot/js/casino/holdem/feedback.js | 80 ++++- .../wwwroot/js/casino/holdem/main.js | 7 + .../wwwroot/js/casino/holdem/render.js | 26 +- tests/holdem/load.js | 9 + tests/holdem/nativeControls.test.js | 27 +- tests/holdem/runUiAudit.js | 20 +- tests/holdem/theKeyboardInASheet.test.js | 51 +++- tests/holdem/theUnansweredPress.test.js | 279 ++++++++++++++++++ tests/holdem/uiAudit.js | 20 ++ 12 files changed, 594 insertions(+), 63 deletions(-) create mode 100644 tests/holdem/theUnansweredPress.test.js diff --git a/JoshHeaps.Net/Pages/Casino/TexasHoldem.cshtml b/JoshHeaps.Net/Pages/Casino/TexasHoldem.cshtml index e8fdbd3..223265b 100644 --- a/JoshHeaps.Net/Pages/Casino/TexasHoldem.cshtml +++ b/JoshHeaps.Net/Pages/Casino/TexasHoldem.cshtml @@ -740,7 +740,10 @@