Rebuild the UI in an Apple style with spring-driven motion

Replace the look of every page (key, lobby, create, table, range, review)
with light/dark semantic colors, translucent materials, iOS-style grouped
lists and system typography. Add fluid.js, a small spring engine with
interruptible, velocity-aware animations, and use it for draggable bottom
sheets, sliding segmented controls, a custom bet slider with rubber-banding,
swipe-to-delete in the lobby, and dealt/flipped cards. Seats and cards are
now reused between renders so animations are not cut off. Honors reduced
motion, reduced transparency and increased contrast.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
agomizi1cmandClaude Opus 5.5 committed 2026-10-21 21:44:21 +09:00
1 parent d5ef2d310f
commit c3fbfdd12e
18 files changed
+4877 -1278

No files matched your search

+12 -3
View File
@@ -16,12 +16,18 @@
const value = () => inputs.map((i) => i.value).join('');
// 数字が入った枠は小さく弾む(空に戻ったら印を外す)
function markFilled() {
for (const i of inputs) i.classList.toggle('filled', Boolean(i.value));
}
function fill(digits, from) {
let i = from;
for (const d of digits) {
if (i >= inputs.length) break;
inputs[i++].value = d;
}
markFilled();
inputs[Math.min(i, inputs.length - 1)].focus();
if (value().length === 6) submit();
}
@@ -31,11 +37,13 @@
const digits = input.value.replace(/\D/g, '');
input.value = '';
if (digits) fill(digits, idx);
else markFilled();
errorEl.textContent = '';
});
input.addEventListener('keydown', (e) => {
if (e.key === 'Backspace' && !input.value && idx > 0) {
inputs[idx - 1].value = '';
markFilled();
inputs[idx - 1].focus();
e.preventDefault();
} else if (e.key === 'ArrowLeft' && idx > 0) {
@@ -68,10 +76,11 @@
location.replace(App.safeNext(next));
} catch (err) {
errorEl.textContent = err.message;
box.classList.remove('shake');
void box.offsetWidth;
box.classList.add('shake');
// 揺れと振動は同じ瞬間に(どちらも「違う」の合図)
Fluid.shake(box);
Fluid.haptic([18, 50, 18]);
inputs.forEach((i) => { i.value = ''; });
markFilled();
inputs[0].focus();
} finally {
busy = false;