your personal website on atproto - mirror blento.app
at main 95 lines 2.5 kB view raw view rendered
1# Game Cards 2 3This folder contains interactive game cards (Tetris, Dino, etc.). 4 5## Implementation Requirements 6 7When creating a new game card, follow these patterns to ensure multiple games on the same page work independently. 8 9### 1. Container Setup 10 11Make 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 34When the game starts, focus the container so keyboard events work: 35 36```typescript 37function startGame() { 38 // ... game initialization 39 container?.focus(); 40} 41``` 42 43### 3. Keyboard Handlers 44 45Do NOT use `<svelte:window onkeydown={...} />` - this captures all keyboard events globally and causes all games to respond at once. 46 47Instead, attach handlers directly to the container div. The handlers will only fire when that specific game is focused. 48 49```typescript 50function handleKeyDown(e: KeyboardEvent) { 51 if (e.code === 'Space') { 52 e.preventDefault(); 53 // handle action 54 } 55} 56``` 57 58### 4. Canvas Setup 59 60Add `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 74For mobile support, add touch event handlers to the canvas. Prevent default to stop page scrolling: 75 76```typescript 77function 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)