Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions battle-tanks/scripts/app.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions docs/adr/0008-experience-theming-system.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,19 @@ updates, cross-tab synchronization, browser theme color, public API, and the
`arcade:theme` event. CSS is layered into experience tokens, shared components,
page layouts, and game-specific rendering.

Theme-owned game rendering values are exposed as CSS custom properties in the
theme styles. Canvas code reads that interface from computed styles and must
not select an experience or contain per-theme palettes. A new experience can
therefore implement game-specific tokens alongside its shared tokens without
requiring a game-code branch.

This contract applies to every modern game. DOM-rendered games (Tic-tac-toe,
Sudoku, and Minesweeper) consume the CSS cascade directly. Canvas-rendered games
(Pong and Battle Tanks) expose scoped `.game-pong` and `.game-battle-tanks`
token interfaces and refresh their computed values on `arcade:theme`. Player
colors and synchronized gameplay colors are game state, not experience-theme
palettes, and remain independent so matches render consistently for all peers.

Layout themes may change shell width, grids, panel placement, typography,
spacing, borders, and decoration. They must preserve semantic DOM order,
keyboard focus order, game rules, required controls, and responsive access to
Expand Down
6 changes: 6 additions & 0 deletions styles/modern-game.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 26 additions & 0 deletions tests/appearance-system.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,32 @@ test('alternative themes customize shared shell and game layouts', () => {
assert.match(games, /box-shadow:none/);
});

test('no modern game selects an experience theme or embeds an experience palette', () => {
const gameScripts = [
'pong/scripts/app.js',
'tictactoe/scripts/app.js',
'battle-tanks/scripts/app.js',
'Sudoku/scripts/app.js',
'Minesweeper/scripts/app.js'
];

for (const file of gameScripts) {
const source = fs.readFileSync(file, 'utf8');
assert.doesNotMatch(source, /dataset\.arcadeTheme/, `${file} must not select an experience theme`);
assert.doesNotMatch(source, /\bpalettes?\s*=\s*\{/, `${file} must not embed an experience palette`);
assert.doesNotMatch(source, /(?:playful|cabinet|calm)\s*:\s*\{/, `${file} must not branch on registered themes`);
}
});

test('theme styles own the Battle Tanks canvas palette', () => {
for (const token of ['sky-top', 'sky-bottom', 'terrain', 'terrain-edge', 'barrier', 'barrier-line', 'ink', 'active', 'aim']) {
assert.match(games, new RegExp(`--battle-${token}:`));
}
const battleTanks = fs.readFileSync('battle-tanks/scripts/app.js', 'utf8');
assert.match(battleTanks, /getComputedStyle\(arena\)/);
assert.doesNotMatch(battleTanks, /const palettes=/);
});

test('cabinet light mode keeps dialog text dark without changing topbar ink', () => {
assert.match(shared, /data-arcade-theme="cabinet"\]\[data-color-mode="light"\] \.arcade-dialog \{ --arcade-nav-ink:#382c42; \}/);
assert.doesNotMatch(shared, /data-color-mode="light"\] \{[^}]*--arcade-nav-ink:/);
Expand Down
Loading