Files
calctext/_bmad-output/C-UX-Scenarios/01-workspace-shell/1.1-app-shell/1.1-app-shell.md
C. Cassel 0d38bd3108 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>
2026-03-18 09:12:05 -04:00

20 KiB
Raw Blame History

1.1 — App Shell

Next Step:Status Bar


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:

Related Pages:

  • Status Bar — 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

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

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 (180400px), 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

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.


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 + 19 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
7681023px 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

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

  • Page purpose clear
  • All Object IDs assigned
  • Layout structure defined (desktop, tablet, mobile)
  • Spacing tokens documented
  • Typography scale applied
  • States documented (first launch, returning, empty, loading, offline)
  • Keyboard shortcuts defined
  • Responsive breakpoints specified
  • Theme integration documented
  • localStorage schema defined
  • Cross-platform portability noted
  • Open questions captured

Next Step:Status Bar


Created using Whiteport Design Studio (WDS) methodology