fix layout a bit and add auto-advance timer

This commit is contained in:
Tobias Nauen
2026-03-06 08:40:44 +01:00
parent b66da20079
commit 18f913b978
3 changed files with 56 additions and 30 deletions

View File

@@ -53,6 +53,7 @@ export class Game {
private sampler: Sampler;
private state: GameState;
private onUpdate: () => void;
private autoAdvanceTimeout: ReturnType<typeof setTimeout> | null = null;
constructor(onUpdate: () => void) {
this.onUpdate = onUpdate;
@@ -138,6 +139,12 @@ export class Game {
}
nextQuestion(): void {
// Clear any pending auto-advance timeout
if (this.autoAdvanceTimeout) {
clearTimeout(this.autoAdvanceTimeout);
this.autoAdvanceTimeout = null;
}
this.state.currentQuestion = this.sampler.generateQuestion();
this.state.selectedAnswer = null;
this.state.selectedIndex = -1;
@@ -168,6 +175,13 @@ export class Game {
this.state.isCorrect
);
// Auto-advance after 1 second for correct answers
if (this.state.isCorrect) {
this.autoAdvanceTimeout = setTimeout(() => {
this.nextQuestion();
}, 1000);
}
this.save();
this.onUpdate();
}

View File

@@ -35,23 +35,16 @@ function render(): void {
? renderTypeBadge(q.defenderTypes[0], 'large')
: `${renderTypeBadge(q.defenderTypes[0], 'large')} / ${renderTypeBadge(q.defenderTypes[1], 'large')}`;
const optionsHtml = options.map((opt, i) => {
const optionsHtml = state.showResult ? '' : options.map((opt, i) => {
let cls = 'option-btn';
if (state.showResult) {
if (opt.value === q.correctAnswer) {
cls += ' correct';
} else if (i === state.selectedIndex && !state.isCorrect) {
cls += ' wrong';
}
} else if (i === state.selectedIndex) {
if (i === state.selectedIndex) {
cls += ' selected';
}
const shortcut = `${startKey + i}`;
const disabled = state.showResult ? 'disabled' : '';
return `
<button class="${cls}" data-index="${i}" ${disabled}>
<button class="${cls}" data-index="${i}">
<span class="option-key">${shortcut}</span>
<span class="option-label">${opt.label}</span>
</button>
@@ -65,7 +58,7 @@ function render(): void {
: `<div class="result-title">✗ Wrong</div>
<div class="explanation">${game.getExplanation()}</div>`
}
<button class="next-btn">Next Question (Enter)</button>
${!state.isCorrect ? '<button class="next-btn">Continue (Enter)</button>' : ''}
</div>
` : '';
@@ -100,12 +93,11 @@ function render(): void {
<div class="options">
${optionsHtml}
${resultHtml}
</div>
${resultHtml}
<footer class="footer">
<span class="hint">Press ${startKey}-${startKey + options.length - 1} to select • Enter to continue</span>
<span class="hint">${state.showResult && !state.isCorrect ? 'Press Enter to continue' : `Press ${startKey}-${startKey + options.length - 1} to select`}</span>
</footer>
</div>
`;

View File

@@ -163,6 +163,23 @@ body {
gap: 10px;
}
/* Result shown in place of options */
.options .result {
padding: 24px 20px;
border-radius: var(--border-radius);
animation: fadeIn 0.3s ease;
}
.result.correct {
background: rgba(74, 222, 128, 0.1);
border: 1px solid rgba(74, 222, 128, 0.3);
}
.result.wrong {
background: rgba(248, 113, 113, 0.1);
border: 1px solid rgba(248, 113, 113, 0.3);
}
.option-btn {
display: flex;
align-items: center;
@@ -544,7 +561,7 @@ body {
/* Full Type Chart */
.full-chart-section {
overflow: hidden;
width: 100%;
}
.chart-toggle-row {
@@ -577,9 +594,18 @@ body {
.full-type-chart {
display: grid;
grid-template-columns: 50px repeat(18, 1fr);
gap: 2px;
font-size: 0.65rem;
grid-template-columns: repeat(19, 1fr);
gap: 1px;
font-size: min(0.55rem, 1.8vw);
width: 100%;
max-width: 100vw;
box-sizing: border-box;
}
.chart-toggle.active {
background: var(--accent);
border-color: var(--accent);
color: white;
}
.full-chart-header-row {
@@ -587,8 +613,7 @@ body {
}
.full-chart-corner {
width: 50px;
height: 40px;
aspect-ratio: 1;
display: flex;
align-items: center;
justify-content: center;
@@ -597,12 +622,10 @@ body {
}
.full-chart-header {
width: 100%;
height: 40px;
aspect-ratio: 1;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.55rem;
font-weight: 600;
text-transform: uppercase;
border-radius: 3px;
@@ -613,34 +636,31 @@ body {
}
.full-chart-row-header {
width: 50px;
height: 40px;
aspect-ratio: 1;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.55rem;
font-weight: 600;
text-transform: uppercase;
border-radius: 3px;
}
.full-chart-cell {
width: 100%;
height: 40px;
aspect-ratio: 1;
display: flex;
align-items: center;
justify-content: center;
font-family: 'JetBrains Mono', monospace;
font-size: 0.55rem;
font-weight: 600;
border-radius: 3px;
transition: var(--transition);
}
.full-chart-cell:hover {
transform: scale(1.15);
transform: scale(1.1);
z-index: 1;
border: 1px solid rgba(255, 255, 255, 0.5);
position: relative;
}
@media (max-width: 480px) {