From 439707b1188e9750fb2c62aac05d54fede196417 Mon Sep 17 00:00:00 2001 From: Thomas Hallock Date: Sun, 28 Sep 2025 07:45:15 -0500 Subject: [PATCH] feat: add GitHub Pages Storybook deployment with dual documentation sites - Add comprehensive GitHub Actions workflow for automated Storybook deployments - Deploy apps/web Storybook to gh-pages/web subdirectory - Deploy packages/abacus-react Storybook to gh-pages/abacus-react subdirectory - Create beautiful landing page with navigation to both Storybooks - Add Component Documentation section to README with direct links - Support both PR previews and main branch deployments - Optimize build process with proper dependency management --- .claude/settings.local.json | 19 +- .github/workflows/deploy-storybook.yml | 187 ++++++++++++++ README.md | 31 +++ apps/web/src/app/arcade/page.tsx | 100 ++++---- .../src/components/EnhancedChampionArena.tsx | 166 +++++++------ apps/web/test_fullscreen_persistence.html | 228 ++++++++++++++++++ .../core/client/node/node_modules/.bin/vitest | 8 +- packages/core/client/node/node_modules/vitest | 2 +- .../typescript/node_modules/.bin/vitest | 8 +- .../client/typescript/node_modules/vitest | 2 +- 10 files changed, 623 insertions(+), 128 deletions(-) create mode 100644 .github/workflows/deploy-storybook.yml create mode 100644 apps/web/test_fullscreen_persistence.html diff --git a/.claude/settings.local.json b/.claude/settings.local.json index ed69dbed..77a293ee 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -131,7 +131,24 @@ "Bash(open http://localhost:3004/games)", "Bash(npx tsc:*)", "Bash(git rm:*)", - "Bash(git check-ignore:*)" + "Bash(git check-ignore:*)", + "Bash(open http://localhost:3002/arcade)", + "Bash(open http://localhost:3002/games)", + "Bash(open http://localhost:3000/arcade)", + "Bash(open http://localhost:3004/arcade)", + "Bash(open http://localhost:3005/arcade)", + "Bash(npx next lint:*)", + "Bash(npx next build:*)", + "Bash(git log:*)", + "Bash(gh run watch:*)", + "Bash(open http://localhost:3005/games/matching)", + "Bash(open test_fullscreen_persistence.html)", + "Bash(npx eslint:*)", + "Bash(npm run build:*)", + "Bash(awk:*)", + "Bash(gh release list:*)", + "Bash(gh release view:*)", + "Bash(git pull:*)" ], "deny": [], "ask": [] diff --git a/.github/workflows/deploy-storybook.yml b/.github/workflows/deploy-storybook.yml new file mode 100644 index 00000000..119a826a --- /dev/null +++ b/.github/workflows/deploy-storybook.yml @@ -0,0 +1,187 @@ +name: Deploy Storybooks to GitHub Pages + +on: + push: + branches: + - main + pull_request: + branches: + - main + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: "pages" + cancel-in-progress: true + +jobs: + build-and-deploy: + name: Build and Deploy Storybooks + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '18' + + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: 8.0.0 + + - name: Get pnpm store directory + shell: bash + run: | + echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV + + - name: Setup pnpm cache + uses: actions/cache@v3 + with: + path: ${{ env.STORE_PATH }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Generate Panda CSS + working-directory: apps/web + run: pnpm panda codegen + + - name: Build abacus-react package + run: pnpm --filter @soroban/abacus-react build + + - name: Build web Storybook + working-directory: apps/web + run: pnpm build-storybook --output-dir ../../storybook-web + + - name: Build abacus-react Storybook + working-directory: packages/abacus-react + run: pnpm build-storybook --output-dir ../../storybook-abacus-react + + - name: Create combined pages directory + run: | + mkdir -p pages + cp -r storybook-web pages/web + cp -r storybook-abacus-react pages/abacus-react + + # Create index page with links to both Storybooks + cat > pages/index.html << 'EOF' + + + + + + Soroban Abacus Flashcards - Storybooks + + + +
+

๐Ÿงฎ Soroban Abacus Flashcards

+

Interactive component documentation and demos

+
+ + + +
+

+ ๐Ÿ“– View on GitHub +

+
+ + + EOF + + - name: Setup Pages + if: github.ref == 'refs/heads/main' + uses: actions/configure-pages@v3 + + - name: Upload artifact + if: github.ref == 'refs/heads/main' + uses: actions/upload-pages-artifact@v2 + with: + path: ./pages + + - name: Deploy to GitHub Pages + if: github.ref == 'refs/heads/main' + id: deployment + uses: actions/deploy-pages@v2 \ No newline at end of file diff --git a/README.md b/README.md index 02d21765..96ac2923 100644 --- a/README.md +++ b/README.md @@ -283,6 +283,37 @@ python3 src/generate.py --range "1,2,5,10,20,50,100" python3 src/generate.py --range 0-99 --shuffle --seed 42 ``` +## ๐Ÿ“š Component Documentation + +Explore our comprehensive component documentation and interactive examples: + +
+ +### ๐ŸŽจ Storybook Documentation + + + + + + +
+ +๐ŸŒ Web Application
+Complete web app components
+Games โ€ข Tutorials โ€ข UI Elements +
+
+ +๐Ÿงฎ Abacus React Component
+Interactive abacus library
+Props โ€ข Stories โ€ข Examples +
+
+ +*Browse interactive demos, component APIs, and implementation examples* + +
+ ## ๐ŸŽฎ Interactive Learning Games The web format includes three immersive learning experiences designed to make soroban mastery engaging and fun: diff --git a/apps/web/src/app/arcade/page.tsx b/apps/web/src/app/arcade/page.tsx index efd1a9bc..0e818391 100644 --- a/apps/web/src/app/arcade/page.tsx +++ b/apps/web/src/app/arcade/page.tsx @@ -31,10 +31,12 @@ function ArcadeContent() {
{/* Animated background elements */}
- {/* Note: Navigation is now handled by the enhanced AppNavBar */} - - {/* Main content */} + {/* Compact Header - only shows in fullscreen */}
-
- {/* Arcade title */} -
-

- ๐ŸŸ๏ธ CHAMPION ARENA -

+ ๐ŸŸ๏ธ CHAMPION ARENA + -

- Select your champions and dive into epic mathematical battles! -

-
+

+ Select your champions and dive into epic mathematical battles! +

+
- {/* Enhanced Full-screen Champion Arena */} - {}} - className={css({ - background: 'rgba(255, 255, 255, 0.05)', - backdropFilter: 'blur(20px)', - border: '1px solid rgba(255, 255, 255, 0.1)', - boxShadow: '0 20px 40px rgba(0, 0, 0, 0.3)' - })} - /> -
+ {/* Main Champion Arena - takes remaining space */} +
+ {}} + className={css({ + width: '100%', + height: '100%', + background: 'rgba(255, 255, 255, 0.05)', + backdropFilter: 'blur(20px)', + border: '1px solid rgba(255, 255, 255, 0.1)', + boxShadow: '0 20px 40px rgba(0, 0, 0, 0.3)', + display: 'flex', + flexDirection: 'column' + })} + />
) diff --git a/apps/web/src/components/EnhancedChampionArena.tsx b/apps/web/src/components/EnhancedChampionArena.tsx index cb4ea3aa..3d4e5a52 100644 --- a/apps/web/src/components/EnhancedChampionArena.tsx +++ b/apps/web/src/components/EnhancedChampionArena.tsx @@ -116,14 +116,14 @@ function ChampionCard({ className={css({ position: 'relative', background: 'white', - rounded: '2xl', - p: '4', + rounded: { base: 'md', md: 'lg' }, + p: { base: '1', md: '1.5' }, textAlign: 'center', cursor: isDragging ? 'grabbing' : 'pointer', - border: '3px solid', + border: { base: '2px solid', md: '2px solid' }, borderColor: player.color, - width: '120px', - minWidth: '120px', + width: { base: '50px', md: '60px', lg: '70px' }, + minWidth: { base: '50px', md: '60px', lg: '70px' }, flexShrink: 0, userSelect: 'none', touchAction: 'none', @@ -219,26 +219,27 @@ function ChampionCard({
{player.emoji}
{player.name}
{zone === 'arena' ? 'READY! ๐Ÿ”ฅ' : `Level ${player.level}`}
@@ -284,13 +285,19 @@ function DroppableZone({ }) return ( -
+

{title}

@@ -301,14 +308,17 @@ function DroppableZone({ className={css({ display: 'flex', flexWrap: 'wrap', - gap: '4', + gap: { base: '1', md: '1.5' }, justifyContent: 'center', - p: '6', - rounded: id === 'arena' ? '3xl' : '2xl', - border: '3px dashed', - minH: id === 'arena' ? '64' : '32', + alignContent: 'flex-start', + p: { base: '1.5', md: '2' }, + rounded: id === 'arena' ? '2xl' : 'xl', + border: { base: '2px dashed', md: '3px dashed' }, + flex: 1, position: 'relative', - transition: 'min-height 0.3s ease', + transition: 'all 0.3s ease', + overflow: 'auto', + minHeight: { base: '30px', md: '40px' } })} > {isEmpty && ( @@ -324,17 +334,17 @@ function DroppableZone({ })} >
{isOver ? 'โœจ' : (id === 'arena' ? '๐ŸŸ๏ธ' : '๐ŸŽฏ')}

- {isOver ? `Drop to ${id === 'arena' ? 'enter the arena' : 'return to roster'}!` : subtitle} + {isOver ? `Drop to ${id === 'arena' ? 'enter' : 'return'}!` : subtitle}

)} @@ -548,40 +558,29 @@ export function EnhancedChampionArena({ onGameModeChange, onConfigurePlayer, cla
- {/* Header */} + {/* Ultra-Compact Header */}
-

- ๐ŸŸ๏ธ Champion Arena -

-

- Drag champions to experience the most tactile arena ever built! -

- - {/* Mode Indicator */} + {/* Mode Indicator - now the main header */}
- + {arenaPlayers.length === 0 ? '๐ŸŽฏ' : gameMode === 'single' ? '๐Ÿ‘ค' : gameMode === 'battle' ? 'โš”๏ธ' : '๐Ÿ†'} {arenaPlayers.length === 0 ? 'Select Champions' : gameMode === 'single' ? 'Solo Mode' : gameMode === 'battle' ? 'Battle Mode' : 'Tournament Mode'}
+ +

+ Drag champions between zones โ€ข Click to toggle +

+ {/* Champion Zones - constrained to small fixed space */}
{/* Available Champions Roster */} -
+
p.id)} strategy={rectSortingStrategy}> {availablePlayers.map(player => ( @@ -647,12 +663,17 @@ export function EnhancedChampionArena({ onGameModeChange, onConfigurePlayer, cla
{/* Arena Drop Zone */} -
+
p.id)} strategy={rectSortingStrategy}> {arenaPlayers.map(player => ( @@ -669,16 +690,21 @@ export function EnhancedChampionArena({ onGameModeChange, onConfigurePlayer, cla
- {/* Game Selector */} - + {/* Prominent Game Selector - takes remaining space */} +
+ +
{/* Drag Overlay */} diff --git a/apps/web/test_fullscreen_persistence.html b/apps/web/test_fullscreen_persistence.html new file mode 100644 index 00000000..03a114c6 --- /dev/null +++ b/apps/web/test_fullscreen_persistence.html @@ -0,0 +1,228 @@ + + + + + + Fullscreen Persistence Test + + + +

๐Ÿงช Fullscreen Persistence Test

+ +
+

Current State

+
Checking...
+
URL:
+
Fullscreen:
+
+ +
+

Manual Tests

+ + + + + +
+ +
+

Automated Test Sequence

+ +
+
+ +
+

Debug Log

+ +
+
+ + + + \ No newline at end of file diff --git a/packages/core/client/node/node_modules/.bin/vitest b/packages/core/client/node/node_modules/.bin/vitest index 99fa7ecc..f23b8576 100755 --- a/packages/core/client/node/node_modules/.bin/vitest +++ b/packages/core/client/node/node_modules/.bin/vitest @@ -6,12 +6,12 @@ case `uname` in esac if [ -z "$NODE_PATH" ]; then - export NODE_PATH="/Users/antialias/projects/soroban-abacus-flashcards/node_modules/.pnpm/vitest@1.0.0_@types+node@20.0.0_happy-dom@18.0.1_jsdom@27.0.0/node_modules/vitest/node_modules:/Users/antialias/projects/soroban-abacus-flashcards/node_modules/.pnpm/vitest@1.0.0_@types+node@20.0.0_happy-dom@18.0.1_jsdom@27.0.0/node_modules:/Users/antialias/projects/soroban-abacus-flashcards/node_modules/.pnpm/node_modules" + export NODE_PATH="/Users/antialias/projects/soroban-abacus-flashcards/node_modules/.pnpm/vitest@1.0.0_@types+node@20.0.0_@vitest+ui@3.2.4_jsdom@27.0.0/node_modules/vitest/node_modules:/Users/antialias/projects/soroban-abacus-flashcards/node_modules/.pnpm/vitest@1.0.0_@types+node@20.0.0_@vitest+ui@3.2.4_jsdom@27.0.0/node_modules:/Users/antialias/projects/soroban-abacus-flashcards/node_modules/.pnpm/node_modules" else - export NODE_PATH="/Users/antialias/projects/soroban-abacus-flashcards/node_modules/.pnpm/vitest@1.0.0_@types+node@20.0.0_happy-dom@18.0.1_jsdom@27.0.0/node_modules/vitest/node_modules:/Users/antialias/projects/soroban-abacus-flashcards/node_modules/.pnpm/vitest@1.0.0_@types+node@20.0.0_happy-dom@18.0.1_jsdom@27.0.0/node_modules:/Users/antialias/projects/soroban-abacus-flashcards/node_modules/.pnpm/node_modules:$NODE_PATH" + export NODE_PATH="/Users/antialias/projects/soroban-abacus-flashcards/node_modules/.pnpm/vitest@1.0.0_@types+node@20.0.0_@vitest+ui@3.2.4_jsdom@27.0.0/node_modules/vitest/node_modules:/Users/antialias/projects/soroban-abacus-flashcards/node_modules/.pnpm/vitest@1.0.0_@types+node@20.0.0_@vitest+ui@3.2.4_jsdom@27.0.0/node_modules:/Users/antialias/projects/soroban-abacus-flashcards/node_modules/.pnpm/node_modules:$NODE_PATH" fi if [ -x "$basedir/node" ]; then - exec "$basedir/node" "$basedir/../../../../../../node_modules/.pnpm/vitest@1.0.0_@types+node@20.0.0_happy-dom@18.0.1_jsdom@27.0.0/node_modules/vitest/vitest.mjs" "$@" + exec "$basedir/node" "$basedir/../../../../../../node_modules/.pnpm/vitest@1.0.0_@types+node@20.0.0_@vitest+ui@3.2.4_jsdom@27.0.0/node_modules/vitest/vitest.mjs" "$@" else - exec node "$basedir/../../../../../../node_modules/.pnpm/vitest@1.0.0_@types+node@20.0.0_happy-dom@18.0.1_jsdom@27.0.0/node_modules/vitest/vitest.mjs" "$@" + exec node "$basedir/../../../../../../node_modules/.pnpm/vitest@1.0.0_@types+node@20.0.0_@vitest+ui@3.2.4_jsdom@27.0.0/node_modules/vitest/vitest.mjs" "$@" fi diff --git a/packages/core/client/node/node_modules/vitest b/packages/core/client/node/node_modules/vitest index 6824fc8f..3842d620 120000 --- a/packages/core/client/node/node_modules/vitest +++ b/packages/core/client/node/node_modules/vitest @@ -1 +1 @@ -../../../../../node_modules/.pnpm/vitest@1.0.0_@types+node@20.0.0_happy-dom@18.0.1_jsdom@27.0.0/node_modules/vitest \ No newline at end of file +../../../../../node_modules/.pnpm/vitest@1.0.0_@types+node@20.0.0_@vitest+ui@3.2.4_jsdom@27.0.0/node_modules/vitest \ No newline at end of file diff --git a/packages/core/client/typescript/node_modules/.bin/vitest b/packages/core/client/typescript/node_modules/.bin/vitest index 99fa7ecc..f23b8576 100755 --- a/packages/core/client/typescript/node_modules/.bin/vitest +++ b/packages/core/client/typescript/node_modules/.bin/vitest @@ -6,12 +6,12 @@ case `uname` in esac if [ -z "$NODE_PATH" ]; then - export NODE_PATH="/Users/antialias/projects/soroban-abacus-flashcards/node_modules/.pnpm/vitest@1.0.0_@types+node@20.0.0_happy-dom@18.0.1_jsdom@27.0.0/node_modules/vitest/node_modules:/Users/antialias/projects/soroban-abacus-flashcards/node_modules/.pnpm/vitest@1.0.0_@types+node@20.0.0_happy-dom@18.0.1_jsdom@27.0.0/node_modules:/Users/antialias/projects/soroban-abacus-flashcards/node_modules/.pnpm/node_modules" + export NODE_PATH="/Users/antialias/projects/soroban-abacus-flashcards/node_modules/.pnpm/vitest@1.0.0_@types+node@20.0.0_@vitest+ui@3.2.4_jsdom@27.0.0/node_modules/vitest/node_modules:/Users/antialias/projects/soroban-abacus-flashcards/node_modules/.pnpm/vitest@1.0.0_@types+node@20.0.0_@vitest+ui@3.2.4_jsdom@27.0.0/node_modules:/Users/antialias/projects/soroban-abacus-flashcards/node_modules/.pnpm/node_modules" else - export NODE_PATH="/Users/antialias/projects/soroban-abacus-flashcards/node_modules/.pnpm/vitest@1.0.0_@types+node@20.0.0_happy-dom@18.0.1_jsdom@27.0.0/node_modules/vitest/node_modules:/Users/antialias/projects/soroban-abacus-flashcards/node_modules/.pnpm/vitest@1.0.0_@types+node@20.0.0_happy-dom@18.0.1_jsdom@27.0.0/node_modules:/Users/antialias/projects/soroban-abacus-flashcards/node_modules/.pnpm/node_modules:$NODE_PATH" + export NODE_PATH="/Users/antialias/projects/soroban-abacus-flashcards/node_modules/.pnpm/vitest@1.0.0_@types+node@20.0.0_@vitest+ui@3.2.4_jsdom@27.0.0/node_modules/vitest/node_modules:/Users/antialias/projects/soroban-abacus-flashcards/node_modules/.pnpm/vitest@1.0.0_@types+node@20.0.0_@vitest+ui@3.2.4_jsdom@27.0.0/node_modules:/Users/antialias/projects/soroban-abacus-flashcards/node_modules/.pnpm/node_modules:$NODE_PATH" fi if [ -x "$basedir/node" ]; then - exec "$basedir/node" "$basedir/../../../../../../node_modules/.pnpm/vitest@1.0.0_@types+node@20.0.0_happy-dom@18.0.1_jsdom@27.0.0/node_modules/vitest/vitest.mjs" "$@" + exec "$basedir/node" "$basedir/../../../../../../node_modules/.pnpm/vitest@1.0.0_@types+node@20.0.0_@vitest+ui@3.2.4_jsdom@27.0.0/node_modules/vitest/vitest.mjs" "$@" else - exec node "$basedir/../../../../../../node_modules/.pnpm/vitest@1.0.0_@types+node@20.0.0_happy-dom@18.0.1_jsdom@27.0.0/node_modules/vitest/vitest.mjs" "$@" + exec node "$basedir/../../../../../../node_modules/.pnpm/vitest@1.0.0_@types+node@20.0.0_@vitest+ui@3.2.4_jsdom@27.0.0/node_modules/vitest/vitest.mjs" "$@" fi diff --git a/packages/core/client/typescript/node_modules/vitest b/packages/core/client/typescript/node_modules/vitest index 6824fc8f..3842d620 120000 --- a/packages/core/client/typescript/node_modules/vitest +++ b/packages/core/client/typescript/node_modules/vitest @@ -1 +1 @@ -../../../../../node_modules/.pnpm/vitest@1.0.0_@types+node@20.0.0_happy-dom@18.0.1_jsdom@27.0.0/node_modules/vitest \ No newline at end of file +../../../../../node_modules/.pnpm/vitest@1.0.0_@types+node@20.0.0_@vitest+ui@3.2.4_jsdom@27.0.0/node_modules/vitest \ No newline at end of file