14 plans in 6 waves covering all 68 requirements for the Tournament Engine phase. Includes research (go-libsql, NATS JetStream, Svelte 5 runes, ICM complexity), plan verification (2 iterations), and user feedback (hand-for-hand UX, SEAT-06 reword, re-entry semantics, integration test, DKK defaults, JWT 7-day expiry, clock tap safety). Wave structure: 1: A (scaffold), B (schema) 2: C (auth/audit), D (clock), E (templates), J (frontend scaffold) 3: F (financial), H (seating), M (layout shell) 4: G (player management) 5: I (tournament lifecycle) 6: K (overview/financials), L (players), N (tables/more) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
180 lines
8.3 KiB
Markdown
180 lines
8.3 KiB
Markdown
# Plan M: Layout Shell — Header, Tabs, FAB, Toast, Data Table
|
|
|
|
---
|
|
wave: 3
|
|
depends_on: [01-PLAN-J]
|
|
files_modified:
|
|
- frontend/src/routes/+layout.svelte
|
|
- frontend/src/lib/components/Header.svelte
|
|
- frontend/src/lib/components/BottomTabs.svelte
|
|
- frontend/src/lib/components/FAB.svelte
|
|
- frontend/src/lib/components/Toast.svelte
|
|
- frontend/src/lib/components/DataTable.svelte
|
|
autonomous: true
|
|
requirements: [UI-01, UI-02, UI-03, UI-04, UI-07, UI-08]
|
|
---
|
|
|
|
## Goal
|
|
|
|
The layout shell wraps all page content: a persistent clock header, mobile bottom tab bar (or desktop sidebar), floating action button (FAB) for quick actions, toast notification system, and a reusable data table component. Multi-tournament tab switching when 2+ tournaments are active.
|
|
|
|
## Context
|
|
|
|
- **SvelteKit scaffold** — Plan J (theme, WS client, API client, auth/tournament state stores)
|
|
- **Svelte 5 runes** for all reactivity
|
|
- **Mobile-first** with responsive desktop layout (sidebar instead of bottom tabs)
|
|
- **48px minimum touch targets** — poker room environment
|
|
- See 01-RESEARCH.md: Pattern 3 (SvelteKit SPA)
|
|
|
|
## User Decisions (from CONTEXT.md)
|
|
|
|
- **Mobile-first bottom tab bar** — Overview, Players, Tables, Financials, More
|
|
- **FAB for quick actions** — Bust, Buy In, Rebuy, Add-On, Pause/Resume
|
|
- **Persistent header** showing clock, level, blinds, player count
|
|
- **Desktop/laptop sidebar** with wider content area
|
|
- **Toast notifications** (success, info, warning, error) with auto-dismiss
|
|
- **Multi-tournament switching** — tabs at top (phone)
|
|
|
|
## Tasks
|
|
|
|
<task id="M1" title="Implement layout shell: header, bottom tabs, FAB, toast, data table">
|
|
**1. Root Layout** (`frontend/src/routes/+layout.svelte`):
|
|
- Auth guard: if not authenticated, redirect to /login
|
|
- Structure:
|
|
```
|
|
┌─────────────────────────┐
|
|
│ PersistentHeader │ ← Fixed top, always visible
|
|
├─────────────────────────┤
|
|
│ [Tournament Tabs] │ ← Multi-tournament selector (when 2+ active)
|
|
├─────────────────────────┤
|
|
│ │
|
|
│ <slot /> │ ← Page content (scrollable)
|
|
│ │
|
|
├─────────────────────────┤
|
|
│ BottomTabBar │ ← Fixed bottom (mobile), Sidebar (desktop)
|
|
└─────────────────────────┘
|
|
│ FAB (floating) │ ← Bottom-right, above tab bar
|
|
│ Toast (floating) │ ← Top-right or bottom-center
|
|
```
|
|
- Responsive: detect screen width
|
|
- Mobile (< 768px): bottom tab bar, content full width
|
|
- Desktop (>= 768px): sidebar left, content fills remaining width — UI-04
|
|
|
|
**2. Persistent Header** (`frontend/src/lib/components/Header.svelte`) — UI-03:
|
|
- Fixed at top, always visible
|
|
- Content (reactive, from tournament state):
|
|
- Clock: large countdown timer (MM:SS format, red text in final 10s)
|
|
- Current level number and name (e.g., "Level 5 — NL Hold'em")
|
|
- Blinds: SB/BB display (e.g., "100/200")
|
|
- Ante: if > 0, show ante (e.g., "Ante 25")
|
|
- Player count: "12/20 remaining" (active/total)
|
|
- Pause indicator: pulsing "PAUSED" when clock is paused
|
|
- Break indicator: "BREAK" with different styling when on break level
|
|
- Compact on mobile (smaller font, abbreviated), expanded on desktop
|
|
- Connected to tournament state store (auto-updates from WebSocket)
|
|
|
|
**3. Bottom Tab Bar** (`frontend/src/lib/components/BottomTabs.svelte`) — UI-01:
|
|
- 5 tabs: Overview, Players, Tables, Financials, More
|
|
- Each tab: icon + label
|
|
- Active tab highlighted with accent color
|
|
- 48px touch targets — UI-06
|
|
- Renders only on mobile (hidden on desktop where sidebar shows)
|
|
- Navigation: SvelteKit goto() or <a> elements
|
|
|
|
**4. Desktop Sidebar** — UI-04:
|
|
- Same 5 navigation items as bottom tabs but in vertical sidebar
|
|
- Wider labels, no icons-only mode
|
|
- Active item highlighted
|
|
- Renders only on desktop (>= 768px)
|
|
|
|
**5. Floating Action Button** (`frontend/src/lib/components/FAB.svelte`) — UI-02:
|
|
- Positioned bottom-right, above the tab bar
|
|
- Default state: single button with "+" icon
|
|
- Expanded state: fan out action buttons:
|
|
- Bust (red) — opens bust-out flow
|
|
- Buy In (green) — opens buy-in flow
|
|
- Rebuy (blue) — opens rebuy flow
|
|
- Add-On (yellow) — opens add-on flow
|
|
- Pause/Resume (orange) — toggles clock
|
|
- Each action button: 48px, with label
|
|
- Press-state animation (scale down on press) — UI-06
|
|
- Context-aware: only show relevant actions (e.g., hide "Add-On" if not in addon window)
|
|
- Close on backdrop tap or ESC
|
|
|
|
**6. Toast Notifications** (`frontend/src/lib/components/Toast.svelte`) — UI-07:
|
|
- Toast state using Svelte 5 runes:
|
|
```typescript
|
|
class ToastState {
|
|
toasts = $state<Toast[]>([]);
|
|
success(message: string, duration?: number) { ... }
|
|
info(message: string, duration?: number) { ... }
|
|
warning(message: string, duration?: number) { ... }
|
|
error(message: string, duration?: number) { ... }
|
|
dismiss(id: string) { ... }
|
|
}
|
|
export const toast = new ToastState();
|
|
```
|
|
- Auto-dismiss: success (3s), info (4s), warning (5s), error (manual dismiss or 8s)
|
|
- Stacking: multiple toasts stack vertically
|
|
- Animation: slide in from right, fade out
|
|
- Color coding: green (success), blue (info), yellow (warning), red (error) — using Catppuccin colors
|
|
|
|
**7. Data Table** (`frontend/src/lib/components/DataTable.svelte`) — UI-08:
|
|
- Props: columns config, data array, sortable flag, searchable flag
|
|
- Features:
|
|
- Sort by clicking column header (asc/desc toggle)
|
|
- Sticky header on scroll
|
|
- Search/filter input (filters across all visible columns)
|
|
- Row click handler (for detail navigation)
|
|
- Mobile: swipe actions (swipe left reveals action buttons like "Bust", "Rebuy")
|
|
- Loading state: skeleton rows
|
|
- Empty state: "No data" message
|
|
- Responsive: hide less important columns on mobile (configurable per column)
|
|
- 48px row height for touch targets — UI-06
|
|
|
|
**8. Multi-Tournament Tabs:**
|
|
- Show tabs at top of content area when 2+ tournaments are active
|
|
- Each tab: tournament name + status indicator
|
|
- Tapping a tab switches the active tournament (changes which state the views render)
|
|
- Keep both tournament states in memory (keyed by tournament ID) for fast switching — don't clear/re-fetch on tab change
|
|
- WebSocket subscribes to all active tournaments simultaneously; messages route to the correct state by tournament ID
|
|
- On phone: scrollable horizontal tabs
|
|
|
|
**9. Loading States** — UI-06:
|
|
- Skeleton loading component: animated placeholder matching content shape
|
|
- Used in all data-fetching views
|
|
- Full-page loading spinner for initial app load
|
|
- Inline loading states for buttons (spinner replaces label during action)
|
|
|
|
**Verification:**
|
|
- App renders with Catppuccin Mocha dark theme
|
|
- Header shows clock countdown (updates from WebSocket)
|
|
- Bottom tabs navigate between Overview/Players/Tables/Financials/More on mobile
|
|
- Sidebar navigation works on desktop
|
|
- FAB expands to show action buttons
|
|
- Toast notifications appear and auto-dismiss
|
|
- Data table sorts, filters, and handles mobile swipe actions
|
|
- Multi-tournament tabs appear when 2+ tournaments exist
|
|
- All interactive elements meet 48px minimum touch target
|
|
</task>
|
|
|
|
## Verification Criteria
|
|
|
|
1. Mobile-first bottom tab bar with Overview, Players, Tables, Financials, More
|
|
2. FAB expands to show quick actions (Bust, Buy In, Rebuy, Add-On, Pause/Resume)
|
|
3. Persistent header shows clock, level, blinds, player count — updates in real time
|
|
4. Desktop sidebar navigation for wider screens
|
|
5. Toast notifications work (success, info, warning, error) with auto-dismiss
|
|
6. Data tables with sort, sticky header, search/filter, swipe actions (mobile)
|
|
7. Multi-tournament tabs appear when 2+ tournaments active
|
|
8. All interactive elements meet 48px minimum touch targets
|
|
9. Loading states (skeleton, spinner) for all data-fetching views
|
|
|
|
## Must-Haves (Goal-Backward)
|
|
|
|
- [ ] Mobile-first bottom tab bar with 5 navigation tabs
|
|
- [ ] FAB with context-aware quick actions
|
|
- [ ] Persistent header with live clock, level, blinds, player count
|
|
- [ ] Responsive layout (bottom tabs on mobile, sidebar on desktop)
|
|
- [ ] Data table component reusable across all views
|
|
- [ ] Toast notification system
|