anvilsign in

collin/mahjong · 4a3e44df

Grow the discards, drop the log, and give the small buttons a name

Collin Richards · 2026-08-14 15:03 UTC · 4a3e44dfe642f65553185cacb51de2b89dc057ad · parent f8f3a70c · browse files

modifiedsrc/App.tsx+1 −3
⋯ 8 unchanged lines
99 import { Help } from './ui/Help';
1010 import { Seat } from './ui/Seat';
1111 import { Settings } from './ui/Settings';
12-import { SoundToggle } from './ui/SoundToggle';
1312 import './styles.css';
1413
1514 const SEATS: SeatId[] = [0, 1, 2, 3];
⋯ 84 unchanged lines
10099 </div>
101100
102101 <div className="lobby-extras">
103- <button className="btn ghost sound-toggle" onClick={() => setSettingsOpen(true)}>
102+ <button className="btn ghost pill" onClick={() => setSettingsOpen(true)}>
104103 ⚙ 設定 Settings
105104 </button>
106- <SoundToggle prefs={prefs} onPrefs={setPrefs} />
107105 </div>
108106 {settingsPanel}
109107 </div>
⋯ 24 unchanged lines
modifiedsrc/styles.css+17 −17
11 @import url('https://fonts.googleapis.com/css2?family=Noto+Sans+TC:wght@400;600;900&display=swap');
22
33 :root {
4+ /* Depth of each player's strip. `--h-len` is floored so a window too narrow
5+ to hold two strips shrinks the tiles rather than going negative. */
46 --depth: clamp(232px, 30vh, 330px);
5- --h-len: calc(100vw - 2 * var(--depth));
7+ --h-len: max(160px, calc(100vw - 2 * var(--depth)));
68 --v-len: 100vh;
9+ /* Largest tile a strip can hold. Edge inwards it has to fit one row of
10+ discards (0.88 tiles tall), the melds (0.86), the buttons (56px, once one
11+ is actually in there), the hand (1.71 + 6px) and the nameplate (28px),
12+ plus its own padding, gaps and margins — so 3.45 tiles plus 112px.
713
14+ Tile size otherwise follows the strip's *length*, which is why a window
15+ with less height than F11 kept full-size tiles and left the discards a
16+ sliver of a row to be cut off in. */
17+ --tile-fit: calc((var(--depth) - 112px) / 3.45);
18+
819 --felt: #0f4534;
920 --felt-2: #0a3126;
1021 --ivory: #f6f0e2;
⋯ 110 unchanged lines
121132 .slot-bottom .seat,
122133 .slot-top .seat {
123134 width: var(--h-len);
124- --tile-w: min(calc((var(--h-len) - 40px) / 18), 72px);
135+ --tile-w: min(calc((var(--h-len) - 40px) / 18), var(--tile-fit), 72px);
125136 }
126137 .slot-left .seat,
127138 .slot-right .seat {
128139 width: var(--v-len);
129- --tile-w: min(calc((var(--v-len) - 40px) / 18), 72px);
140+ --tile-w: min(calc((var(--v-len) - 40px) / 18), var(--tile-fit), 72px);
130141 }
131142 .seat.active {
132143 background: linear-gradient(to top, rgba(217, 180, 92, 0.22), transparent 70%);
⋯ 24 unchanged lines
157168 --tw: calc(var(--tile-w) * 0.62);
158169 }
159170 .tile.t-small {
160- --tw: calc(var(--tile-w) * 0.42);
171+ --tw: calc(var(--tile-w) * 0.64);
161172 }
162173 .tile.face {
163174 background-image: url('/tiles/tiles.svg');
⋯ 305 unchanged lines
469480 .last-discard,
470481 .prompt,
471482 .result,
472-.log,
473-.log,
474483 .info {
475484 display: flex;
476485 flex-direction: column;
⋯ 162 unchanged lines
639648 color: #ffb4a2;
640649 font-weight: 600;
641650 }
642-.log {
643- position: absolute;
644- bottom: 8px;
645- left: 12px;
646- font-size: 12px;
647- line-height: 1.5;
648- opacity: 0.55;
649- pointer-events: none;
650-}
651-
652651 .result {
653652 background: rgba(10, 30, 24, 0.94);
654653 border: 1px solid rgba(217, 180, 92, 0.45);
⋯ 243 unchanged lines
898897 gap: 12px;
899898 align-items: center;
900899 }
901-.sound-toggle {
900+/* Small rounded button for the things that sit under the main choices. */
901+.btn.pill {
902902 min-height: 34px;
903903 padding: 2px 14px;
904904 font-size: 13px;
⋯ 273 unchanged lines
modifiedsrc/ui/Center.tsx+0 −8
⋯ 134 unchanged lines
135135 )}
136136 <SoundToggle prefs={prefs} onPrefs={onPrefs} compact />
137137 </div>
138-
139- <div className="log">
140- {s.log.slice(0, 5).map((l, i) => (
141- <div key={i} style={{ opacity: 1 - i * 0.18 }}>
142- {l}
143- </div>
144- ))}
145- </div>
146138 </div>
147139 );
148140 }
modifiedsrc/ui/SoundToggle.tsx+1 −1
⋯ 16 unchanged lines
1717 const on = prefs.sound;
1818 return (
1919 <button
20- className={`btn ghost sound-toggle ${compact ? 'compact' : ''} ${on ? 'on' : ''}`}
20+ className={`btn ghost pill sound-toggle ${compact ? 'compact' : ''} ${on ? 'on' : ''}`}
2121 aria-pressed={on}
2222 onClick={() => {
2323 // Unlock the audio hardware here, inside the click, rather than
⋯ 13 unchanged lines