diff options
| author | srdusr <[email protected]> | 2025-12-04 20:58:00 +0200 |
|---|---|---|
| committer | srdusr <[email protected]> | 2025-12-04 20:58:00 +0200 |
| commit | f48fa830b10d4122d145e9822522d9b71e3f00fa (patch) | |
| tree | 3ab1696b2fae87c49c056bbd56ad1975c3b7ca5d /web/src/styles.css | |
| parent | 3d26cb457b2023d686136f1c9ee014c210951729 (diff) | |
| download | typerpunk-f48fa830b10d4122d145e9822522d9b71e3f00fa.tar.gz typerpunk-f48fa830b10d4122d145e9822522d9b71e3f00fa.zip | |
Fix the multiplayer race hand-off, fill the field, and polish controls
Standings on the end screen
- A race used to end on your own numbers alone. The end screen now shows the
whole field, filling in live as the slower racers come home.
- Two teardown paths were killing the feed it depends on. app.js tears the
race screen down before rendering the end screen, and that ran both the
inner cleanup (unsubscribing progress and finished) and the outer one
(closing the socket). Your own PlayerFinished arrives from the server a
moment after your finish callback runs, so nobody - including you - ever
got a place. The screen now marks the feed as handed off and leaves it to
the end screen, which drops it on its own teardown.
More racers
- Up to four bots per room instead of two, biased towards a fuller lobby.
With four, picking one of two speed tiers put pairs on top of each other,
so a bot now takes a pace at least 9 wpm clear of every other bot in the
room, drawn from the whole slow-to-fast span. Accuracy tracks speed rather
than being rolled independently, which had been pairing 80 wpm with 88% and
35 wpm with 99%.
Lobby
- The countdown is the whole screen for its three seconds, instead of a small
number under a large disabled button. Quick match says "Finding a race"
rather than offering a room code to share that nobody needs.
Controls
- Keyboard focus was invisible almost everywhere: only two inputs and the
theme toggle had a :focus rule, and four other controls set outline:none
outright. A :focus-visible ring now covers every interactive control,
drawn as a box-shadow so it survives those declarations.
- Disabled buttons no longer keep the filled hover state of a live primary
action, placeholders have a defined colour rather than a per-engine
default, inputs gained hover feedback and a consistent width, and pressed
controls acknowledge the press.
Diffstat (limited to 'web/src/styles.css')
| -rw-r--r-- | web/src/styles.css | 153 |
1 files changed, 151 insertions, 2 deletions
diff --git a/web/src/styles.css b/web/src/styles.css index 4131f64..8462fbf 100644 --- a/web/src/styles.css +++ b/web/src/styles.css @@ -1780,10 +1780,13 @@ body { screen, so it carried no urgency. --warning-color is used here and on the device badge, nowhere else. */ .mp-countdown { - font-size: 3rem; + font-size: 6rem; + line-height: 1; + font-weight: 700; color: var(--warning-color); text-align: center; - min-height: 4rem; + margin: 0.5rem 0 1rem; + font-family: 'JetBrains Mono', monospace; } .stat-label { @@ -2468,3 +2471,149 @@ body::-webkit-scrollbar, .app::-webkit-scrollbar, #root::-webkit-scrollbar { color: var(--primary-color); margin-bottom: 0.3rem; } + + +/* A disabled control must not still look like the live primary action. The + lobby's "Waiting for players..." button kept the filled hover state and + read as the thing to press. */ +.menu-button:disabled, +.menu-button[disabled] { + opacity: 0.55; + cursor: default; +} + +.menu-button:disabled:hover, +.menu-button[disabled]:hover { + background: none; + color: var(--sub-color); +} + +/* Where everyone placed, on the end screen after a race. A multiplayer result + used to end on your own numbers alone, with no way to see who beat you or + by how much. */ +.mp-standings { + width: 100%; + max-width: 460px; + margin: 1.75rem auto 0 auto; + display: flex; + flex-direction: column; + gap: 0.3rem; +} + +.mp-standings-heading { + font-size: 0.7rem; + text-transform: uppercase; + letter-spacing: 1px; + color: var(--sub-color); + text-align: center; + margin-bottom: 0.35rem; +} + +.mp-standings-row { + display: grid; + grid-template-columns: 1.75rem 1fr auto auto; + align-items: center; + gap: 0.75rem; + padding: 0.4rem 0.75rem; + border: 1px solid transparent; + border-radius: 6px; + font-size: 0.85rem; + color: var(--sub-color); +} + +/* Your own row is the one being looked for. */ +.mp-standings-row.me { + border-color: color-mix(in srgb, var(--primary-color) 45%, transparent); + color: var(--text-color); +} + +.mp-standings-place { + font-family: 'JetBrains Mono', monospace; + color: var(--primary-color); + text-align: center; +} + +.mp-standings-name { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.mp-standings-wpm, +.mp-standings-acc { + font-family: 'JetBrains Mono', monospace; + white-space: nowrap; +} + +/* Still typing: no place yet, so the row shows how far along they are. */ +.mp-standings-row.racing { + opacity: 0.65; +} + +.mp-standings-place { + color: var(--racer-color, var(--primary-color)); +} + +/* ---- Interactive control polish ------------------------------------- + Focus was invisible almost everywhere: only the two text inputs and the + theme toggle had a :focus rule, while .corner-icon-button, .theme-toggle, + .restart-toggle and .zen-finish-button all set `outline: none` outright. + Tabbing through the app showed nothing at all. + + A box-shadow ring rather than an outline, so it works regardless of those + existing `outline: none` declarations, and :focus-visible rather than + :focus so it appears for keyboard users without ringing every mouse + click. */ +.menu-button:focus-visible, +.corner-icon-button:focus-visible, +.theme-toggle:focus-visible, +.restart-toggle:focus-visible, +.zen-finish-button:focus-visible, +.top-rail-link:focus-visible, +.mode-popover-item:focus-visible, +.lang-item:focus-visible, +.theme-swatch:focus-visible, +.end-screen-button:focus-visible, +.account-input:focus-visible, +.custom-textarea:focus-visible { + outline: none; + box-shadow: 0 0 0 2px var(--background-color), 0 0 0 4px var(--primary-color); + border-radius: 6px; +} + +/* Placeholders were inheriting the input's own text colour at whatever + opacity the browser chose, which differed between engines. */ +.account-input::placeholder, +.custom-textarea::placeholder { + color: var(--sub-color); + opacity: 1; +} + +.account-input:hover:not(:focus), +.custom-textarea:hover:not(:focus) { + border-color: color-mix(in srgb, var(--primary-color) 45%, var(--neutral-color)); +} + +/* Inputs sat at whatever width their container gave them, which left the + multiplayer name field and its Join row on different widths. */ +.account-input { + width: 100%; + box-sizing: border-box; + transition: border-color 0.15s ease; +} + +/* A pressed control should acknowledge the press. Nothing in the app moved + on :active, so a click on a button that opens a panel elsewhere on screen + gave no feedback at the point of contact. */ +.menu-button:active:not(:disabled), +.corner-icon-button:active, +.end-screen-button:active { + transform: translateY(1px); +} + +/* Popover rows are buttons but read as list items; they need the same hover + affordance the chips and menu buttons have. */ +.mode-popover-item, +.lang-item { + transition: background-color 0.12s ease, color 0.12s ease; +} |