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:
1 parent
d5ef2d310f
commit
c3fbfdd12e
18 files changed
+4877
-1278
No files matched your search
+12
-10
@@ -16,8 +16,8 @@
|
||||
const timerInput = $('timer');
|
||||
const intervalInput = $('interval');
|
||||
const scheduleEl = $('schedule');
|
||||
const modeHint = $('mode-hint');
|
||||
const cpuOptions = $('cpu-options');
|
||||
const intervalRow = $('interval-row');
|
||||
const blindHint = $('blind-hint');
|
||||
const errorEl = $('error');
|
||||
const submitBtn = $('submit');
|
||||
@@ -49,7 +49,7 @@
|
||||
const stack = int(stackInput);
|
||||
const bb = int(bbInput);
|
||||
if (blindsTouched && stack > 0 && bb > 0) {
|
||||
blindHint.innerHTML = `開始スタック = ${Math.floor(stack / bb)} BB ・ <a href="#" id="reset-blinds" class="link-gold">おすすめに戻す</a>`;
|
||||
blindHint.innerHTML = `開始スタック = ${Math.floor(stack / bb)} BB ・ <a href="#" id="reset-blinds" class="link">おすすめに戻す</a>`;
|
||||
} else {
|
||||
blindHint.textContent = 'スタックに合わせて自動設定(BB ≒ スタックの1/100)';
|
||||
}
|
||||
@@ -60,6 +60,7 @@
|
||||
const bb = int(bbInput);
|
||||
const on = timerInput.checked;
|
||||
intervalInput.disabled = !on;
|
||||
setOpen(intervalRow, on);
|
||||
scheduleEl.hidden = !on || !(sb > 0 && bb > sb);
|
||||
if (scheduleEl.hidden) return;
|
||||
const mins = int(intervalInput) > 0 ? int(intervalInput) : 0;
|
||||
@@ -68,18 +69,17 @@
|
||||
.join('');
|
||||
}
|
||||
|
||||
const MODE_HINTS = {
|
||||
chips: '実物のカードで遊び、サイトはチップだけを管理。ショーダウンの勝者はホストが選ぶ',
|
||||
friends: '各自のスマホに手札が配られ、勝敗とポットの分配は自動',
|
||||
cpu: 'CPU と対戦(友達も空いている席に参加できる)。カードの配布・勝敗の判定は自動',
|
||||
review: 'あなたと CPU だけで対戦(友達は入れない)。ハンドごとにハンドレンジの色・行動の点数を表示し、対局全体の成績も振り返れる',
|
||||
};
|
||||
const radioValue = (name) => (form.querySelector(`input[name="${name}"]:checked`) || {}).value;
|
||||
|
||||
// 行の開け閉め(高さはばねで変わる)。閉じている間はフォーカスも届かないようにする
|
||||
function setOpen(el, open) {
|
||||
el.classList.toggle('collapsed', !open);
|
||||
el.inert = !open;
|
||||
}
|
||||
|
||||
function updateMode() {
|
||||
const mode = radioValue('mode');
|
||||
modeHint.textContent = MODE_HINTS[mode] || '';
|
||||
cpuOptions.hidden = mode !== 'cpu' && mode !== 'review';
|
||||
setOpen(cpuOptions, mode === 'cpu' || mode === 'review');
|
||||
}
|
||||
|
||||
function refresh() {
|
||||
@@ -110,6 +110,8 @@
|
||||
intervalInput.addEventListener('input', refresh);
|
||||
form.querySelectorAll('input[type="radio"]').forEach((el) => el.addEventListener('change', refresh));
|
||||
$('reroll').addEventListener('click', suggestName);
|
||||
Fluid.Segmented(form.querySelector('.segmented.numbers'));
|
||||
Fluid.navBar($('nav'), $('large-title'));
|
||||
|
||||
function validate() {
|
||||
const name = nameInput.value.trim();
|
||||
|
||||
Reference in new issue
Block a user