feat(web): implement complete workspace with themes, tabs, sidebar, and mobile
Transform CalcText from a single-document calculator into a full workspace application with multi-document support, theming, and responsive mobile experience. - Theme system: 5 presets (Light, Dark, Matrix, Midnight, Warm) + accent colors - Document model with localStorage persistence and auto-save - Tab bar with keyboard shortcuts (Ctrl+N/W/Tab/1-9), rename, close - Sidebar with search, recent, favorites, folders, templates, drag-and-drop - 5 templates: Budget, Invoice, Unit Converter, Trip Planner, Loan Calculator - Status bar with cursor position, engine status, dedication to Igor Cassel - Results panel: type-specific colors, click-to-copy, error hints - Format toolbar: H, B, I, //, color labels with live preview toggle - Syntax highlighting using theme CSS variables - Error hover tooltips - Mobile: bottom results tray, sidebar drawer, touch targets, safe areas - Docker multi-stage build (Rust WASM + Vite + Nginx) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,558 @@
|
||||
# 1.1 — App Shell
|
||||
|
||||
**Next Step:** → [Status Bar](../1.2-status-bar/1.2-status-bar.md)
|
||||
|
||||
---
|
||||
|
||||
## Page Metadata
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| **Scenario** | 01 — Workspace Shell |
|
||||
| **Page Number** | 1.1 |
|
||||
| **Platform** | Web (PWA), portable to macOS/Windows |
|
||||
| **Page Type** | Full Application Shell |
|
||||
| **Viewport** | Desktop-first, responsive to mobile |
|
||||
| **Interaction** | Mouse + keyboard (primary), touch (secondary) |
|
||||
| **Visibility** | Public (no auth required) |
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
**Page Purpose:** The app shell is the top-level container that defines the spatial structure of the entire CalcText workspace. It arranges all panels (sidebar, editor, results), the tab bar, header, and status bar into a cohesive layout that persists across all user interactions.
|
||||
|
||||
**User Situation:** User opens CalcText in a browser. They expect a professional workspace where they can write calculations, manage files, and personalize their environment. First-time users should immediately understand the layout. Returning users should find their documents and preferences exactly as they left them.
|
||||
|
||||
**Success Criteria:**
|
||||
- User understands the 3-panel layout within 3 seconds
|
||||
- All panels are resizable and collapsible
|
||||
- Layout state persists across sessions (sidebar width, panel visibility)
|
||||
- Feels native — not like a web page
|
||||
|
||||
**Entry Points:**
|
||||
- Direct URL (calctext.app or localhost)
|
||||
- PWA launch from desktop/dock
|
||||
- Returning session (restores last state from localStorage)
|
||||
|
||||
**Exit Points:**
|
||||
- Close browser/PWA (state auto-saves)
|
||||
- All navigation is within the shell (no page transitions)
|
||||
|
||||
---
|
||||
|
||||
## Reference Materials
|
||||
|
||||
**Strategic Foundation:**
|
||||
- [Product Brief](../../../A-Product-Brief/project-brief.md) — Workspace evolution, web-first
|
||||
- [Brownfield Analysis](../../../A-Product-Brief/01-brownfield-analysis.md) — Current CSS tokens, components, gaps
|
||||
|
||||
**Related Pages:**
|
||||
- [Status Bar](../1.2-status-bar/1.2-status-bar.md) — Bottom status strip
|
||||
- Tab Bar (Scenario 03) — Document tabs above editor
|
||||
- Sidebar (Scenario 04) — File tree panel
|
||||
- Editor (Scenario 02) — Calculation editor
|
||||
- Results Panel (Scenario 02) — Results display
|
||||
|
||||
---
|
||||
|
||||
## Layout Structure
|
||||
|
||||
The app shell uses a 4-region layout: Header, Sidebar, Main Area (tabs + editor + results), and Status Bar.
|
||||
|
||||
### Desktop (>= 768px)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Header [Logo] [Theme] [Settings] [⌘] │ 40px
|
||||
├────────┬────────────────────────────────────────────────┤
|
||||
│ │ Tab Bar [Budget ×] [Invoice ×] [+] │ 36px
|
||||
│ ├─────────────────────────┬──┬──────────────────┤
|
||||
│ Side │ │ │ │
|
||||
│ bar │ Editor │ D│ Results │
|
||||
│ │ (CodeMirror 6) │ iv│ Panel │
|
||||
│ 240px │ │ │ │
|
||||
│ (coll │ │ │ │
|
||||
│ apsi │ │ │ │
|
||||
│ ble) │ │ │ │
|
||||
│ │ │ │ │
|
||||
├────────┴─────────────────────────┴──┴──────────────────┤
|
||||
│ Status Bar [Ln 12, Col 8] [Engine ●] [Dark 🎨] │ 24px
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Tablet (768px — 1024px)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ Header [Logo] [Theme] [≡] │ 40px
|
||||
├─────────────────────────────────────────┤
|
||||
│ Tab Bar [Budget ×] [Invoice ×] [+] │ 36px
|
||||
├─────────────────────────┬──┬────────────┤
|
||||
│ │ │ │
|
||||
│ Editor │ D│ Results │
|
||||
│ (CodeMirror 6) │ iv│ Panel │
|
||||
│ │ │ │
|
||||
├─────────────────────────┴──┴────────────┤
|
||||
│ Status Bar │ 24px
|
||||
└─────────────────────────────────────────┘
|
||||
Sidebar: overlay drawer via hamburger [≡]
|
||||
```
|
||||
|
||||
### Mobile (< 768px)
|
||||
|
||||
```
|
||||
┌─────────────────────────┐
|
||||
│ Header [Logo] [≡] │ 44px (touch)
|
||||
├─────────────────────────┤
|
||||
│ Tab Bar (scrollable) │ 36px
|
||||
├─────────────────────────┤
|
||||
│ │
|
||||
│ Editor │
|
||||
│ (full width) │
|
||||
│ │
|
||||
│ │
|
||||
├─────────────────────────┤
|
||||
│ Results Tray (toggle) │ 48px collapsed / 40vh expanded
|
||||
├─────────────────────────┤
|
||||
│ Status Bar │ 24px
|
||||
└─────────────────────────┘
|
||||
Sidebar: full-screen drawer
|
||||
Results: bottom tray with drag handle
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Spacing
|
||||
|
||||
**Scale:** [Spacing Scale](../../../D-Design-System/00-design-system.md#spacing-scale)
|
||||
|
||||
| Property | Token | Pixels (proposed) |
|
||||
|----------|-------|--------------------|
|
||||
| Page padding (horizontal) | space-zero | 0px (panels fill edge-to-edge) |
|
||||
| Header padding (horizontal) | space-md | 12px |
|
||||
| Header padding (vertical) | space-xs | 6px |
|
||||
| Sidebar width (default) | — | 240px |
|
||||
| Sidebar min width | — | 180px |
|
||||
| Sidebar max width | — | 400px |
|
||||
| Divider width (sidebar ↔ editor) | — | 1px visible, 8px hit area |
|
||||
| Divider width (editor ↔ results) | — | 1px visible, 8px hit area |
|
||||
| Tab bar height | — | 36px |
|
||||
| Tab padding (horizontal) | space-sm | 8px |
|
||||
| Status bar height | — | 24px |
|
||||
| Status bar padding (horizontal) | space-md | 12px |
|
||||
|
||||
---
|
||||
|
||||
## Typography
|
||||
|
||||
**Scale:** [Type Scale](../../../D-Design-System/00-design-system.md#type-scale)
|
||||
|
||||
| Element | Semantic | Size | Weight | Typeface |
|
||||
|---------|----------|------|--------|----------|
|
||||
| App title (header) | — | text-sm | 600 | system sans |
|
||||
| Tab label | — | text-xs | 400 (normal), 500 (active) | system sans |
|
||||
| Status bar text | — | text-3xs | 400 | system mono |
|
||||
| Sidebar section title | H3 | text-2xs | 600 | system sans |
|
||||
| Sidebar file name | — | text-xs | 400 | system sans |
|
||||
| Editor content | — | text-md | 400 | system mono |
|
||||
| Results value | — | text-md | 400 | system mono |
|
||||
|
||||
---
|
||||
|
||||
## Page Sections
|
||||
|
||||
### Section: Header
|
||||
|
||||
**OBJECT ID:** `shell-header`
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| Purpose | App identity, global actions, theme quick-switch |
|
||||
| Height | 40px (desktop/tablet), 44px (mobile — touch target) |
|
||||
| Background | var(--bg) |
|
||||
| Border | bottom 1px solid var(--border) |
|
||||
| Layout | Horizontal: logo-left, actions-right |
|
||||
|
||||
#### Logo Group
|
||||
|
||||
**OBJECT ID:** `shell-header-logo`
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| Content | CalcText icon + wordmark |
|
||||
| Icon size | 20px × 20px |
|
||||
| Wordmark | "CalcText" in text-sm, weight 600 |
|
||||
| Gap | space-xs (6px) between icon and wordmark |
|
||||
| Mobile | Wordmark hidden < 480px, icon only |
|
||||
|
||||
#### Header Actions
|
||||
|
||||
**OBJECT ID:** `shell-header-actions`
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| Layout | Horizontal, space-xs gap |
|
||||
| Items | Theme toggle, Settings button, Keyboard shortcuts (⌘) |
|
||||
| Button size | 28px × 28px (icon buttons) |
|
||||
| Icon size | 16px |
|
||||
| Style | Ghost buttons — transparent bg, var(--text) icon, hover → var(--accent-bg) |
|
||||
|
||||
#### Theme Toggle (Header)
|
||||
|
||||
**OBJECT ID:** `shell-header-theme-toggle`
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| Component | Icon button with dropdown |
|
||||
| Icon | Sun (light), Moon (dark), Terminal (matrix), Palette (custom) |
|
||||
| Click | Opens theme picker dropdown |
|
||||
| Tooltip | "Switch theme (Ctrl+Shift+T)" |
|
||||
|
||||
#### ↕ `shell-header-v-space-zero` — Header sits flush against tab bar below
|
||||
|
||||
---
|
||||
|
||||
### Section: Sidebar
|
||||
|
||||
**OBJECT ID:** `shell-sidebar`
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| Purpose | File navigation, document organization, templates |
|
||||
| Width | 240px default, resizable (180–400px), collapsible to 0 |
|
||||
| Background | var(--bg-secondary) |
|
||||
| Border | right 1px solid var(--border) |
|
||||
| Toggle | Cmd/Ctrl+B to show/hide |
|
||||
| Resize | Drag right edge, cursor col-resize |
|
||||
| Persistence | Width and visibility stored in localStorage |
|
||||
|
||||
#### Sidebar Sections
|
||||
|
||||
**OBJECT ID:** `shell-sidebar-sections`
|
||||
|
||||
| Section | Icon | Content |
|
||||
|---------|------|---------|
|
||||
| **Recent** | 🕐 | Last 5 opened documents, sorted by time |
|
||||
| **Favorites** | ⭐ | User-pinned documents |
|
||||
| **Files** | 📁 | Full folder tree with nested structure |
|
||||
| **Templates** | 📋 | Pre-built starting points (Budget, Invoice, Unit Converter, Trip Planner, Blank) |
|
||||
|
||||
Each section is collapsible with a chevron toggle.
|
||||
|
||||
#### File Tree Item
|
||||
|
||||
**OBJECT ID:** `shell-sidebar-file-item`
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| Height | 28px |
|
||||
| Padding left | 12px + (depth × 16px) for nesting |
|
||||
| Icon | 📄 file / 📁 folder (closed) / 📂 folder (open) |
|
||||
| Label | File/folder name, text-xs, ellipsis on overflow |
|
||||
| Hover | var(--accent-bg) background |
|
||||
| Active | var(--accent-bg) + left 2px accent border |
|
||||
| Right-click | Context menu: Rename, Delete, Duplicate, Move to folder, Add to favorites |
|
||||
| Double-click | Opens document in new tab |
|
||||
| Drag | Reorder within folder, drag between folders |
|
||||
|
||||
#### Sidebar Footer
|
||||
|
||||
**OBJECT ID:** `shell-sidebar-footer`
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| Content | [+ New Document] button, [+ New Folder] button |
|
||||
| Layout | Horizontal, full width, space-xs gap |
|
||||
| Button style | Ghost, text-2xs, var(--text), hover → var(--accent) |
|
||||
| Position | Sticky bottom of sidebar |
|
||||
| Padding | space-sm |
|
||||
| Border | top 1px solid var(--border) |
|
||||
|
||||
---
|
||||
|
||||
### Section: Tab Bar
|
||||
|
||||
**OBJECT ID:** `shell-tabbar`
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| Purpose | Multi-document navigation, quick tab management |
|
||||
| Height | 36px |
|
||||
| Background | var(--bg-secondary) |
|
||||
| Border | bottom 1px solid var(--border) |
|
||||
| Layout | Horizontal scroll when tabs overflow |
|
||||
| Position | Between header and editor area |
|
||||
|
||||
#### Tab Item
|
||||
|
||||
**OBJECT ID:** `shell-tabbar-tab`
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| Min width | 100px |
|
||||
| Max width | 200px |
|
||||
| Padding | 0 space-sm (0 8px) |
|
||||
| Height | 36px (fills bar) |
|
||||
| Label | Document title, text-xs, ellipsis on overflow |
|
||||
| Modified indicator | Dot (6px) before title when unsaved changes |
|
||||
| Close button | × icon, 14px, visible on hover or active tab |
|
||||
| Active state | var(--bg) background, no bottom border (connected to editor) |
|
||||
| Inactive state | var(--bg-secondary), bottom border 1px solid var(--border) |
|
||||
| Hover (inactive) | var(--bg-secondary) lightened slightly |
|
||||
| Drag | Reorder tabs via drag-and-drop |
|
||||
| Middle-click | Close tab |
|
||||
| Double-click | Rename document inline |
|
||||
|
||||
#### New Tab Button
|
||||
|
||||
**OBJECT ID:** `shell-tabbar-new`
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| Icon | + (16px) |
|
||||
| Size | 36px × 36px (square, fills bar height) |
|
||||
| Style | Ghost, var(--text), hover → var(--accent) |
|
||||
| Click | Creates "Untitled" document and switches to it |
|
||||
| Position | After last tab, before overflow |
|
||||
|
||||
#### Tab Overflow
|
||||
|
||||
**OBJECT ID:** `shell-tabbar-overflow`
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| Trigger | When tabs exceed container width |
|
||||
| Behavior | Horizontal scroll with mouse wheel or trackpad |
|
||||
| Indicators | Fade gradient on edges when scrollable |
|
||||
| Keyboard | Ctrl+Tab / Ctrl+Shift+Tab to cycle tabs |
|
||||
|
||||
---
|
||||
|
||||
### Section: Main Area
|
||||
|
||||
**OBJECT ID:** `shell-main`
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| Purpose | Contains the active document's editor and results panel |
|
||||
| Layout | Horizontal flex: editor (flex: 3) + divider + results (flex: 1) |
|
||||
| Background | var(--bg) |
|
||||
| Content | Delegates to Scenario 02 (Editor + Results Panel) |
|
||||
|
||||
#### Editor Pane
|
||||
|
||||
**OBJECT ID:** `shell-main-editor`
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| Flex | 3 (default ~75%) |
|
||||
| Min width | 300px |
|
||||
| Content | CodeMirror 6 instance (see Scenario 02) |
|
||||
| Overflow | Vertical scroll (editor handles internally) |
|
||||
|
||||
#### Pane Divider (Editor ↔ Results)
|
||||
|
||||
**OBJECT ID:** `shell-main-divider`
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| Width | 1px visible line |
|
||||
| Hit area | 8px (invisible padding for easy grabbing) |
|
||||
| Cursor | col-resize |
|
||||
| Color | var(--border), hover → var(--accent) |
|
||||
| Transition | background 0.15s |
|
||||
| Double-click | Reset to default 75/25 split |
|
||||
| Persistence | Position stored in localStorage |
|
||||
|
||||
#### Results Pane
|
||||
|
||||
**OBJECT ID:** `shell-main-results`
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| Flex | 1 (default ~25%) |
|
||||
| Min width | 120px |
|
||||
| Content | Results panel (see Scenario 02) |
|
||||
| Scroll sync | Mirrors editor scroll position |
|
||||
|
||||
---
|
||||
|
||||
### Section: Status Bar
|
||||
|
||||
**OBJECT ID:** `shell-statusbar`
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| Purpose | Contextual info: cursor position, engine status, theme indicator |
|
||||
| Height | 24px |
|
||||
| Background | var(--bg-secondary) |
|
||||
| Border | top 1px solid var(--border) |
|
||||
| Font | text-3xs, monospace |
|
||||
| Color | var(--text) |
|
||||
| Layout | Horizontal: left-info + right-info |
|
||||
|
||||
Full specification in [1.2 — Status Bar](../1.2-status-bar/1.2-status-bar.md).
|
||||
|
||||
---
|
||||
|
||||
## Page States
|
||||
|
||||
| State | When | Appearance | Actions |
|
||||
|-------|------|------------|---------|
|
||||
| **First Launch** | No localStorage data | Sidebar open with Templates section expanded. Single tab "Welcome" with demo calctext. Theme follows OS preference. | User can start typing, explore templates, or create new doc |
|
||||
| **Returning User** | localStorage has documents | Restores: last open tabs, active tab, sidebar state, theme, divider positions | Resume exactly where they left off |
|
||||
| **Empty Workspace** | All documents deleted | Editor shows subtle placeholder: "Create a new document or choose a template to get started" | + New Document button prominent, Templates section highlighted |
|
||||
| **Engine Loading** | WASM initializing | Status bar shows "Engine loading..." with pulse animation. Editor is editable. Results show "—" | Editor works, results appear once engine is ready |
|
||||
| **Offline** | No network | Subtle indicator in status bar. All features work (localStorage). Currency rates may be stale. | Full functionality, offline banner only if currency conversion attempted |
|
||||
|
||||
---
|
||||
|
||||
## Interactions & Keyboard Shortcuts
|
||||
|
||||
| Shortcut | Action |
|
||||
|----------|--------|
|
||||
| Cmd/Ctrl + B | Toggle sidebar |
|
||||
| Cmd/Ctrl + N | New document |
|
||||
| Cmd/Ctrl + W | Close active tab |
|
||||
| Cmd/Ctrl + Tab | Next tab |
|
||||
| Cmd/Ctrl + Shift + Tab | Previous tab |
|
||||
| Cmd/Ctrl + 1–9 | Switch to tab N |
|
||||
| Cmd/Ctrl + Shift + T | Open theme picker |
|
||||
| Cmd/Ctrl + , | Open settings |
|
||||
| Cmd/Ctrl + S | Force save (visual confirmation — auto-save is default) |
|
||||
|
||||
---
|
||||
|
||||
## Responsive Behavior
|
||||
|
||||
| Breakpoint | Layout Changes |
|
||||
|------------|----------------|
|
||||
| **>= 1024px** | Full 3-panel: sidebar + editor + results |
|
||||
| **768–1023px** | Sidebar becomes overlay drawer (hamburger toggle). Editor + results remain side-by-side |
|
||||
| **< 768px** | Single column. Sidebar = full-screen drawer. Results = bottom tray (collapsible). Tabs = horizontal scroll. Header = 44px (touch). |
|
||||
|
||||
### Mobile Results Tray
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| Collapsed height | 48px (shows last result + drag handle) |
|
||||
| Expanded height | 40vh |
|
||||
| Drag handle | 32px × 4px pill, centered, var(--border) |
|
||||
| Swipe up | Expand tray |
|
||||
| Swipe down | Collapse tray |
|
||||
| Tap collapsed | Expand tray |
|
||||
|
||||
### Mobile Sidebar Drawer
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| Width | 85vw (max 320px) |
|
||||
| Background | var(--bg) |
|
||||
| Overlay | 50% black backdrop |
|
||||
| Animation | Slide from left, 200ms ease-out |
|
||||
| Close | Tap backdrop, swipe left, or X button |
|
||||
|
||||
---
|
||||
|
||||
## Theme Integration
|
||||
|
||||
The app shell's colors are entirely driven by CSS custom properties. Switching themes means swapping the property values on `:root`. No component changes needed.
|
||||
|
||||
| Theme | --bg | --bg-secondary | --text | --accent | Special |
|
||||
|-------|------|----------------|--------|----------|---------|
|
||||
| **Light** | #fff | #f8f9fa | #6b6375 | #6366f1 | — |
|
||||
| **Dark** | #16171d | #1a1b23 | #9ca3af | #818cf8 | — |
|
||||
| **Matrix** | #0a0a0a | #0f0f0f | #00ff41 | #00ff41 | Monospace everywhere. Subtle scanline overlay. Cursor blink green. |
|
||||
| **Custom** | User-defined | User-defined | User-defined | User-defined | Accent color picker + base tone (warm/cool/neutral) |
|
||||
|
||||
Theme selection persisted in localStorage as `calctext-theme`.
|
||||
|
||||
---
|
||||
|
||||
## localStorage Schema
|
||||
|
||||
```typescript
|
||||
interface CalcTextStorage {
|
||||
// Documents
|
||||
documents: Document[]
|
||||
folders: Folder[]
|
||||
activeTabId: string
|
||||
openTabIds: string[]
|
||||
|
||||
// Layout
|
||||
sidebarWidth: number
|
||||
sidebarVisible: boolean
|
||||
dividerPosition: number // percentage
|
||||
|
||||
// Preferences
|
||||
theme: 'light' | 'dark' | 'matrix' | string // string for custom
|
||||
customTheme?: ThemeTokens
|
||||
accentColor?: string
|
||||
|
||||
// State
|
||||
lastOpenedAt: string // ISO timestamp
|
||||
}
|
||||
|
||||
interface Document {
|
||||
id: string
|
||||
title: string
|
||||
content: string
|
||||
folderId: string | null
|
||||
isFavorite: boolean
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
interface Folder {
|
||||
id: string
|
||||
name: string
|
||||
parentId: string | null
|
||||
order: number
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Technical Notes
|
||||
|
||||
- **Cross-platform portability:** All layout patterns map to native equivalents. Sidebar → NavigationView (SwiftUI) / side_panel (iced). Tab bar → TabView. Status bar → standard OS status bar pattern.
|
||||
- **Performance:** Only the active tab's CodeMirror instance should be in DOM. Inactive tabs store content in memory, restore on switch.
|
||||
- **Auto-save:** Documents save to localStorage on every change (debounced 500ms). No explicit "save" needed, but Cmd+S provides visual confirmation.
|
||||
- **Sidebar resize:** Use ResizeObserver + mouse events. Store width in localStorage. Minimum 180px, maximum 400px.
|
||||
- **Tab management:** Maximum suggested tabs: 20. Beyond that, show "too many tabs" hint. No hard limit.
|
||||
|
||||
---
|
||||
|
||||
## Open Questions
|
||||
|
||||
| # | Question | Context | Status |
|
||||
|---|----------|---------|--------|
|
||||
| 1 | Should Matrix theme have a subtle CRT scanline effect? | Could be fun but might impact readability | 🔴 Open |
|
||||
| 2 | Should we support tab groups / workspaces? | Multiple sets of tabs for different projects | 🔴 Open — defer to v2 |
|
||||
| 3 | Max localStorage size for documents? | ~5MB browser limit. Need strategy for large collections. | 🟡 In Discussion — may need IndexedDB |
|
||||
|
||||
---
|
||||
|
||||
## Checklist
|
||||
|
||||
- [x] Page purpose clear
|
||||
- [x] All Object IDs assigned
|
||||
- [x] Layout structure defined (desktop, tablet, mobile)
|
||||
- [x] Spacing tokens documented
|
||||
- [x] Typography scale applied
|
||||
- [x] States documented (first launch, returning, empty, loading, offline)
|
||||
- [x] Keyboard shortcuts defined
|
||||
- [x] Responsive breakpoints specified
|
||||
- [x] Theme integration documented
|
||||
- [x] localStorage schema defined
|
||||
- [x] Cross-platform portability noted
|
||||
- [x] Open questions captured
|
||||
|
||||
---
|
||||
|
||||
**Next Step:** → [Status Bar](../1.2-status-bar/1.2-status-bar.md)
|
||||
|
||||
---
|
||||
|
||||
_Created using Whiteport Design Studio (WDS) methodology_
|
||||
@@ -0,0 +1,124 @@
|
||||
# 1.2 — Status Bar
|
||||
|
||||
**Previous Step:** ← [App Shell](../1.1-app-shell/1.1-app-shell.md)
|
||||
|
||||
---
|
||||
|
||||
## Page Metadata
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| **Scenario** | 01 — Workspace Shell |
|
||||
| **Page Number** | 1.2 |
|
||||
| **Platform** | Web (PWA), portable to macOS/Windows |
|
||||
| **Page Type** | Persistent UI Strip (embedded in App Shell) |
|
||||
| **Viewport** | All breakpoints |
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
**Page Purpose:** Provide at-a-glance contextual information about the current document, engine status, and workspace state. Acts as a persistent information bar at the bottom of the workspace.
|
||||
|
||||
**User Situation:** User is working in the editor and glances down for context — current line/column, whether the engine is ready, what theme is active, and document stats.
|
||||
|
||||
**Success Criteria:**
|
||||
- Information readable at a glance without interrupting flow
|
||||
- No interactive elements that accidentally trigger (info-only, with 2 clickable shortcuts)
|
||||
- Consistent across all themes
|
||||
|
||||
---
|
||||
|
||||
## Layout Structure
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ [Ln 12, Col 8] [42 lines] │ [Engine ● Ready] [Dark 🎨] │
|
||||
│ ← left-aligned info │ right-aligned info → │
|
||||
└──────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
Height: 24px. Full width. Background: var(--bg-secondary). Border-top: 1px solid var(--border).
|
||||
|
||||
---
|
||||
|
||||
## Spacing
|
||||
|
||||
| Property | Token | Pixels |
|
||||
|----------|-------|--------|
|
||||
| Height | — | 24px |
|
||||
| Padding horizontal | space-md | 12px |
|
||||
| Item gap | space-md | 12px |
|
||||
| Dot size (engine status) | — | 6px |
|
||||
| Dot margin-right | space-2xs | 4px |
|
||||
|
||||
---
|
||||
|
||||
## Typography
|
||||
|
||||
| Element | Size | Weight | Typeface | Color |
|
||||
|---------|------|--------|----------|-------|
|
||||
| All status text | text-3xs | 400 | system mono | var(--text) |
|
||||
| Engine status (ready) | text-3xs | 400 | system mono | var(--success) |
|
||||
| Engine status (loading) | text-3xs | 400 | system mono | var(--warning) |
|
||||
| Theme name | text-3xs | 500 | system mono | var(--text) |
|
||||
|
||||
---
|
||||
|
||||
## Status Items
|
||||
|
||||
### Left Group
|
||||
|
||||
**OBJECT ID:** `statusbar-left`
|
||||
|
||||
| Item | Content | Update Trigger |
|
||||
|------|---------|----------------|
|
||||
| Cursor position | `Ln {line}, Col {col}` | Cursor movement |
|
||||
| Line count | `{n} lines` | Document change |
|
||||
| Selection (conditional) | `{n} selected` | When text selected |
|
||||
|
||||
### Right Group
|
||||
|
||||
**OBJECT ID:** `statusbar-right`
|
||||
|
||||
| Item | Content | Behavior |
|
||||
|------|---------|----------|
|
||||
| Engine status | `● Ready` (green dot) or `◌ Loading...` (amber, pulse) | Auto-updates on engine state change |
|
||||
| Theme indicator | `{Theme Name} 🎨` | Click → opens theme picker (same as header button) |
|
||||
| Offline (conditional) | `📡 Offline` | Only visible when offline |
|
||||
|
||||
---
|
||||
|
||||
## States
|
||||
|
||||
| State | Engine Indicator | Additional |
|
||||
|-------|-----------------|------------|
|
||||
| Ready | ● green dot, "Ready" | — |
|
||||
| Loading | ◌ amber dot, pulse animation, "Loading..." | — |
|
||||
| Error | ● red dot, "Engine error" | Tooltip with error message |
|
||||
| Offline | ● green dot, "Ready" | + "📡 Offline" appended |
|
||||
|
||||
---
|
||||
|
||||
## Responsive
|
||||
|
||||
| Breakpoint | Behavior |
|
||||
|------------|----------|
|
||||
| >= 768px | Full status bar, all items visible |
|
||||
| < 768px | Simplified: cursor position + engine dot only. Theme and line count hidden. |
|
||||
|
||||
---
|
||||
|
||||
## Technical Notes
|
||||
|
||||
- Status bar reads from editor state (cursor, selection, line count) and engine hook (ready, error)
|
||||
- Theme indicator is the only clickable element — keeps status bar non-disruptive
|
||||
- On macOS/Windows: maps to native status bar or window title bar info
|
||||
|
||||
---
|
||||
|
||||
**Previous Step:** ← [App Shell](../1.1-app-shell/1.1-app-shell.md)
|
||||
|
||||
---
|
||||
|
||||
_Created using Whiteport Design Studio (WDS) methodology_
|
||||
Reference in New Issue
Block a user