Add auto-tutorial, hard mode, and colorblind mode#152
Conversation
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughAdds Hard Mode (guess-validation and difficulty control) and High Contrast (accessibility color/theme) features with UI toggles, localStorage persistence, CSS overrides, analytics events, and a first-visit tutorial hook. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant SettingsUI
participant GameState
participant LocalStorage
participant Analytics
rect rgba(100,150,200,0.5)
Note over User,Analytics: Enable High Contrast
User->>SettingsUI: Click High Contrast toggle
SettingsUI->>GameState: toggleHighContrast()
GameState->>LocalStorage: save preference
GameState->>Analytics: emit 'high_contrast' setting change
GameState->>SettingsUI: apply CSS class / update UI
SettingsUI->>User: reflect new style
end
rect rgba(150,100,200,0.5)
Note over User,GameState: Submit Guess under Hard Mode
User->>SettingsUI: Submit guess
SettingsUI->>GameState: submitWord()
GameState->>GameState: checkHardMode(guess)
alt violates revealed hints
GameState->>SettingsUI: return validation error
SettingsUI->>User: show error notification
else valid
GameState->>GameState: process guess normally
GameState->>SettingsUI: update board
end
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
webapp/templates/game.html (1)
371-407: Consider adding i18n support for new toggle labels.The new toggle labels ("Hard Mode", "High Contrast", "Revealed hints must be used", "Colorblind-friendly colors") are hardcoded in English, while existing toggles use
language.config.ui.*keys for localization.This is fine for an initial implementation, but consider adding translation keys (e.g.,
language.config.ui.hard_mode,language.config.ui.high_contrast) for consistency with the existing i18n pattern.Example i18n pattern
- <p :class="{ 'opacity-50': active_row > 0 && !game_over }">Hard Mode</p> - <p class="text-xs text-neutral-500 dark:text-neutral-400" - :class="{ 'opacity-50': active_row > 0 && !game_over }">Revealed hints must be used</p> + <p :class="{ 'opacity-50': active_row > 0 && !game_over }">{{ language.config.ui.hard_mode or "Hard Mode" }}</p> + <p class="text-xs text-neutral-500 dark:text-neutral-400" + :class="{ 'opacity-50': active_row > 0 && !game_over }">{{ language.config.ui.hard_mode_desc or "Revealed hints must be used" }}</p>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@webapp/templates/game.html` around lines 371 - 407, Replace the hard-coded English labels in the template with i18n keys consistent with the existing pattern: use language.config.ui.hard_mode and language.config.ui.hard_mode_hint for the "Hard Mode" title and hint (referencing the block that reads "Hard Mode" and "Revealed hints must be used" and the reactive bindings using hardMode, active_row and game_over), and use language.config.ui.high_contrast and language.config.ui.high_contrast_hint for the "High Contrast" title and hint (referencing the block that currently calls toggle_switch('highContrast', 'toggleHighContrast()', 'High Contrast')). Update the template to output those language.* keys instead of literals and ensure the aria-label on the hardMode input also uses the i18n key; no logic changes to hardMode, toggleHighContrast(), toggle_switch, active_row or game_over are required.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@frontend/src/game.ts`:
- Around line 1494-1524: The hard-mode check in checkHardMode currently compares
raw characters with toLowerCase(), which fails when diacritics differ; modify
checkHardMode to normalize both the stored tile letter and the guess string
using the same fullNormalize helper used by updateColors (e.g., compute
normalizedGuess = fullNormalize(guess).toLowerCase() and compare against
fullNormalize(letter).toLowerCase()), then use normalizedGuess[c] for position
checks and normalizedGuess.includes(fullNormalize(letter)) for yellow checks;
ensure fullNormalize is imported/available in this module and use the normalized
forms everywhere you currently call guess.toLowerCase() or letter.toLowerCase().
---
Nitpick comments:
In `@webapp/templates/game.html`:
- Around line 371-407: Replace the hard-coded English labels in the template
with i18n keys consistent with the existing pattern: use
language.config.ui.hard_mode and language.config.ui.hard_mode_hint for the "Hard
Mode" title and hint (referencing the block that reads "Hard Mode" and "Revealed
hints must be used" and the reactive bindings using hardMode, active_row and
game_over), and use language.config.ui.high_contrast and
language.config.ui.high_contrast_hint for the "High Contrast" title and hint
(referencing the block that currently calls toggle_switch('highContrast',
'toggleHighContrast()', 'High Contrast')). Update the template to output those
language.* keys instead of literals and ensure the aria-label on the hardMode
input also uses the i18n key; no logic changes to hardMode,
toggleHighContrast(), toggle_switch, active_row or game_over are required.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 7e20f38f-d9b9-4546-91ce-80a6d90144bd
📒 Files selected for processing (4)
frontend/src/analytics.tsfrontend/src/game.tsfrontend/src/style.csswebapp/templates/game.html
…lector - Unified Easy/Normal/Hard as a segmented button group - Removed standalone "Allow any word" checkbox - Hard button grayed out mid-game with hint: "can be enabled before your first guess tomorrow" - Contextual descriptions under each difficulty level
Instead of toast notification, tapping Hard mid-game now: - Shakes the button group (reuses existing shake animation) - Shows amber warning: "Hard mode can only be enabled before your first guess" - Stays on current difficulty (no visual change)
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
webapp/templates/game.html (1)
371-410: Difficulty descriptions are not localized.The difficulty label uses the localization pattern (
{{ language.config.ui.difficulty or "Difficulty" }}), but the mode descriptions (lines 403-409) are hardcoded in English. For consistency with other UI strings, consider using localization keys.♻️ Suggested localization pattern
<p class="text-xs text-neutral-500 dark:text-neutral-400 mt-1" - v-if="allow_any_word && !hardMode">Any word accepted, even if not in the dictionary</p> + v-if="allow_any_word && !hardMode">{{ language.config.ui.easy_mode_desc or "Any word accepted, even if not in the dictionary" }}</p> <p class="text-xs text-neutral-500 dark:text-neutral-400 mt-1" - v-if="!allow_any_word && !hardMode">Guesses must be valid words from the dictionary</p> + v-if="!allow_any_word && !hardMode">{{ language.config.ui.normal_mode_desc or "Guesses must be valid words from the dictionary" }}</p> <p class="text-xs text-neutral-500 dark:text-neutral-400 mt-1" - v-if="hardMode">Revealed hints must be used in subsequent guesses</p> + v-if="hardMode">{{ language.config.ui.hard_mode_desc or "Revealed hints must be used in subsequent guesses" }}</p> <p class="text-xs text-amber-500 mt-1" - v-if="difficultyWarning">Hard mode can only be enabled before your first guess</p> + v-if="difficultyWarning">{{ language.config.ui.hard_mode_warning or "Hard mode can only be enabled before your first guess" }}</p>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@webapp/templates/game.html` around lines 371 - 410, Replace the three hardcoded mode description strings and the three explanatory lines with localized strings from language.config.ui (similar to the existing difficulty label) — update the button labels and the paragraphs that use allow_any_word, !allow_any_word, hardMode, and difficultyWarning to reference keys like language.config.ui.difficulty_easy / difficulty_normal / difficulty_hard and language.config.ui.difficulty_any_word / difficulty_valid_guesses / language.config.ui.difficulty_hard_hint / language.config.ui.difficulty_warning (or your chosen key names) so the UI uses {{ language.config.ui.<key> or "<fallback>" }} instead of literal English; keep the existing bindings (v-on:click="setDifficulty('...')", :class conditions and v-if expressions) intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@frontend/src/game.ts`:
- Around line 1494-1516: The setDifficulty method only persists hardMode to
localStorage, so selecting Easy (allow_any_word = true) is lost on reload;
update setDifficulty to also persist the easy mode flag (e.g., write
allow_any_word or an "easyMode"/"allowAnyWord" key via localStorage.setItem) and
update loadHardModePreference (or add a new loadEasyModePreference) to read that
key and restore this.allow_any_word accordingly so the Easy setting survives
page refresh; ensure the same keys are used and handle localStorage exceptions
the same way as existing hardMode persistence.
---
Nitpick comments:
In `@webapp/templates/game.html`:
- Around line 371-410: Replace the three hardcoded mode description strings and
the three explanatory lines with localized strings from language.config.ui
(similar to the existing difficulty label) — update the button labels and the
paragraphs that use allow_any_word, !allow_any_word, hardMode, and
difficultyWarning to reference keys like language.config.ui.difficulty_easy /
difficulty_normal / difficulty_hard and language.config.ui.difficulty_any_word /
difficulty_valid_guesses / language.config.ui.difficulty_hard_hint /
language.config.ui.difficulty_warning (or your chosen key names) so the UI uses
{{ language.config.ui.<key> or "<fallback>" }} instead of literal English; keep
the existing bindings (v-on:click="setDifficulty('...')", :class conditions and
v-if expressions) intact.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 41c0312e-2caf-4851-b897-f6f5dc47ef47
📒 Files selected for processing (2)
frontend/src/game.tswebapp/templates/game.html
- Tracks the highest difficulty any guess was submitted at - Can always go back up to that level (e.g., Normal→Easy→Normal is fine) - Can't go higher than max used (e.g., Easy→Normal blocked if first guess was on Easy)
- Fix: persist allow_any_word to localStorage (easy mode was reverting on reload) - Fix: remove dead toggleHardMode() (replaced by setDifficulty) - Fix: remove unused diffLevels variable - DRY: extract currentDifficultyLevel() helper (was inline ternary 3x) - Rename loadHardModePreference → loadDifficultyPreference (loads both) - Guard against hardMode + allow_any_word both true
Summary
Three quick-win features that every major Wordle competitor has and we didn't:
1. Auto-show tutorial on first visit
2. Hard mode
*when hard mode active (NYT convention)3. Colorblind / high contrast mode
Why
Market research showed these 3 features are table-stakes that NYT, wordleunlimited (10M/mo), Sanuli (77K/mo), and wordly.org (3M/mo) all have. We were the only major Wordle site missing all three.
Files changed
frontend/src/game.ts— tutorial logic, hard mode validation, high contrast toggle (+139 lines)frontend/src/style.css— high contrast color overrides (+19 lines)webapp/templates/game.html— settings toggles for hard mode + high contrast (+38 lines)Test plan
*suffix in hard modeSummary by CodeRabbit