Hold'em dealer: 55 polish rounds, one merge #101
@@ -163,7 +163,7 @@
|
||||
<template id="seatTemplate">
|
||||
<div class="seat" draggable="true">
|
||||
<div class="seatChairNumber"></div>
|
||||
<button class="dealerChip" title="Make this seat the dealer button">D</button>
|
||||
<button class="dealerChip" type="button" title="Make this seat the dealer button">D</button>
|
||||
<span class="blindBadge sbBadge">SB</span>
|
||||
<span class="blindBadge bbBadge">BB</span>
|
||||
<div class="seatPuckName"></div>
|
||||
|
||||
@@ -591,7 +591,6 @@ button,
|
||||
font-size: 0.68rem;
|
||||
cursor: pointer;
|
||||
z-index: 2;
|
||||
opacity: 0.32;
|
||||
transition: opacity 0.15s ease;
|
||||
/* A dealer puck should look like a puck — small, sitting on the rim of its seat.
|
||||
But tapping it hands the button to that seat and re-posts the blinds, and 22px
|
||||
@@ -622,16 +621,40 @@ button,
|
||||
left: -18px;
|
||||
}
|
||||
|
||||
.dealerChip:focus-visible {
|
||||
opacity: 1;
|
||||
/* A poker table has one dealer button. This one drew nine.
|
||||
|
||||
Every seat carried a puck — the button's, and eight ghosts at 0.32 opacity that
|
||||
were there to be pressed. Measured on a nine-seat table: eight pale discs, all
|
||||
eight showing the letter D, one of them real. Finding the button meant comparing
|
||||
nine identical shapes for the one that's gold, when it should be the only thing
|
||||
of its kind on the felt. The ghosts also sat on top of their neighbours: every
|
||||
remaining "something important is covered" offender on a crowded table was a
|
||||
seat covered by the seat-next-door's ghost puck.
|
||||
|
||||
So a seat that doesn't have the button doesn't draw one. The affordance is still
|
||||
there — hovering a seat fades its slot in, which is a preview of where the button
|
||||
would go — and on touch, where there is no hover, "Give the button" has always
|
||||
been in the seat's long-press menu. Keyboard reaches it by focus.
|
||||
|
||||
pointer-events matters as much as the opacity: an invisible puck that still takes
|
||||
taps would be worse than a visible one. */
|
||||
.dealerChip:not(.active) {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@media (hover: hover) {
|
||||
.seat:hover .dealerChip {
|
||||
opacity: 1;
|
||||
.seat:hover .dealerChip:not(.active) {
|
||||
opacity: 0.5;
|
||||
pointer-events: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.dealerChip:not(.active):focus-visible {
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.dealerChip.active {
|
||||
background: radial-gradient(circle at 35% 30%, #ffe9a8, #f5d547 55%, #cba428 100%);
|
||||
border-color: #a9782f;
|
||||
|
||||
@@ -174,8 +174,18 @@ const Render = {
|
||||
node.querySelector(".seatChairNumber").textContent = index + 1;
|
||||
|
||||
const dealerChip = node.querySelector(".dealerChip");
|
||||
dealerChip.classList.toggle("active", index === dealerIndex);
|
||||
const hasButton = index === dealerIndex;
|
||||
dealerChip.classList.toggle("active", hasButton);
|
||||
dealerChip.classList.toggle("hidden", !!this.state.dedicatedDealer);
|
||||
// Every one of these announced itself as "D", so a screen reader heard a row
|
||||
// of nine identical buttons and couldn't tell which seat held the real one.
|
||||
// The label now says whose it is, or what pressing it would do.
|
||||
const who = (player.name || "").trim() || `seat ${index + 1}`;
|
||||
const chipLabel = hasButton
|
||||
? `${who} has the dealer button`
|
||||
: `Give the dealer button to ${who}`;
|
||||
dealerChip.setAttribute("aria-label", chipLabel);
|
||||
dealerChip.title = chipLabel;
|
||||
// Tapping the puck is the same act as "Give the button" in the seat menu,
|
||||
// so it goes through the same hook — otherwise this one path would move
|
||||
// the button without moving the blinds that follow it.
|
||||
|
||||
@@ -514,6 +514,34 @@ const LayoutAudit = {
|
||||
return { name: "a seat's centre belongs to that seat", offenders };
|
||||
},
|
||||
|
||||
// A poker table has one dealer button. Nine pucks all showing "D", one of them
|
||||
// gold, turns the most-read marker on the felt into a spot-the-difference — and
|
||||
// a screen reader heard nine buttons named "D" with nothing to tell them apart.
|
||||
// Both halves are checked here: what's drawn, and what it announces itself as.
|
||||
oneDealerButton() {
|
||||
const chips = [...document.querySelectorAll(".dealerChip")];
|
||||
const shown = chips.filter(chip => {
|
||||
const style = getComputedStyle(chip);
|
||||
return style.display !== "none" && style.visibility !== "hidden" &&
|
||||
parseFloat(style.opacity) > 0.05;
|
||||
});
|
||||
const offenders = [];
|
||||
|
||||
if (shown.length > 1) {
|
||||
offenders.push(`${shown.length} dealer buttons drawn on the felt at once`);
|
||||
}
|
||||
|
||||
const labels = chips.map(chip => chip.getAttribute("aria-label") || chip.textContent.trim());
|
||||
const duplicated = labels.filter((label, i) => labels.indexOf(label) !== i);
|
||||
if (duplicated.length) {
|
||||
offenders.push(
|
||||
`${duplicated.length + 1} dealer buttons announce themselves as "${duplicated[0]}"`
|
||||
);
|
||||
}
|
||||
|
||||
return { name: "the felt shows one dealer button", offenders };
|
||||
},
|
||||
|
||||
// ---- Runner ----
|
||||
|
||||
runAll(options = {}) {
|
||||
@@ -527,6 +555,7 @@ const LayoutAudit = {
|
||||
this.horizontalOverflow(),
|
||||
this.fieldFontSize(),
|
||||
this.seatOwnership(),
|
||||
this.oneDealerButton(),
|
||||
];
|
||||
if (options.includeTouchTargets) checks.push(this.touchTargets(options.minimumTarget));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user