Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
65f201cdfd | ||
|
|
d297c1a2c9 | ||
|
|
f0cfd24647 |
@@ -153,6 +153,12 @@
|
|||||||
<div id="chipLegendList"></div>
|
<div id="chipLegendList"></div>
|
||||||
<button id="addChipColorBtn" class="holdemBtn holdemBtnSmall">+ Add chip color</button>
|
<button id="addChipColorBtn" class="holdemBtn holdemBtnSmall">+ Add chip color</button>
|
||||||
<p class="fieldHint">Give each chip color a value, then count chips on a seat instead of typing a total.</p>
|
<p class="fieldHint">Give each chip color a value, then count chips on a seat instead of typing a total.</p>
|
||||||
|
|
||||||
|
<div id="colourUp" hidden>
|
||||||
|
<h3 class="panelSubhead">Stacks in chips</h3>
|
||||||
|
<dl id="colourUpList" class="colourUpList"></dl>
|
||||||
|
<p class="fieldHint">The fewest chips that make each stack — for colouring up, or counting one out.</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|||||||
@@ -510,13 +510,53 @@ button,
|
|||||||
|
|
||||||
/* Sitting out, not gone: still a person the dealer may need to deal back in, so
|
/* Sitting out, not gone: still a person the dealer may need to deal back in, so
|
||||||
the name has to stay readable rather than fading almost to the felt. */
|
the name has to stay readable rather than fading almost to the felt. */
|
||||||
|
/* Out of the hand, still readable.
|
||||||
|
|
||||||
|
Both of these used to fade the whole seat — opacity 0.5 folded, 0.58 sitting out —
|
||||||
|
and opacity on a box fades the text you still have to read along with the box you
|
||||||
|
wanted to push back. Measured off the rendered pixels at 11.5px text, where AA asks
|
||||||
|
for 4.5:1:
|
||||||
|
|
||||||
|
live name 13.28 stack 4.75
|
||||||
|
folded name 4.75 stack 2.22
|
||||||
|
sat out name 7.00 stack 3.22
|
||||||
|
|
||||||
|
A folded player's stack is not decoration. It's what they'll have next hand and the
|
||||||
|
answer to "how much has Ben got?", and at 2.22:1 it was barely there.
|
||||||
|
|
||||||
|
So the box recedes and the text doesn't: a flatter, darker background and a muted
|
||||||
|
border say "not in this hand", while the name and the stack keep colours that
|
||||||
|
measure. The folded seat keeps its red border and the line through the name, which
|
||||||
|
is the part that actually names the state. */
|
||||||
|
.seat.seatInactive,
|
||||||
|
.seat.seatFolded {
|
||||||
|
background: linear-gradient(160deg, #232323, #171717);
|
||||||
|
border-color: rgba(255, 255, 255, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A folded seat already says so twice — a red border and a line through the name — but
|
||||||
|
a seat that's sitting out said it only by being faint, and taking the faintness away
|
||||||
|
took the whole signal with it. A dashed edge is the same thing an empty chair wears,
|
||||||
|
which is right: neither is in this hand. The name and the stack tell them apart. */
|
||||||
.seat.seatInactive {
|
.seat.seatInactive {
|
||||||
opacity: 0.58;
|
border-style: dashed;
|
||||||
|
border-color: rgba(255, 255, 255, 0.22);
|
||||||
|
}
|
||||||
|
|
||||||
|
.seat.seatInactive .seatPuckName,
|
||||||
|
.seat.seatFolded .seatPuckName {
|
||||||
|
color: #b0b0b0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.seat.seatInactive .seatPuckStack,
|
||||||
|
.seat.seatFolded .seatPuckStack,
|
||||||
|
.seat.seatInactive .seatPuckTotal,
|
||||||
|
.seat.seatFolded .seatPuckTotal {
|
||||||
|
color: #8f8f8f;
|
||||||
}
|
}
|
||||||
|
|
||||||
.seat.seatFolded {
|
.seat.seatFolded {
|
||||||
border-color: rgba(224, 123, 123, 0.4);
|
border-color: rgba(224, 123, 123, 0.4);
|
||||||
opacity: 0.5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.seat.seatFolded .seatPuckName {
|
.seat.seatFolded .seatPuckName {
|
||||||
@@ -1105,6 +1145,30 @@ button,
|
|||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Each stack and the chips that make it, laid out like the shortcut legend below —
|
||||||
|
the thing being named on one line, the answer under it, so a dealer with a rack in
|
||||||
|
one hand reads down rather than across. */
|
||||||
|
.colourUpList {
|
||||||
|
margin: 0.2rem 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.colourUpWho {
|
||||||
|
color: #ddd;
|
||||||
|
font-size: 0.78rem;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
}
|
||||||
|
|
||||||
|
.colourUpChips {
|
||||||
|
margin: 0 0 0.45rem;
|
||||||
|
color: #9fb8a6;
|
||||||
|
font-size: 0.74rem;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
}
|
||||||
|
|
||||||
|
.colourUpChips:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* The shortcut legend. A touch device has no keys to press, so it doesn't get a panel
|
/* The shortcut legend. A touch device has no keys to press, so it doesn't get a panel
|
||||||
telling it about them — the same pointer question the touch-target rules ask. */
|
telling it about them — the same pointer question the touch-target rules ask. */
|
||||||
@media (pointer: coarse) {
|
@media (pointer: coarse) {
|
||||||
@@ -2169,11 +2233,12 @@ body.hasActionBar #holdemSidebar {
|
|||||||
|
|
||||||
/* The undo pill's key, inline rather than pinned to a corner — see actionBar.js. */
|
/* The undo pill's key, inline rather than pinned to a corner — see actionBar.js. */
|
||||||
.actionUndoKey {
|
.actionUndoKey {
|
||||||
|
/* See .actionKey below for why these are not fainter. */
|
||||||
margin-left: 0.4rem;
|
margin-left: 0.4rem;
|
||||||
padding: 0 0.25rem;
|
padding: 0 0.25rem;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
border: 1px solid currentColor;
|
border: 1px solid currentColor;
|
||||||
opacity: 0.55;
|
opacity: 0.75;
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
font-size: 0.6rem;
|
font-size: 0.6rem;
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
@@ -2181,6 +2246,10 @@ body.hasActionBar #holdemSidebar {
|
|||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* A key hint is small — 9.6px — so AA asks 4.5:1 of it, and at the opacity these used
|
||||||
|
to carry they measured 2.97 to 3.33 against their buttons. That's the same fault as
|
||||||
|
the folded seats above: a fade chosen for looks pushing text a dealer is meant to
|
||||||
|
read under the threshold. They're still quieter than the label they sit beside. */
|
||||||
.actionKey {
|
.actionKey {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 5px;
|
top: 5px;
|
||||||
@@ -2188,7 +2257,7 @@ body.hasActionBar #holdemSidebar {
|
|||||||
padding: 0 0.25rem;
|
padding: 0 0.25rem;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
border: 1px solid currentColor;
|
border: 1px solid currentColor;
|
||||||
opacity: 0.4;
|
opacity: 0.75;
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
font-size: 0.6rem;
|
font-size: 0.6rem;
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
|
|||||||
@@ -667,6 +667,49 @@ const Render = {
|
|||||||
|
|
||||||
list.appendChild(row);
|
list.appendChild(row);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.renderColourUp();
|
||||||
|
},
|
||||||
|
|
||||||
|
// Each stack as the chips that make it.
|
||||||
|
//
|
||||||
|
// The legend has only ever read chips *into* an amount — counting what's in front
|
||||||
|
// of somebody. Colouring up at the end of a level is the same question backwards,
|
||||||
|
// and it's the one the dealer has to answer with a rack in one hand: $205 is four
|
||||||
|
// fifties and a five. So is counting a stack out for a player who's leaving.
|
||||||
|
//
|
||||||
|
// Only when there's a legend to work from and a stack to break down; a table that
|
||||||
|
// never set its chip colours up gets nothing, which is what it had before.
|
||||||
|
renderColourUp() {
|
||||||
|
const host = document.getElementById("colourUp");
|
||||||
|
const list = document.getElementById("colourUpList");
|
||||||
|
if (!host || !list) return;
|
||||||
|
|
||||||
|
const legend = this.state.chipLegend || [];
|
||||||
|
const rows = this.state.seats
|
||||||
|
.map((player, index) => ({ player, index }))
|
||||||
|
.filter(({ player }) => Betting.round(Number(player.stack) || 0) > 0)
|
||||||
|
.map(({ player, index }) => ({
|
||||||
|
name: HoldemState.displayName(player, index),
|
||||||
|
stack: Betting.round(Number(player.stack) || 0),
|
||||||
|
chips: Money.formatChipBreakdown(Number(player.stack) || 0, legend),
|
||||||
|
}))
|
||||||
|
.filter(row => row.chips);
|
||||||
|
|
||||||
|
host.hidden = rows.length === 0;
|
||||||
|
if (host.hidden) return;
|
||||||
|
|
||||||
|
list.innerHTML = "";
|
||||||
|
rows.forEach(row => {
|
||||||
|
const term = document.createElement("dt");
|
||||||
|
term.className = "colourUpWho";
|
||||||
|
term.textContent = `${row.name} — ${Money.format(row.stack)}`;
|
||||||
|
const detail = document.createElement("dd");
|
||||||
|
detail.className = "colourUpChips";
|
||||||
|
detail.textContent = row.chips;
|
||||||
|
list.appendChild(term);
|
||||||
|
list.appendChild(detail);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// ---- Pot breakdown ----
|
// ---- Pot breakdown ----
|
||||||
|
|||||||
+49
-8
@@ -349,6 +349,16 @@ const LayoutAudit = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Every element between this one and the document, so an opacity set on a
|
||||||
|
// container can be seen from the text inside it.
|
||||||
|
*ancestors(el) {
|
||||||
|
let node = el.parentElement;
|
||||||
|
while (node) {
|
||||||
|
yield node;
|
||||||
|
node = node.parentElement;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
contrast({ minimum = 4.5, largeMinimum = 3, selector = null } = {}) {
|
contrast({ minimum = 4.5, largeMinimum = 3, selector = null } = {}) {
|
||||||
const offenders = [];
|
const offenders = [];
|
||||||
const unmeasured = [];
|
const unmeasured = [];
|
||||||
@@ -358,19 +368,50 @@ const LayoutAudit = {
|
|||||||
: [...document.querySelectorAll("*")];
|
: [...document.querySelectorAll("*")];
|
||||||
|
|
||||||
nodes.forEach(el => {
|
nodes.forEach(el => {
|
||||||
if (el.children.length > 0) return; // leaf text only
|
// An element's *own* text, not its descendants' — they get measured on
|
||||||
const text = (el.textContent || "").trim();
|
// their own turn, against their own colour.
|
||||||
|
//
|
||||||
|
// This used to be "leaf elements only", which quietly stopped measuring
|
||||||
|
// anything the moment a child was added to it. The undo control went that
|
||||||
|
// way the day a <kbd> was appended to it: its label became invisible to
|
||||||
|
// this check, with no sign that anything had changed.
|
||||||
|
const text = [...el.childNodes]
|
||||||
|
.filter(node => node.nodeType === 3)
|
||||||
|
.map(node => node.textContent)
|
||||||
|
.join(" ")
|
||||||
|
.trim();
|
||||||
if (!text) return;
|
if (!text) return;
|
||||||
const rect = el.getBoundingClientRect();
|
const rect = el.getBoundingClientRect();
|
||||||
if (rect.width === 0 || rect.height === 0) return;
|
if (rect.width === 0 || rect.height === 0) return;
|
||||||
const style = getComputedStyle(el);
|
const style = getComputedStyle(el);
|
||||||
if (style.visibility === "hidden" || style.display === "none") return;
|
if (style.visibility === "hidden" || style.display === "none") return;
|
||||||
if (parseFloat(style.opacity) < 0.99) return; // faded on purpose
|
// Faded text used to be skipped outright as "faded on purpose", and that
|
||||||
// Decoration is exempt by definition: the watermark on the felt is meant
|
// exemption hid a real fault: the folded and sat-out seats dimmed their
|
||||||
// to be barely there, and holding it to a reading threshold would mean
|
// whole box with opacity, so a folded player's stack measured 2.22:1 at
|
||||||
// making it not a watermark. Marked aria-hidden so screen readers skip it
|
// 11.5px and this check never looked at it. Something invisible is still
|
||||||
// too, which is the same claim expressed where it also does some good.
|
// exempt — there's nothing to read at zero — but anything in between is
|
||||||
if (el.closest("[aria-hidden='true']")) return;
|
// reported as unmeasured rather than passed over in silence, because a
|
||||||
|
// number nobody checked is not the same as a number that's fine.
|
||||||
|
const opacity = parseFloat(style.opacity);
|
||||||
|
if (opacity <= 0.02) return;
|
||||||
|
const faded = opacity < 0.99 ||
|
||||||
|
[...this.ancestors(el)].some(a => parseFloat(getComputedStyle(a).opacity) < 0.99);
|
||||||
|
if (faded) {
|
||||||
|
unmeasured.push(`${this.describe(el)} :: faded (opacity ${opacity}), contrast not checked`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// aria-hidden used to exempt text here, on the grounds that decoration
|
||||||
|
// marked for screen readers was decoration for everyone. Those are two
|
||||||
|
// different questions and the answer differs: the bet chips on the felt are
|
||||||
|
// aria-hidden because their amounts are already announced by the seat and
|
||||||
|
// the action bar, and repeating them would be noise — but they are exactly
|
||||||
|
// what a sighted dealer reads the felt for, and this check had stopped
|
||||||
|
// looking at them. Hiding something from one audience is not a claim about
|
||||||
|
// whether the other audience can read it.
|
||||||
|
//
|
||||||
|
// Nothing is exempt now. If something genuinely decorative turns up, it
|
||||||
|
// should say so in its own words rather than borrowing an attribute that
|
||||||
|
// means something else.
|
||||||
|
|
||||||
const fgRaw = this.parseColour(style.color);
|
const fgRaw = this.parseColour(style.color);
|
||||||
if (!fgRaw) return;
|
if (!fgRaw) return;
|
||||||
|
|||||||
Reference in New Issue
Block a user