From a61309e9ed7987c8a196fe0981028465cd1db05d Mon Sep 17 00:00:00 2001 From: evanmcfarland Date: Mon, 15 Dec 2025 11:35:04 -0500 Subject: [PATCH 1/2] Add implementation plan for life fullscreen sidebar --- PLAN_life_fullscreen_sidebar.md | 337 ++++++++++++++++++++++++++++++++ 1 file changed, 337 insertions(+) create mode 100644 PLAN_life_fullscreen_sidebar.md diff --git a/PLAN_life_fullscreen_sidebar.md b/PLAN_life_fullscreen_sidebar.md new file mode 100644 index 00000000..99ea12de --- /dev/null +++ b/PLAN_life_fullscreen_sidebar.md @@ -0,0 +1,337 @@ +# AUTONOMOUS PR ORCHESTRATOR - DO NOT SKIP + +**You are an autonomous PR orchestrator. Your ONLY job is to implement this plan and create a PR.** + +## Isolation Check (RUN FIRST) +```bash +REPO_ROOT=$(git rev-parse --show-toplevel) +if [ "$REPO_ROOT" = "/home/theseus/alexandria/openhouse" ]; then + echo "FATAL: In main repo. Must be in worktree." + echo "Worktree: /home/theseus/alexandria/openhouse-life-fullscreen" + exit 1 +fi +echo "In isolated worktree: $REPO_ROOT" +``` + +## Your Autonomous Workflow (NO QUESTIONS ALLOWED) +1. **Verify isolation** - You must be in worktree: `/home/theseus/alexandria/openhouse-life-fullscreen` +2. **Implement feature** - Follow plan sections below +3. **Build & Deploy to Mainnet**: + ```bash + cd openhouse_frontend + npm run build + cd .. + ./deploy.sh --frontend-only + ``` +4. **Verify deployment**: + ```bash + echo "Visit: https://pezw3-laaaa-aaaal-qssoa-cai.icp0.io/life" + ``` +5. **Create PR** (MANDATORY): + ```bash + git add . + git commit -m "feat(life): fullscreen grid with collapsible sidebar" + git push -u origin feature/life-fullscreen-sidebar + gh pr create --title "Life: Fullscreen grid with collapsible sidebar" --body "$(cat <<'EOF' +## Summary +- Grid now takes full screen height (except page header) +- Combined info + pattern selector in collapsible left sidebar (desktop) +- Bottom bar for mobile devices +- Sidebar state persisted to localStorage + +## Test plan +- [ ] Visit /life route on desktop - sidebar should be visible on left +- [ ] Collapse sidebar - grid expands, state persists on refresh +- [ ] Test on mobile viewport - bottom bar should appear instead +- [ ] Verify zoom controls still work in top-right overlay +- [ ] Verify pattern selection and cell placement still work + +Deployed to mainnet: +- Frontend: https://pezw3-laaaa-aaaal-qssoa-cai.icp0.io/life + +Generated with Claude Code +EOF +)" + ``` +6. **Iterate autonomously** - Fix any P0 issues from review + +## CRITICAL RULES +- NO questions ("should I?", "want me to?") +- NO skipping PR creation +- MAINNET DEPLOYMENT: All changes go directly to production +- ONLY stop at: approved, max iterations, or error + +**Branch:** `feature/life-fullscreen-sidebar` +**Worktree:** `/home/theseus/alexandria/openhouse-life-fullscreen` + +--- + +# Implementation Plan: Life Fullscreen Grid with Collapsible Sidebar + +## Goal +Redesign `/life` route so the grid takes full screen (except page header), with a collapsible left sidebar containing info + pattern selection on desktop, and a bottom bar on mobile. + +## Current State + +**File:** `openhouse_frontend/src/pages/Life.tsx` (606 lines) + +Current layout structure: +``` +div (h-[calc(100vh-120px)]) // Lines 462 +├── Header row (mb-3) // Lines 464-501 +├── Error display // Lines 503-508 +├── Pattern selector (mb-3) // Lines 510-570 +└── Canvas container (flex-1) // Lines 572-602 + ├── Zoom controls (top-right) + ├── Info text (bottom-left) + └── Canvas element +``` + +## Target State + +``` +div (h-[calc(100vh-80px)] flex) +├── Sidebar (w-72 when open, w-12 when collapsed) [desktop: hidden on mobile] +│ ├── Toggle button (chevron) +│ ├── Info section +│ │ ├── Title "Game of Life" +│ │ ├── Player status +│ │ ├── Generation counter +│ │ ├── Player count +│ │ └── Territory/cell stats +│ └── Pattern section +│ ├── Category filters +│ └── Pattern buttons +├── Canvas container (flex-1) +│ ├── Zoom controls (top-right overlay) +│ └── Canvas element +└── Bottom bar [mobile only: hidden on desktop] + ├── Collapsed: Gen, players, expand button + └── Expanded: Info + horizontal pattern scroller +``` + +## Implementation Steps + +### Step 1: Add sidebar state management + +Add at top of component (after existing state declarations around line 172): + +```typescript +// PSEUDOCODE +// Sidebar collapsed state with localStorage persistence +const [sidebarCollapsed, setSidebarCollapsed] = useState(() => { + // Check localStorage for saved preference + const saved = localStorage.getItem('life-sidebar-collapsed'); + return saved === 'true'; +}); + +// Mobile bottom bar expanded state +const [mobileExpanded, setMobileExpanded] = useState(false); + +// Persist sidebar state +useEffect(() => { + localStorage.setItem('life-sidebar-collapsed', String(sidebarCollapsed)); +}, [sidebarCollapsed]); +``` + +### Step 2: Create Sidebar component (inline) + +Add before the return statement (around line 439): + +```typescript +// PSEUDOCODE +const Sidebar = () => ( + +); +``` + +### Step 3: Create Mobile Bottom Bar component (inline) + +```typescript +// PSEUDOCODE +const MobileBottomBar = () => ( +
+ {/* Collapsed view */} +
+
+ Gen: {gameState?.generation.toString() || 0} + {gameState?.players.length || 0}/10 players +
+ +
+ + {/* Expanded view */} + {mobileExpanded && ( +
+ {/* Territory/cell stats in row */} +
+ {/* Stats */} +
+ {/* Horizontal scrolling pattern selector */} +
+ {filteredPatterns.map(pattern => ( + + ))} +
+
+ )} +
+); +``` + +### Step 4: Update main return statement + +Replace the entire return statement (lines 461-603) with: + +```typescript +// PSEUDOCODE +return ( +
+ {/* Error display - keep at top */} + {error && ( +
+ {error} +
+ )} + + {/* Main content area */} +
+ {/* Desktop Sidebar */} + + + {/* Canvas Container */} +
+ {/* Zoom controls - top right overlay */} +
+ {/* Same zoom buttons as current */} +
+ + {/* Canvas */} +
+ e.preventDefault()} + className={`w-full h-full ${isPanning ? 'cursor-grabbing' : 'cursor-crosshair'}`} + style={{ display: 'block' }} + /> +
+
+
+ + {/* Mobile Bottom Bar */} + +
+); +``` + +### Step 5: Update login screen height + +Change line 442 from: +```typescript +
+``` +to: +```typescript +
+``` + +## Key Changes Summary + +| Section | Before | After | +|---------|--------|-------| +| Outer height | `h-[calc(100vh-120px)]` | `h-[calc(100vh-80px)]` | +| Header row | Separate div at top | Moved into sidebar | +| Pattern selector | Full-width panel | Inside sidebar (desktop) / bottom bar (mobile) | +| Canvas | Takes remaining flex space | Same, but more space available | +| Info text overlay | Bottom-left of canvas | Removed (now in sidebar) | + +## Responsive Breakpoints + +- `lg` (1024px+): Sidebar visible, bottom bar hidden +- Below `lg`: Sidebar hidden, bottom bar visible + +## Files Modified + +- `openhouse_frontend/src/pages/Life.tsx` - All changes in single file + +## Testing Notes + +1. Desktop: Sidebar should appear on left, collapsible +2. Collapse state should persist across page refresh (localStorage) +3. Mobile: Bottom bar should appear, expandable +4. Zoom controls remain functional in top-right +5. Pattern selection and placement still work +6. Canvas should resize correctly when sidebar collapses/expands From b8d292e2391be1d042677ee762474715e2e5c0f7 Mon Sep 17 00:00:00 2001 From: evanmcfarland Date: Mon, 15 Dec 2025 11:41:43 -0500 Subject: [PATCH 2/2] feat(life): fullscreen grid with collapsible sidebar MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Grid now takes full screen height (except page header) - Combined info + pattern selector in collapsible left sidebar (desktop) - Bottom bar for mobile devices with expandable pattern selection - Sidebar collapse state persisted to localStorage 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- openhouse_frontend/src/pages/Life.tsx | 427 ++++++++++++++++++-------- 1 file changed, 295 insertions(+), 132 deletions(-) diff --git a/openhouse_frontend/src/pages/Life.tsx b/openhouse_frontend/src/pages/Life.tsx index 8dc4ae15..58c9145e 100644 --- a/openhouse_frontend/src/pages/Life.tsx +++ b/openhouse_frontend/src/pages/Life.tsx @@ -171,6 +171,20 @@ export const Life: React.FC = () => { const [myPlayerNum, setMyPlayerNum] = useState(null); const [, forceRender] = useState(0); + // Sidebar collapsed state with localStorage persistence + const [sidebarCollapsed, setSidebarCollapsed] = useState(() => { + const saved = localStorage.getItem('life-sidebar-collapsed'); + return saved === 'true'; + }); + + // Mobile bottom bar expanded state + const [mobileExpanded, setMobileExpanded] = useState(false); + + // Persist sidebar state + useEffect(() => { + localStorage.setItem('life-sidebar-collapsed', String(sidebarCollapsed)); + }, [sidebarCollapsed]); + // Parse pattern on selection change useEffect(() => { setParsedPattern(parseRLE(selectedPattern.rle)); @@ -436,10 +450,249 @@ export const Life: React.FC = () => { const filteredPatterns = selectedCategory === 'all' ? PATTERNS : PATTERNS.filter(p => p.category === selectedCategory); + // Desktop Sidebar component + const Sidebar = () => ( +