···1+# Game Cards
2+3+This folder contains interactive game cards (Tetris, Dino, etc.).
4+5+## Implementation Requirements
6+7+When creating a new game card, follow these patterns to ensure multiple games on the same page work independently.
8+9+### 1. Container Setup
10+11+Make the game container focusable and handle keyboard events on it (not on `svelte:window`):
12+13+```svelte
14+<script lang="ts">
15+ let container: HTMLDivElement;
16+</script>
17+18+<!-- svelte-ignore a11y_no_noninteractive_tabindex a11y_no_noninteractive_element_interactions -->
19+<div
20+ bind:this={container}
21+ class="relative h-full w-full overflow-hidden outline-none"
22+ tabindex="0"
23+ role="application"
24+ aria-label="Your game name"
25+ onkeydown={handleKeyDown}
26+ onkeyup={handleKeyUp}
27+>
28+ <!-- game content -->
29+</div>
30+```
31+32+### 2. Focus on Game Start
33+34+When the game starts, focus the container so keyboard events work:
35+36+```typescript
37+function startGame() {
38+ // ... game initialization
39+ container?.focus();
40+}
41+```
42+43+### 3. Keyboard Handlers
44+45+Do NOT use `<svelte:window onkeydown={...} />` - this captures all keyboard events globally and causes all games to respond at once.
46+47+Instead, attach handlers directly to the container div. The handlers will only fire when that specific game is focused.
48+49+```typescript
50+function handleKeyDown(e: KeyboardEvent) {
51+ if (e.code === 'Space') {
52+ e.preventDefault();
53+ // handle action
54+ }
55+}
56+```
57+58+### 4. Canvas Setup
59+60+Add `touch-none` and `select-none` classes to prevent scrolling and text selection during gameplay:
61+62+```svelte
63+<canvas
64+ bind:this={canvas}
65+ class="h-full w-full touch-none select-none"
66+ ontouchstart={handleTouchStart}
67+ ontouchmove={handleTouchMove}
68+ ontouchend={handleTouchEnd}
69+></canvas>
70+```
71+72+### 5. Touch Controls
73+74+For mobile support, add touch event handlers to the canvas. Prevent default to stop page scrolling:
75+76+```typescript
77+function handleTouchStart(e: TouchEvent) {
78+ if (gameState === 'playing') {
79+ e.preventDefault();
80+ }
81+ // handle touch
82+}
83+```
84+85+## Checklist for New Game Cards
86+87+- [ ] Container has `bind:this={container}` reference
88+- [ ] Container has `tabindex="0"` for focusability
89+- [ ] Container has `role="application"` and `aria-label`
90+- [ ] Container has `outline-none` class
91+- [ ] Keyboard handlers are on container, NOT `svelte:window`
92+- [ ] `startGame()` calls `container?.focus()`
93+- [ ] Canvas has `touch-none select-none` classes
94+- [ ] Touch handlers call `e.preventDefault()` when game is active
95+- [ ] No `isTyping()` check needed (focus handles this automatically)