Fix low-contrast dashed targets & elements in game themes (BL-16323) - #7985
Conversation
…(BL-16323) Several game themes used colors for the dashed drop-target rectangle (and other elements) that were the same as, or too low-contrast against, the page background, making them hard or impossible to see. Audited every element of every theme against WCAG 2.1 Level AA (4.5:1 for text, 3:1 for non-text UI / large text) and gave the failing themes their own contrasting, palette-aware overrides: - garden-path: olive draggable + white text, dark-green target outline, control button, button outline, and selected checkbox (gold was invisible on cream). - coral-reef: pale coral draggables / Check button / selected checkbox and target outline (bold coral was invisible on teal). - white-and-orange-on-blue: brighter orange chips + target outline, white checkbox outline (orange was just under AA on blue; gray was off-palette). - cherry-blossom: deepened the primary cherry so white text clears AA on the magenta chips, plus a cherry border on the white button. - pollinator: deepened the terracotta correct/selected color and the semi-transparent target outline. - blue-on-white / red-on-white: target outline overrides where needed. All eight themes now pass AA on every measured element. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…6323) A reusable skill that audits WCAG contrast across all Bloom game themes and drives an AI-curated, human-approved fix loop: - contrast.py: WCAG contrast library (named/hex/alpha colors, alpha compositing). CLI: py contrast.py <fg> <bg>. - generate_preview.py: parses gamesThemes.less, resolves the full --game-* cascade per theme, measures contrast for every element pair, and writes a self-contained HTML preview. Failing cards are outlined orange/red and offer validated fix options (each checked against ALL of an element's contrast relationships, so a fix can't break a sibling); shows before->after ratios; optionally folds in AI-curated "Recommended" picks from a JSON file, with a copy-to-clipboard approval flow. - SKILL.md: documents the canonical loop (measure -> agent curates palette-aware colors -> validate/visualize -> human approves -> apply -> re-verify) and WCAG AA thresholds. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Updates Bloom’s game theme styling to ensure dashed drop targets and other UI elements meet WCAG 2.1 AA contrast requirements, and adds a reusable “game-theme-preview” skill to audit/preview theme contrast and generate validated fix suggestions.
Changes:
- Adjusted per-theme
--game-*CSS variable overrides ingamesThemes.lessto improve contrast for draggables, targets, buttons, and checkboxes. - Added a new
game-theme-previewskill (docs + scripts) to generate an HTML preview that flags low-contrast element pairs and proposes validated fixes. - Added a small WCAG contrast utility library (
contrast.py) used by the preview generator.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
src/content/templates/template books/Games/gamesThemes.less |
Theme-specific CSS variable overrides to improve visibility/contrast of key game UI elements. |
.github/skills/game-theme-preview/SKILL.md |
Documents the workflow for generating a preview, curating fixes, and re-verifying across themes. |
.github/skills/game-theme-preview/generate_preview.py |
Implements LESS parsing, contrast checks, fix-candidate generation, and HTML preview output. |
.github/skills/game-theme-preview/contrast.py |
Provides WCAG contrast computation utilities including alpha compositing support. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
| Filename | Overview |
|---|---|
| src/content/templates/template books/Games/gamesThemes.less | Core theme fix file — addresses WCAG contrast across eight themes, but garden-path and cherry-blossom appear to have elements that still fall below 4.5:1 (missing draggable color override, header text regression), and garden-path's correct-answer button text is ~3.6:1 against its background |
| src/content/templates/template books/Games/Games.less | Adds .bloom-editable { color: var(--game-draggable-target-outline-color) } inside target elements; the outline color is designed for 3:1 non-text UI contrast but will now be used as text color (needs 4.5:1) in filled targets |
| src/BloomBrowserUI/bookEdit/toolbox/games/GameTool.tsx | Changes arrow color from hardcoded #80808080 to the target's computed borderTopColor, so the arrow matches each theme's dashed outline color; clean and safe change |
| .github/skills/game-theme-preview/contrast.py | New WCAG contrast utility library; correctly implements the WCAG 2.x relative luminance formula with alpha compositing; CLI works as documented |
| .github/skills/game-theme-preview/generate_preview.py | New theme auditing tool; parses LESS, resolves variable cascade, renders an interactive HTML preview with fix suggestions; previously flagged bugs (var() fallback handling and alpha preservation) have been addressed per the reply threads |
| .github/skills/game-theme-preview/SKILL.md | New skill documentation for the theme-preview tooling; clearly documents the measure → curate → approve → apply loop and the tool's known limitations |
Reviews (3): Last reviewed commit: "Adjust game theme colors and target-outl..." | Re-trigger Greptile
- resolve(): support var(--x, fallback) syntax so an undefined variable falls
back instead of returning None and erroring later.
- _search_one(): preserve the alpha channel of an 8-digit hex color so a
"darken/lighten" suggestion for a semi-transparent value (e.g. a translucent
target outline) is never silently made opaque; contrast is judged on the
composited result.
- parse_themes(): fail fast with a clear message if the mixin, base block, or
any theme blocks are missing, and match blocks with [^{}]* so the parser
isn't fragile to a missing newline before the closing brace.
- Document the optional curated.json third argument in the module docstring.
- Copy-output header now reminds the user to keep an issue id in each comment.
- Remove an unused local variable.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Tune the built-in game theme colors for contrast and consistency, and rework how the draggable-target outline color is handled. - Raise several theme colors to clear the 3:1 UI contrast minimum (BL-16323), e.g. brighter orange draggable/control/checkbox backgrounds and a white checkbox outline on the blue theme; refresh garden-path, cherry-blossom, coral-reef, pollinator, and arctic-dawn palettes. - Drive the target outline color entirely from each themes
andrew-polk
left a comment
There was a problem hiding this comment.
@andrew-polk reviewed 6 files and all commit messages.
Reviewable status:complete! all files reviewed, all discussions resolved (waiting on hatton).
andrew-polk
left a comment
There was a problem hiding this comment.
Reviewable status:
complete! all files reviewed, all discussions resolved (waiting on hatton).
The factory theme file had been round-tripped through the editor's "Save Factory Theme to Source" path, which rewrote each theme block alphabetically, stripped the explanatory comments, and dropped values it considered redundant with what they would derive anyway. That silently undid part of the contrast work already shipped in PR #7985 (BL-16323): white-and-orange-on-blue lost --game-control-button-bg-color and --game-checkbox-outline-color, and coral-reef lost --game-control-button-bg-color, leaving the control-button background to fall back to #ffb453 -- 2.81:1 on the blue page, under the 3:1 UI minimum that PR was specifically fixing. The editor work does not need any of this, so restore the file to master's version. Any genuine theme adjustments can be redone deliberately later, on their own card. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
[Claude Opus 4.8]
What & why (BL-16323)
The game themes were generated without checking the color used for the dashed
drop-target rectangles (and several other themed elements) against each theme's
background. In several themes that color was the same as, or too low-contrast
against, the page background, so the dashed targets were hard or impossible to see.
I audited every element of every game theme against WCAG 2.1 Level AA
(4.5:1 for text, 3:1 for non-text UI / large text) and applied palette-aware,
on-theme color overrides. All eight themes now pass AA on every measured element.
Theme fixes (
gamesThemes.less)(blue-on-white, red-on-white, and arctic-dawn already passed AA on every element and were left unchanged.)
Each override has an inline comment explaining the before/after contrast and the issue id.
New tooling:
game-theme-previewskill.github/skills/game-theme-preview/— a reusable way to audit and fix theme contrast:gamesThemes.less, resolves the full--game-*cascade per theme, measures contrast for every element pair, and writes a
self-contained HTML preview. Failing cards are outlined orange/red and offer
validated fix options — each candidate is checked against all of an element's
contrast relationships, so a fix can't pass one while breaking another — with
before→after ratios and an approval/copy flow. It can fold in AI-curated
"Recommended" picks.
colors → validate/visualize → human approves → apply → re-verify.
Notes
one-line variable overrides per theme — no image/SVG assets changed.
output/.../gamesThemes.csswill regenerate from this source.🤖 Generated with Claude Code
This change is