From 05056a3446f9b43bb38caa60e9a2cf62c1f7e5b3 Mon Sep 17 00:00:00 2001 From: Michael Yankelev Date: Fri, 23 Jan 2026 03:44:49 +0100 Subject: [PATCH 01/33] docs(06.2): create phase plan for Pencil restyle Phase 6.2: Restyle App with Pencil Design - 6 plans in 4 waves - Wave 1: Design tokens foundation (01) - Wave 2: File browser, dialogs, responsive/matrix (02, 03, 04) - parallel - Wave 3: Component TSX updates (05) - Wave 4: E2E updates and verification (06) Terminal/hacker aesthetic: JetBrains Mono, green-on-black, [DIR]/[FILE] prefixes Co-Authored-By: Claude Opus 4.5 --- .planning/ROADMAP.md | 20 +- .../06.2-01-PLAN.md | 440 ++++++++++ .../06.2-02-PLAN.md | 592 +++++++++++++ .../06.2-03-PLAN.md | 821 ++++++++++++++++++ .../06.2-04-PLAN.md | 543 ++++++++++++ .../06.2-05-PLAN.md | 233 +++++ .../06.2-06-PLAN.md | 191 ++++ 7 files changed, 2833 insertions(+), 7 deletions(-) create mode 100644 .planning/phases/06.2-restyle-app-with-pencil-design/06.2-01-PLAN.md create mode 100644 .planning/phases/06.2-restyle-app-with-pencil-design/06.2-02-PLAN.md create mode 100644 .planning/phases/06.2-restyle-app-with-pencil-design/06.2-03-PLAN.md create mode 100644 .planning/phases/06.2-restyle-app-with-pencil-design/06.2-04-PLAN.md create mode 100644 .planning/phases/06.2-restyle-app-with-pencil-design/06.2-05-PLAN.md create mode 100644 .planning/phases/06.2-restyle-app-with-pencil-design/06.2-06-PLAN.md diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 81cf0e4c42..61ee14bec7 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -223,20 +223,25 @@ Plans: ### Phase 6.2: Restyle App with Pencil Design (INSERTED) -**Goal**: Complete UI redesign using Pencil design tool for modern, polished appearance +**Goal**: Complete UI redesign with terminal/hacker aesthetic using Pencil design specifications **Depends on**: Phase 6.1 **Requirements**: Visual refresh of all UI components **Success Criteria** (what must be TRUE): -1. All UI components restyled with Pencil design system -2. Consistent visual language across login, file browser, and settings pages +1. All UI components restyled with terminal aesthetic (green-on-black, JetBrains Mono) +2. Consistent visual language across login, file browser, and modals 3. Responsive design maintained after restyle 4. Existing E2E tests pass with new styling - **Plans**: TBD +**Plans**: 6 plans Plans: -- [ ] TBD (run /gsd:plan-phase 6.2 to break down) +- [ ] 06.2-01-PLAN.md — Design tokens and typography foundation (JetBrains Mono, CSS variables, login page) +- [ ] 06.2-02-PLAN.md — File browser and breadcrumbs restyle (sidebar, file list, toolbar) +- [ ] 06.2-03-PLAN.md — Dialogs, context menus, modals, and upload UI restyle +- [ ] 06.2-04-PLAN.md — Responsive styles and matrix background animation +- [ ] 06.2-05-PLAN.md — Component updates ([DIR]/[FILE] prefixes, button text, headers) +- [ ] 06.2-06-PLAN.md — E2E test updates and visual verification ### Phase 7: Multi-Device Sync @@ -357,7 +362,7 @@ Decimal phases (if any) execute between their surrounding integers. | 5. Folder System | 4/4 | Complete | 2026-01-21 | | 6. File Browser UI | 4/4 | Complete | 2026-01-22 | | 6.1 Webapp Automation | 6/6 | Complete | 2026-01-22 | -| 6.2 Pencil Restyle | 0/? | Not started | - | +| 6.2 Pencil Restyle | 0/6 | Not started | - | | 7. Multi-Device Sync | 0/3 | Not started | - | | 8. TEE Integration | 0/4 | Not started | - | | 9. Desktop Client | 0/5 | Not started | - | @@ -385,4 +390,5 @@ _Phase 6 planned: 2026-01-21_ _Phase 6.1 planned: 2026-01-22_ _Phase 6.1 complete: 2026-01-22_ _Phase 6.2 inserted: 2026-01-23_ -_Total phases: 13 | Total plans: 53 | Depth: Comprehensive_ +_Phase 6.2 planned: 2026-01-23_ +_Total phases: 13 | Total plans: 59 | Depth: Comprehensive_ diff --git a/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-01-PLAN.md b/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-01-PLAN.md new file mode 100644 index 0000000000..9c0d74804e --- /dev/null +++ b/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-01-PLAN.md @@ -0,0 +1,440 @@ +--- +phase: 06.2-restyle-app-pencil-design +plan: 01 +type: execute +wave: 1 +depends_on: [] +files_modified: + - apps/web/index.html + - apps/web/src/index.css + - apps/web/src/App.css +autonomous: true + +must_haves: + truths: + - "JetBrains Mono font loads on page render" + - "All text uses monospace typography" + - "Background is pure black (#000000)" + - "Primary accent color is green (#00D084)" + artifacts: + - path: "apps/web/index.html" + provides: "Google Fonts CDN link for JetBrains Mono" + contains: "JetBrains+Mono" + - path: "apps/web/src/index.css" + provides: "CSS custom properties (design tokens)" + contains: "--color-green-primary" + key_links: + - from: "apps/web/index.html" + to: "fonts.googleapis.com" + via: "link preconnect and stylesheet" + pattern: "fonts\\.googleapis\\.com.*JetBrains" + - from: "apps/web/src/index.css" + to: "all CSS files" + via: "CSS variable inheritance" + pattern: "--color-|--font-|--spacing-" +--- + + +Establish design tokens and typography foundation for terminal/hacker aesthetic. + +Purpose: All subsequent styling plans depend on these CSS variables and font being available. This plan creates the foundation that enables consistent styling across all components. + +Output: Design tokens in :root, JetBrains Mono font loaded, base dark theme applied. + + + +@./.claude/get-shit-done/workflows/execute-plan.md +@./.claude/get-shit-done/templates/summary.md + + + +@.planning/PROJECT.md +@.planning/ROADMAP.md +@.planning/phases/06.2-restyle-app-with-pencil-design/06.2-CONTEXT.md +@.planning/phases/06.2-restyle-app-with-pencil-design/06.2-RESEARCH.md + + + + + + Task 1: Add JetBrains Mono font to index.html + apps/web/index.html + +Add Google Fonts preconnect and stylesheet links in the `` section, BEFORE the `` tag: + +```html +<!-- Preconnect to Google Fonts --> +<link rel="preconnect" href="https://fonts.googleapis.com"> +<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> + +<!-- Load JetBrains Mono (400, 600, 700 weights) --> +<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;600;700&display=swap" rel="stylesheet"> +``` + +Weights needed per design: +- 400 (normal) - body text, breadcrumbs, user email +- 600 (semibold) - app name, column headers, button text +- 700 (bold) - prompt symbol `>` + </action> + <verify>Open apps/web/index.html and confirm the font links are present before the title tag</verify> + <done>JetBrains Mono font links present in HTML head with preconnect for fast loading</done> +</task> + +<task type="auto"> + <name>Task 2: Create design tokens in index.css</name> + <files>apps/web/src/index.css</files> + <action> +Replace the entire index.css with design tokens and base styles. Remove the old Inter font family and gray backgrounds. + +```css +/* ========================================================================== + Design Tokens - Terminal/Hacker Aesthetic + ========================================================================== */ + +:root { + /* Color Primitives */ + --color-black: #000000; + --color-green-primary: #00D084; + --color-green-dim: #006644; + --color-green-darker: #003322; + --color-green-glow: #00D08466; /* 40% opacity for shadows */ + + /* Semantic Colors - Error/Warning */ + --color-error: #EF4444; + --color-error-dim: #7F1D1D; + --color-warning: #F59E0B; + --color-warning-dim: #78350F; + + /* Background & Text */ + --color-background: var(--color-black); + --color-border: var(--color-green-primary); + --color-border-dim: var(--color-green-darker); + --color-text-primary: var(--color-green-primary); + --color-text-secondary: var(--color-green-dim); + + /* Typography */ + --font-family-mono: "JetBrains Mono", monospace; + --font-size-xs: 10px; /* Status text */ + --font-size-sm: 11px; /* Body, buttons, file list */ + --font-size-md: 14px; /* App name */ + --font-size-lg: 18px; /* Prompt symbol */ + --font-size-xl: 24px; /* Login logo */ + + /* Font Weights */ + --font-weight-normal: 400; + --font-weight-semibold: 600; + --font-weight-bold: 700; + + /* Spacing (from design file) */ + --spacing-xs: 8px; + --spacing-sm: 12px; + --spacing-md: 16px; + --spacing-lg: 24px; + --spacing-xl: 32px; + + /* Effects */ + --glow-green: 0 0 10px var(--color-green-glow); + --border-thickness: 1px; + + /* Remove color-scheme to enforce dark mode only */ + color-scheme: dark; +} + +/* ========================================================================== + Global Resets + ========================================================================== */ + +* { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +/* ========================================================================== + Base Styles + ========================================================================== */ + +html { + font-family: var(--font-family-mono); + font-size: var(--font-size-sm); + line-height: 1.5; + font-weight: var(--font-weight-normal); + color: var(--color-text-primary); + background-color: var(--color-background); + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +body { + min-height: 100vh; +} + +#root { + width: 100%; + min-height: 100vh; +} + +/* Links */ +a { + color: var(--color-text-primary); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +/* Focus styles for accessibility */ +:focus-visible { + outline: 2px solid var(--color-green-primary); + outline-offset: 2px; +} + +/* Selection */ +::selection { + background-color: var(--color-green-primary); + color: var(--color-black); +} +``` + +Key changes from old index.css: +- Remove Inter font, use JetBrains Mono exclusively +- Remove `place-items: center` from body (was centering content) +- Change background from #242424 to pure black #000000 +- Change text color to green #00D084 +- Add all design tokens as CSS variables + </action> + <verify>Run `grep -c "JetBrains Mono" apps/web/src/index.css` - should return 1. Run `grep -c "#00D084" apps/web/src/index.css` - should return at least 1.</verify> + <done>index.css contains complete design token system with colors, typography, spacing, and effects</done> +</task> + +<task type="auto"> + <name>Task 3: Restyle login page in App.css</name> + <files>apps/web/src/App.css</files> + <action> +Update App.css to restyle the login page to terminal aesthetic. Keep the CSS imports at the top. Replace login-related styles with new terminal design. + +Update these sections: + +1. Keep the CSS imports at the very top (unchanged): +```css +/* Import component styles */ +@import './styles/file-browser.css'; +@import './styles/breadcrumbs.css'; +@import './styles/responsive.css'; +``` + +2. Replace `.login-container` and related styles with: +```css +/* ========================================================================== + Login Page - Terminal Aesthetic + ========================================================================== */ + +.login-container { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + min-height: 100vh; + padding: var(--spacing-lg); + text-align: center; + position: relative; + overflow: hidden; +} + +/* Logo: > CIPHERBOX with terminal prompt */ +.login-container h1 { + font-family: var(--font-family-mono); + font-size: var(--font-size-xl); + font-weight: var(--font-weight-bold); + color: var(--color-text-primary); + margin-bottom: var(--spacing-xs); + letter-spacing: 0.05em; +} + +.login-container h1::before { + content: "> "; + color: var(--color-text-primary); +} + +/* Tagline */ +.login-container .tagline { + font-size: var(--font-size-sm); + color: var(--color-text-secondary); + margin-bottom: var(--spacing-md); + text-transform: uppercase; + letter-spacing: 0.1em; +} + +.login-container .login-description { + font-size: var(--font-size-sm); + color: var(--color-text-secondary); + margin-bottom: var(--spacing-lg); + max-width: 400px; +} + +/* Terminal-style connect button */ +.login-button { + padding: var(--spacing-sm) var(--spacing-lg); + font-family: var(--font-family-mono); + font-size: var(--font-size-sm); + font-weight: var(--font-weight-semibold); + background-color: var(--color-green-primary); + color: var(--color-black); + border: none; + border-radius: 0; /* Sharp corners for terminal aesthetic */ + cursor: pointer; + transition: box-shadow 0.2s ease, transform 0.1s ease; + text-transform: uppercase; + letter-spacing: 0.05em; +} + +.login-button:hover { + box-shadow: var(--glow-green); + transform: translateY(-1px); +} + +.login-button:active { + transform: translateY(0); +} + +.login-button:disabled { + opacity: 0.6; + cursor: not-allowed; +} + +.login-note { + margin-top: var(--spacing-lg); + font-size: var(--font-size-xs); + color: var(--color-text-secondary); +} +``` + +3. Update dashboard styles to use design tokens: +```css +/* ========================================================================== + Dashboard Layout + ========================================================================== */ + +.dashboard-container { + display: flex; + flex-direction: column; + min-height: 100vh; + background-color: var(--color-background); +} + +.dashboard-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: var(--spacing-sm) var(--spacing-md); + border-bottom: var(--border-thickness) solid var(--color-border); + background-color: var(--color-background); +} + +/* Header branding: > CIPHERBOX */ +.dashboard-header h1, +.dashboard-header .app-title { + font-family: var(--font-family-mono); + font-size: var(--font-size-md); + font-weight: var(--font-weight-semibold); + color: var(--color-text-primary); +} + +.logout-link { + font-family: var(--font-family-mono); + font-size: var(--font-size-sm); + color: var(--color-text-secondary); + text-decoration: none; + text-transform: lowercase; +} + +.logout-link:hover { + color: var(--color-text-primary); + text-decoration: none; +} + +.dashboard-main { + display: flex; + flex: 1; + background-color: var(--color-background); +} + +.placeholder-text { + color: var(--color-text-secondary); + font-style: normal; + margin-top: var(--spacing-md); +} +``` + +4. Update API Status Indicator to use design tokens: +```css +/* ========================================================================== + API Status Indicator + ========================================================================== */ + +.api-status { + position: fixed; + bottom: var(--spacing-md); + right: var(--spacing-md); + display: flex; + align-items: center; + gap: var(--spacing-xs); + font-family: var(--font-family-mono); + font-size: var(--font-size-xs); + color: var(--color-text-secondary); + text-transform: lowercase; +} + +.status-dot { + width: 8px; + height: 8px; + border-radius: 50%; +} + +.status-dot.online { + background-color: var(--color-green-primary); + box-shadow: 0 0 6px var(--color-green-primary); +} + +.status-dot.offline { + background-color: var(--color-error); + box-shadow: 0 0 6px var(--color-error); +} + +.status-dot.loading { + background-color: var(--color-text-secondary); +} +``` + </action> + <verify>Run `pnpm --filter web dev` and visually check the login page loads with black background, green text, and JetBrains Mono font</verify> + <done>Login page displays terminal aesthetic with > CIPHERBOX branding, green-on-black theme, and [CONNECT] style button</done> +</task> + +</tasks> + +<verification> +1. `pnpm --filter web dev` starts without errors +2. Login page shows: + - Black background (#000000) + - Green text (#00D084) + - JetBrains Mono font (monospace) + - "> CIPHERBOX" title with prompt + - Green connect button with sharp corners +3. Browser DevTools shows JetBrains Mono loaded in Network tab +4. CSS variables are visible in :root when inspecting any element +</verification> + +<success_criteria> +- JetBrains Mono font loads successfully from Google Fonts CDN +- All design tokens defined as CSS custom properties in :root +- Login page displays terminal/hacker aesthetic (dark mode, green accents) +- No console errors or font loading failures +- Existing functionality unchanged (login still works) +</success_criteria> + +<output> +After completion, create `.planning/phases/06.2-restyle-app-with-pencil-design/06.2-01-SUMMARY.md` +</output> diff --git a/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-02-PLAN.md b/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-02-PLAN.md new file mode 100644 index 0000000000..2d6d2e5e72 --- /dev/null +++ b/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-02-PLAN.md @@ -0,0 +1,592 @@ +--- +phase: 06.2-restyle-app-pencil-design +plan: 02 +type: execute +wave: 2 +depends_on: ["06.2-01"] +files_modified: + - apps/web/src/styles/file-browser.css + - apps/web/src/styles/breadcrumbs.css +autonomous: true + +must_haves: + truths: + - "File browser sidebar has green border on right edge" + - "File list shows green column headers (NAME, SIZE, TYPE, MODIFIED)" + - "File list items have green text and dim green borders between rows" + - "Breadcrumbs display terminal-style path navigation" + - "Folder tree items highlight with green on hover/active" + artifacts: + - path: "apps/web/src/styles/file-browser.css" + provides: "Terminal-styled file browser layout" + contains: "var(--color-green-primary)" + - path: "apps/web/src/styles/breadcrumbs.css" + provides: "Terminal-styled breadcrumb navigation" + contains: "var(--color-text-primary)" + key_links: + - from: "apps/web/src/styles/file-browser.css" + to: "apps/web/src/index.css" + via: "CSS variable references" + pattern: "var\\(--color-|var\\(--font-|var\\(--spacing-" +--- + +<objective> +Restyle the file browser layout, sidebar, file list, and breadcrumbs to match terminal aesthetic. + +Purpose: The file browser is the main UI users interact with. This plan transforms it from the current gray/white theme to the green-on-black terminal design specified in the Pencil design file. + +Output: Terminal-styled file browser with green borders, monospace text, and proper design token usage. +</objective> + +<execution_context> +@./.claude/get-shit-done/workflows/execute-plan.md +@./.claude/get-shit-done/templates/summary.md +</execution_context> + +<context> +@.planning/PROJECT.md +@.planning/ROADMAP.md +@.planning/phases/06.2-restyle-app-with-pencil-design/06.2-CONTEXT.md +@.planning/phases/06.2-restyle-app-with-pencil-design/06.2-RESEARCH.md +@.planning/phases/06.2-restyle-app-with-pencil-design/06.2-01-SUMMARY.md +</context> + +<tasks> + +<task type="auto"> + <name>Task 1: Restyle file-browser.css with terminal aesthetic</name> + <files>apps/web/src/styles/file-browser.css</files> + <action> +Replace the entire file-browser.css with terminal-styled version using design tokens. + +```css +/** + * File Browser Component Styles - Terminal Aesthetic + * + * Styling for the file browser UI including: + * - Main layout (sidebar + content) + * - Folder tree navigation + * - File list with columns + * - Empty state drop zone + */ + +/* ========================================================================== + File Browser Layout + ========================================================================== */ + +.file-browser { + display: flex; + flex: 1; + min-height: 0; + background-color: var(--color-background); +} + +.file-browser-sidebar { + width: 250px; + min-width: 200px; + max-width: 350px; + border-right: var(--border-thickness) solid var(--color-border); + overflow-y: auto; + background-color: var(--color-background); +} + +.file-browser-main { + flex: 1; + min-width: 0; + overflow-y: auto; + padding: var(--spacing-md); + background-color: var(--color-background); +} + +.file-browser-toolbar { + display: flex; + align-items: center; + gap: var(--spacing-md); + padding-bottom: var(--spacing-md); + border-bottom: var(--border-thickness) solid var(--color-border-dim); + margin-bottom: var(--spacing-md); +} + +/* Toolbar buttons - Terminal flag style */ +.file-browser-toolbar button, +.toolbar-button { + padding: var(--spacing-xs) var(--spacing-md); + font-family: var(--font-family-mono); + font-size: var(--font-size-sm); + font-weight: var(--font-weight-normal); + border-radius: 0; + cursor: pointer; + transition: box-shadow 0.15s ease; +} + +/* Primary action button (--upload) */ +.toolbar-button--primary, +.file-browser-toolbar .btn-primary { + background-color: var(--color-green-primary); + color: var(--color-black); + border: none; + font-weight: var(--font-weight-semibold); +} + +.toolbar-button--primary:hover, +.file-browser-toolbar .btn-primary:hover { + box-shadow: var(--glow-green); +} + +/* Secondary action buttons (--new-dir, --refresh) */ +.toolbar-button--secondary, +.file-browser-toolbar .btn-secondary { + background-color: transparent; + color: var(--color-text-primary); + border: var(--border-thickness) solid var(--color-border); +} + +.toolbar-button--secondary:hover, +.file-browser-toolbar .btn-secondary:hover { + box-shadow: var(--glow-green); +} + +.file-browser-loading { + display: flex; + align-items: center; + justify-content: center; + height: 200px; + color: var(--color-text-secondary); + font-family: var(--font-family-mono); +} + +.file-browser-loading-spinner { + font-size: var(--font-size-sm); +} + +/* ========================================================================== + Folder Tree + ========================================================================== */ + +.folder-tree { + display: flex; + flex-direction: column; + height: 100%; +} + +.folder-tree-header { + padding: var(--spacing-md); + border-bottom: var(--border-thickness) solid var(--color-border-dim); +} + +.folder-tree-title { + margin: 0; + font-family: var(--font-family-mono); + font-size: var(--font-size-xs); + font-weight: var(--font-weight-semibold); + text-transform: uppercase; + letter-spacing: 0.1em; + color: var(--color-text-secondary); +} + +.folder-tree-content { + flex: 1; + overflow-y: auto; + padding: var(--spacing-xs) 0; +} + +.folder-tree-placeholder { + padding: var(--spacing-md); + color: var(--color-text-secondary); + font-style: normal; + font-size: var(--font-size-sm); +} + +/* Folder Tree Node */ +.folder-tree-node { + user-select: none; +} + +.folder-tree-item { + display: flex; + align-items: center; + gap: var(--spacing-xs); + padding: var(--spacing-xs) var(--spacing-sm); + cursor: pointer; + transition: background-color 0.15s ease; + border-radius: 0; + margin: 0 var(--spacing-xs); + border-left: 2px solid transparent; +} + +.folder-tree-item:hover { + background-color: var(--color-green-darker); + border-left-color: var(--color-green-dim); +} + +.folder-tree-item--active { + background-color: var(--color-green-darker); + border-left-color: var(--color-green-primary); +} + +.folder-tree-item--active:hover { + background-color: var(--color-green-darker); +} + +.folder-tree-item--drag-over { + background-color: var(--color-green-darker); + border-left-color: var(--color-green-primary); + box-shadow: inset 0 0 0 1px var(--color-green-dim); +} + +.folder-tree-toggle { + width: 16px; + flex-shrink: 0; + font-size: 10px; + color: var(--color-text-secondary); + cursor: pointer; +} + +.folder-tree-toggle--hidden { + visibility: hidden; +} + +.folder-tree-icon { + font-size: var(--font-size-sm); + flex-shrink: 0; + color: var(--color-text-primary); +} + +.folder-tree-name { + flex: 1; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + font-family: var(--font-family-mono); + font-size: var(--font-size-sm); + color: var(--color-text-primary); +} + +.folder-tree-loading { + color: var(--color-text-secondary); + font-size: var(--font-size-xs); + margin-left: auto; +} + +/* ========================================================================== + File List + ========================================================================== */ + +.file-list { + display: flex; + flex-direction: column; + border: var(--border-thickness) solid var(--color-border); +} + +.file-list-header { + display: grid; + grid-template-columns: 1fr 120px 120px 180px; + gap: var(--spacing-md); + padding: var(--spacing-sm) var(--spacing-md); + border-bottom: var(--border-thickness) solid var(--color-border); + font-family: var(--font-family-mono); + font-size: var(--font-size-xs); + font-weight: var(--font-weight-semibold); + text-transform: uppercase; + letter-spacing: 0.1em; + color: var(--color-text-primary); + background-color: var(--color-background); +} + +.file-list-body { + /* Container for file items */ +} + +/* File List Item */ +.file-list-item { + display: grid; + grid-template-columns: 1fr 120px 120px 180px; + gap: var(--spacing-md); + padding: var(--spacing-sm) var(--spacing-md); + cursor: pointer; + transition: background-color 0.15s ease; + border-bottom: var(--border-thickness) solid var(--color-border-dim); + font-family: var(--font-family-mono); +} + +.file-list-item:last-child { + border-bottom: none; +} + +.file-list-item:hover { + background-color: var(--color-green-darker); +} + +.file-list-item--selected { + background-color: var(--color-green-darker); + border-left: 2px solid var(--color-green-primary); +} + +.file-list-item--selected:hover { + background-color: var(--color-green-darker); +} + +.file-list-item-name { + display: flex; + align-items: center; + gap: var(--spacing-xs); + min-width: 0; +} + +.file-list-item-icon { + font-family: var(--font-family-mono); + font-size: var(--font-size-sm); + flex-shrink: 0; + color: var(--color-text-primary); +} + +.file-list-item-text { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + color: var(--color-text-primary); + font-size: var(--font-size-sm); +} + +.file-list-item-size { + display: flex; + align-items: center; + color: var(--color-text-secondary); + font-size: var(--font-size-sm); +} + +.file-list-item-type { + display: flex; + align-items: center; + color: var(--color-text-secondary); + font-size: var(--font-size-sm); + text-transform: lowercase; +} + +.file-list-item-date { + display: flex; + align-items: center; + color: var(--color-text-secondary); + font-size: var(--font-size-sm); +} + +/* ========================================================================== + Empty State + ========================================================================== */ + +.empty-state { + display: flex; + align-items: center; + justify-content: center; + min-height: 300px; + border: var(--border-thickness) dashed var(--color-border); + border-radius: 0; + margin: var(--spacing-lg); + cursor: pointer; + transition: border-color 0.2s ease, background-color 0.2s ease; +} + +.empty-state:hover { + border-color: var(--color-green-primary); + background-color: var(--color-green-darker); +} + +.empty-state-content { + text-align: center; + padding: var(--spacing-lg); +} + +.empty-state-icon { + font-size: 2rem; + display: block; + margin-bottom: var(--spacing-md); + color: var(--color-text-secondary); +} + +.empty-state-text { + font-family: var(--font-family-mono); + font-size: var(--font-size-sm); + margin: 0 0 var(--spacing-xs) 0; + color: var(--color-text-primary); +} + +.empty-state-hint { + font-family: var(--font-family-mono); + font-size: var(--font-size-xs); + margin: 0; + color: var(--color-text-secondary); +} + +.empty-state-upload { + margin-top: var(--spacing-md); +} + +/* Note: Mobile responsive styles are in responsive.css */ +``` + +Key changes: +- Replace all rgba() colors with CSS variables +- Remove border-radius (use 0 for terminal aesthetic) +- Use design token spacing variables +- Add 4-column grid for file list (NAME, SIZE, TYPE, MODIFIED) +- Add green border around file list +- Add left border highlight for selected/active items + </action> + <verify>Check file contains `var(--color-green-primary)` and `grid-template-columns: 1fr 120px 120px 180px`</verify> + <done>File browser CSS uses design tokens, has green borders, and shows 4-column layout per design</done> +</task> + +<task type="auto"> + <name>Task 2: Restyle breadcrumbs.css with terminal aesthetic</name> + <files>apps/web/src/styles/breadcrumbs.css</files> + <action> +Replace the entire breadcrumbs.css with terminal-styled version using design tokens. + +```css +/** + * Breadcrumb Navigation Styles - Terminal Aesthetic + * + * Per design: Terminal-style path display like ~/storage/documents/projects + * Shows current folder path with back navigation + */ + +/* ========================================================================== + Breadcrumbs Container + ========================================================================== */ + +.breadcrumbs { + display: flex; + align-items: center; + gap: var(--spacing-xs); + padding: var(--spacing-xs) 0; + font-family: var(--font-family-mono); + font-size: var(--font-size-sm); + min-height: 2.5rem; + color: var(--color-text-primary); +} + +/* Terminal-style path prefix */ +.breadcrumbs::before { + content: "~/"; + color: var(--color-text-secondary); +} + +/* ========================================================================== + Back Button + ========================================================================== */ + +.breadcrumbs-back { + display: flex; + align-items: center; + justify-content: center; + width: 2rem; + height: 2rem; + padding: 0; + background-color: transparent; + border: var(--border-thickness) solid var(--color-border); + border-radius: 0; + color: var(--color-text-primary); + cursor: pointer; + transition: background-color 0.15s ease, box-shadow 0.15s ease; +} + +.breadcrumbs-back:hover { + background-color: var(--color-green-darker); + box-shadow: var(--glow-green); +} + +.breadcrumbs-back:focus { + outline: 2px solid var(--color-green-primary); + outline-offset: 2px; +} + +.breadcrumbs-back:active { + background-color: var(--color-green-darker); +} + +.breadcrumbs-back-icon { + font-size: var(--font-size-sm); + line-height: 1; +} + +/* ========================================================================== + Path Segments + ========================================================================== */ + +.breadcrumbs-separator { + color: var(--color-text-secondary); +} + +.breadcrumbs-segment { + color: var(--color-text-secondary); + transition: color 0.15s ease; +} + +.breadcrumbs-segment:hover { + color: var(--color-text-primary); + cursor: pointer; +} + +/* ========================================================================== + Current Folder Name + ========================================================================== */ + +.breadcrumbs-current { + font-weight: var(--font-weight-semibold); + color: var(--color-text-primary); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 300px; +} + +/* ========================================================================== + Mobile Responsive + ========================================================================== */ + +@media (max-width: 768px) { + .breadcrumbs { + padding: var(--spacing-xs); + } + + .breadcrumbs-current { + max-width: 200px; + font-size: var(--font-size-sm); + } +} +``` + +Key changes: +- Add `~/` prefix before path for terminal feel +- Remove border-radius from back button +- Use design token variables for all values +- Keep green color scheme consistent + </action> + <verify>Check file contains `content: "~/";` and `var(--color-text-primary)`</verify> + <done>Breadcrumbs display terminal-style path with ~/ prefix and green accents</done> +</task> + +</tasks> + +<verification> +1. Navigate to file browser after login +2. Verify sidebar has green right border +3. Verify file list has green border around it +4. Verify column headers show NAME, SIZE, TYPE, MODIFIED in green +5. Verify folder tree items highlight green on hover +6. Verify breadcrumbs show terminal-style path +7. No console errors +</verification> + +<success_criteria> +- File browser layout uses design tokens throughout +- Green borders visible on sidebar and file list +- Column headers match design (green, uppercase, monospace) +- Hover states show green highlights +- Breadcrumbs display terminal-style path navigation +- All existing functionality preserved +</success_criteria> + +<output> +After completion, create `.planning/phases/06.2-restyle-app-with-pencil-design/06.2-02-SUMMARY.md` +</output> diff --git a/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-03-PLAN.md b/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-03-PLAN.md new file mode 100644 index 0000000000..943e869fb3 --- /dev/null +++ b/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-03-PLAN.md @@ -0,0 +1,821 @@ +--- +phase: 06.2-restyle-app-pencil-design +plan: 03 +type: execute +wave: 2 +depends_on: ["06.2-01"] +files_modified: + - apps/web/src/styles/context-menu.css + - apps/web/src/styles/dialogs.css + - apps/web/src/styles/modal.css + - apps/web/src/styles/upload.css +autonomous: true + +must_haves: + truths: + - "Context menus have green border and black background" + - "Dialogs use monospace font and green accents" + - "Modal overlays have terminal-style appearance" + - "Upload zone and progress use green color scheme" + - "All interactive elements show green glow on hover/focus" + artifacts: + - path: "apps/web/src/styles/context-menu.css" + provides: "Terminal-styled context menu" + contains: "var(--color-border)" + - path: "apps/web/src/styles/dialogs.css" + provides: "Terminal-styled dialog components" + contains: "var(--font-family-mono)" + - path: "apps/web/src/styles/modal.css" + provides: "Terminal-styled modal overlay" + contains: "var(--color-green-primary)" + - path: "apps/web/src/styles/upload.css" + provides: "Terminal-styled upload UI" + contains: "var(--color-text-primary)" + key_links: + - from: "apps/web/src/styles/*.css" + to: "apps/web/src/index.css" + via: "CSS variable references" + pattern: "var\\(--" +--- + +<objective> +Restyle context menus, dialogs, modals, and upload UI to match terminal aesthetic. + +Purpose: These overlay components need consistent styling with the main UI. They appear during user interactions (right-click, file operations, uploads) and must maintain the green-on-black terminal theme. + +Output: Terminal-styled overlays with green borders, monospace text, and proper design token usage throughout. +</objective> + +<execution_context> +@./.claude/get-shit-done/workflows/execute-plan.md +@./.claude/get-shit-done/templates/summary.md +</execution_context> + +<context> +@.planning/PROJECT.md +@.planning/ROADMAP.md +@.planning/phases/06.2-restyle-app-with-pencil-design/06.2-CONTEXT.md +@.planning/phases/06.2-restyle-app-with-pencil-design/06.2-RESEARCH.md +@.planning/phases/06.2-restyle-app-with-pencil-design/06.2-01-SUMMARY.md +</context> + +<tasks> + +<task type="auto"> + <name>Task 1: Restyle context-menu.css</name> + <files>apps/web/src/styles/context-menu.css</files> + <action> +Replace the entire context-menu.css with terminal-styled version. Remove light mode and prefers-color-scheme queries. + +```css +/** + * Context Menu Styles - Terminal Aesthetic + * + * Right-click menu for file/folder actions + * Green border, black background, monospace font + */ + +/* ========================================================================== + Context Menu Container + ========================================================================== */ + +.context-menu { + position: absolute; + z-index: 1100; + min-width: 180px; + padding: var(--spacing-xs) 0; + overflow: hidden; + background-color: var(--color-background); + border: var(--border-thickness) solid var(--color-border); + border-radius: 0; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5), var(--glow-green); +} + +/* ========================================================================== + Menu Item + ========================================================================== */ + +.context-menu-item { + display: flex; + align-items: center; + gap: var(--spacing-xs); + width: 100%; + padding: var(--spacing-xs) var(--spacing-sm); + font-family: var(--font-family-mono); + font-size: var(--font-size-sm); + color: var(--color-text-primary); + text-align: left; + cursor: pointer; + background: transparent; + border: none; + transition: background-color 0.15s ease; +} + +.context-menu-item:hover, +.context-menu-item:focus { + background-color: var(--color-green-darker); + outline: none; +} + +.context-menu-item:focus-visible { + outline: 2px solid var(--color-green-primary); + outline-offset: -2px; +} + +/* ========================================================================== + Menu Item Icon + ========================================================================== */ + +.context-menu-item-icon { + display: inline-flex; + align-items: center; + justify-content: center; + width: 16px; + font-size: var(--font-size-sm); + color: var(--color-text-secondary); +} + +/* ========================================================================== + Destructive Action (Delete) + ========================================================================== */ + +.context-menu-item--destructive { + color: var(--color-error); +} + +.context-menu-item--destructive .context-menu-item-icon { + color: var(--color-error); +} + +.context-menu-item--destructive:hover, +.context-menu-item--destructive:focus { + background-color: var(--color-error-dim); +} + +/* ========================================================================== + Divider + ========================================================================== */ + +.context-menu-divider { + height: 1px; + margin: var(--spacing-xs) 0; + background-color: var(--color-border-dim); +} +``` + +Key changes: +- Remove all light mode CSS and prefers-color-scheme queries +- Use design token variables +- Remove border-radius +- Add green glow to box-shadow + </action> + <verify>Check file does NOT contain `@media (prefers-color-scheme` and contains `var(--color-border)`</verify> + <done>Context menu has terminal styling with green border, black background, no light mode</done> +</task> + +<task type="auto"> + <name>Task 2: Restyle dialogs.css</name> + <files>apps/web/src/styles/dialogs.css</files> + <action> +Replace the entire dialogs.css with terminal-styled version. Remove light mode defaults and prefers-color-scheme queries. + +```css +/** + * Dialog Styles - Terminal Aesthetic + * + * Dialog content for rename, delete confirmation, etc. + * Green accents, monospace font, dark only + */ + +/* ========================================================================== + Dialog Content + ========================================================================== */ + +.dialog-content { + display: flex; + flex-direction: column; + gap: var(--spacing-md); +} + +/* ========================================================================== + Dialog Message + ========================================================================== */ + +.dialog-message { + margin: 0; + font-family: var(--font-family-mono); + font-size: var(--font-size-sm); + line-height: 1.6; + color: var(--color-text-primary); +} + +/* ========================================================================== + Dialog Field + ========================================================================== */ + +.dialog-field { + display: flex; + flex-direction: column; + gap: var(--spacing-xs); +} + +/* ========================================================================== + Dialog Label + ========================================================================== */ + +.dialog-label { + font-family: var(--font-family-mono); + font-size: var(--font-size-xs); + font-weight: var(--font-weight-semibold); + text-transform: uppercase; + letter-spacing: 0.05em; + color: var(--color-text-secondary); +} + +/* ========================================================================== + Dialog Input + ========================================================================== */ + +.dialog-input { + width: 100%; + padding: var(--spacing-xs) var(--spacing-sm); + font-family: var(--font-family-mono); + font-size: var(--font-size-sm); + line-height: 1.5; + color: var(--color-text-primary); + background-color: var(--color-background); + border: var(--border-thickness) solid var(--color-border); + border-radius: 0; + outline: none; + transition: border-color 0.15s ease, box-shadow 0.15s ease; +} + +.dialog-input:focus { + border-color: var(--color-green-primary); + box-shadow: var(--glow-green); +} + +.dialog-input--error { + border-color: var(--color-error); +} + +.dialog-input--error:focus { + border-color: var(--color-error); + box-shadow: 0 0 10px rgba(239, 68, 68, 0.4); +} + +.dialog-input:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.dialog-input::placeholder { + color: var(--color-text-secondary); +} + +/* ========================================================================== + Dialog Error + ========================================================================== */ + +.dialog-error { + font-family: var(--font-family-mono); + font-size: var(--font-size-xs); + color: var(--color-error); +} + +/* ========================================================================== + Dialog Actions + ========================================================================== */ + +.dialog-actions { + display: flex; + gap: var(--spacing-sm); + justify-content: flex-end; + margin-top: var(--spacing-xs); +} + +/* ========================================================================== + Dialog Button Base + ========================================================================== */ + +.dialog-button { + display: inline-flex; + align-items: center; + justify-content: center; + padding: var(--spacing-xs) var(--spacing-md); + font-family: var(--font-family-mono); + font-size: var(--font-size-sm); + font-weight: var(--font-weight-normal); + line-height: 1.5; + border: none; + border-radius: 0; + cursor: pointer; + transition: background-color 0.15s ease, box-shadow 0.15s ease; +} + +.dialog-button:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.dialog-button:focus-visible { + outline: 2px solid var(--color-green-primary); + outline-offset: 2px; +} + +/* ========================================================================== + Secondary Button (Cancel) + ========================================================================== */ + +.dialog-button--secondary { + color: var(--color-text-primary); + background-color: transparent; + border: var(--border-thickness) solid var(--color-border); +} + +.dialog-button--secondary:hover:not(:disabled) { + background-color: var(--color-green-darker); + box-shadow: var(--glow-green); +} + +/* ========================================================================== + Primary Button (Confirm) + ========================================================================== */ + +.dialog-button--primary { + color: var(--color-black); + background-color: var(--color-green-primary); + font-weight: var(--font-weight-semibold); +} + +.dialog-button--primary:hover:not(:disabled) { + box-shadow: var(--glow-green); +} + +/* ========================================================================== + Destructive Button (Delete) + ========================================================================== */ + +.dialog-button--destructive { + color: var(--color-black); + background-color: var(--color-error); + font-weight: var(--font-weight-semibold); +} + +.dialog-button--destructive:hover:not(:disabled) { + box-shadow: 0 0 10px rgba(239, 68, 68, 0.6); +} +``` + +Key changes: +- Remove ALL light mode CSS (:root defaults and @media prefers-color-scheme) +- Use design token variables throughout +- Remove border-radius on all elements +- Add green glow effects on focus/hover + </action> + <verify>Check file does NOT contain `@media (prefers-color-scheme` and does NOT contain `#ffffff`</verify> + <done>Dialog styles use terminal aesthetic with green accents, no light mode</done> +</task> + +<task type="auto"> + <name>Task 3: Restyle modal.css and upload.css</name> + <files>apps/web/src/styles/modal.css, apps/web/src/styles/upload.css</files> + <action> +First, replace modal.css: + +```css +/** + * Modal Styles - Terminal Aesthetic + * + * Modal overlay and container for dialogs + * Green border, black background, terminal feel + */ + +/* ========================================================================== + Modal Backdrop + ========================================================================== */ + +.modal-backdrop { + position: fixed; + inset: 0; + z-index: 1000; + display: flex; + align-items: center; + justify-content: center; + background-color: rgba(0, 0, 0, 0.8); + backdrop-filter: blur(4px); +} + +/* ========================================================================== + Modal Container + ========================================================================== */ + +.modal-container { + position: relative; + width: 100%; + max-width: 500px; + max-height: 90vh; + margin: var(--spacing-md); + overflow: hidden; + background-color: var(--color-background); + border: var(--border-thickness) solid var(--color-border); + border-radius: 0; + box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5), var(--glow-green); +} + +/* ========================================================================== + Modal Header + ========================================================================== */ + +.modal-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: var(--spacing-md); + border-bottom: var(--border-thickness) solid var(--color-border-dim); +} + +.modal-title { + margin: 0; + font-family: var(--font-family-mono); + font-size: var(--font-size-sm); + font-weight: var(--font-weight-semibold); + text-transform: uppercase; + letter-spacing: 0.05em; + color: var(--color-text-primary); +} + +/* ========================================================================== + Modal Close Button + ========================================================================== */ + +.modal-close { + display: flex; + align-items: center; + justify-content: center; + width: 2rem; + height: 2rem; + padding: 0; + margin-left: auto; + font-size: 1.25rem; + font-weight: var(--font-weight-normal); + line-height: 1; + color: var(--color-text-secondary); + cursor: pointer; + background: transparent; + border: var(--border-thickness) solid var(--color-border); + border-radius: 0; + transition: background-color 0.15s ease, color 0.15s ease; +} + +.modal-close:hover { + background-color: var(--color-green-darker); + color: var(--color-text-primary); +} + +.modal-close:focus { + outline: 2px solid var(--color-green-primary); + outline-offset: 2px; +} + +/* ========================================================================== + Modal Body + ========================================================================== */ + +.modal-body { + padding: var(--spacing-md); + overflow-y: auto; + max-height: calc(90vh - 80px); + color: var(--color-text-primary); +} +``` + +Then, replace upload.css: + +```css +/** + * Upload Styles - Terminal Aesthetic + * + * Upload zone (drag-drop) and upload modal progress + * Green accents, terminal feel + */ + +/* ========================================================================== + Upload Zone + ========================================================================== */ + +.upload-zone-wrapper { + width: 100%; +} + +.upload-zone { + display: flex; + align-items: center; + justify-content: center; + min-height: 120px; + padding: var(--spacing-lg); + border: var(--border-thickness) dashed var(--color-border); + border-radius: 0; + background-color: var(--color-background); + cursor: pointer; + transition: border-color 0.15s ease, background-color 0.15s ease; +} + +.upload-zone:hover { + border-color: var(--color-green-primary); + background-color: var(--color-green-darker); +} + +.upload-zone:focus-within { + outline: 2px solid var(--color-green-primary); + outline-offset: 2px; +} + +/* Active drop state */ +.upload-zone-active { + border-color: var(--color-green-primary); + border-style: solid; + background-color: var(--color-green-darker); + box-shadow: var(--glow-green); +} + +/* Uploading state */ +.upload-zone-uploading { + cursor: default; + opacity: 0.7; +} + +/* Content */ +.upload-zone-content { + display: flex; + flex-direction: column; + align-items: center; + gap: var(--spacing-xs); + text-align: center; + color: var(--color-text-secondary); +} + +.upload-zone-icon { + font-size: 2rem; + line-height: 1; + color: var(--color-text-secondary); +} + +.upload-zone-text { + margin: 0; + font-family: var(--font-family-mono); + font-size: var(--font-size-sm); + color: var(--color-text-primary); +} + +/* Error message */ +.upload-zone-error { + display: flex; + align-items: center; + justify-content: space-between; + gap: var(--spacing-xs); + margin-top: var(--spacing-xs); + padding: var(--spacing-sm); + font-family: var(--font-family-mono); + font-size: var(--font-size-xs); + color: var(--color-error); + background-color: var(--color-error-dim); + border: var(--border-thickness) solid var(--color-error); + border-radius: 0; +} + +.upload-zone-error-dismiss { + padding: 0; + font-size: 1rem; + font-weight: var(--font-weight-normal); + line-height: 1; + color: inherit; + cursor: pointer; + background: transparent; + border: none; + opacity: 0.7; +} + +.upload-zone-error-dismiss:hover { + opacity: 1; +} + +/* ========================================================================== + Upload Modal + ========================================================================== */ + +.upload-modal-content { + min-width: 400px; +} + +.upload-modal-progress { + margin-bottom: var(--spacing-md); +} + +.upload-modal-overall { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: var(--spacing-xs); + font-family: var(--font-family-mono); + font-size: var(--font-size-xs); + color: var(--color-text-secondary); +} + +/* Upload item list */ +.upload-item-list { + display: flex; + flex-direction: column; + gap: var(--spacing-sm); + max-height: 300px; + overflow-y: auto; +} + +/* Individual upload item */ +.upload-item { + display: flex; + flex-direction: column; + gap: var(--spacing-xs); + padding: var(--spacing-sm); + background-color: var(--color-green-darker); + border: var(--border-thickness) solid var(--color-border-dim); + border-radius: 0; +} + +.upload-item-header { + display: flex; + align-items: center; + justify-content: space-between; + gap: var(--spacing-xs); +} + +.upload-item-info { + display: flex; + align-items: center; + gap: var(--spacing-xs); + flex: 1; + min-width: 0; +} + +.upload-item-icon { + flex-shrink: 0; + font-size: var(--font-size-sm); + color: var(--color-text-secondary); +} + +.upload-item-name { + flex: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-family: var(--font-family-mono); + font-size: var(--font-size-sm); + color: var(--color-text-primary); +} + +.upload-item-actions { + display: flex; + gap: var(--spacing-xs); +} + +.upload-item-cancel, +.upload-item-retry { + padding: var(--spacing-xs); + font-family: var(--font-family-mono); + font-size: var(--font-size-xs); + cursor: pointer; + border: none; + border-radius: 0; + transition: background-color 0.15s ease; +} + +.upload-item-cancel { + color: var(--color-text-primary); + background-color: transparent; + border: var(--border-thickness) solid var(--color-border); +} + +.upload-item-cancel:hover { + background-color: var(--color-green-darker); +} + +.upload-item-retry { + color: var(--color-black); + background-color: var(--color-green-primary); +} + +.upload-item-retry:hover { + box-shadow: var(--glow-green); +} + +/* Progress bar */ +.upload-item-progress-bar { + height: 4px; + background-color: var(--color-border-dim); + border-radius: 0; + overflow: hidden; +} + +.upload-item-progress-fill { + height: 100%; + background-color: var(--color-green-primary); + transition: width 0.2s ease; +} + +.upload-item-progress-fill[data-status='complete'] { + background-color: var(--color-green-primary); +} + +.upload-item-progress-fill[data-status='error'] { + background-color: var(--color-error); +} + +/* Status text */ +.upload-item-status { + font-family: var(--font-family-mono); + font-size: var(--font-size-xs); + color: var(--color-text-secondary); +} + +.upload-item-status[data-status='complete'] { + color: var(--color-green-primary); +} + +.upload-item-status[data-status='error'] { + color: var(--color-error); +} + +/* Modal actions */ +.upload-modal-actions { + display: flex; + justify-content: flex-end; + gap: var(--spacing-xs); + margin-top: var(--spacing-md); + padding-top: var(--spacing-md); + border-top: var(--border-thickness) solid var(--color-border-dim); +} + +.upload-modal-btn { + padding: var(--spacing-xs) var(--spacing-md); + font-family: var(--font-family-mono); + font-size: var(--font-size-sm); + cursor: pointer; + border: none; + border-radius: 0; + transition: background-color 0.15s ease, box-shadow 0.15s ease; +} + +.upload-modal-btn-cancel { + color: var(--color-text-primary); + background-color: transparent; + border: var(--border-thickness) solid var(--color-border); +} + +.upload-modal-btn-cancel:hover { + background-color: var(--color-green-darker); +} + +.upload-modal-btn-close { + color: var(--color-black); + background-color: var(--color-green-primary); + font-weight: var(--font-weight-semibold); +} + +.upload-modal-btn-close:hover { + box-shadow: var(--glow-green); +} +``` + +Key changes for both files: +- Remove ALL light mode CSS and @media prefers-color-scheme queries +- Use design token variables throughout +- Remove all border-radius values +- Add green glow effects + </action> + <verify>Check neither file contains `@media (prefers-color-scheme` and both contain `var(--color-green-primary)`</verify> + <done>Modal and upload styles use terminal aesthetic with green accents, no light mode</done> +</task> + +</tasks> + +<verification> +1. Right-click a file to open context menu - should have green border, black background +2. Click rename on a file - dialog should have terminal styling +3. Upload a file - upload zone should have green dashed border +4. Upload modal should show green progress bar +5. Delete confirmation should have proper button styling (red for delete) +6. No light mode colors visible anywhere +</verification> + +<success_criteria> +- All overlay components use design tokens +- Context menus have green border on black background +- Dialogs use monospace font throughout +- Upload UI shows green progress indicators +- No light mode CSS remains (no prefers-color-scheme queries) +- All border-radius values are 0 (sharp corners) +</success_criteria> + +<output> +After completion, create `.planning/phases/06.2-restyle-app-with-pencil-design/06.2-03-SUMMARY.md` +</output> diff --git a/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-04-PLAN.md b/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-04-PLAN.md new file mode 100644 index 0000000000..b4a21e5693 --- /dev/null +++ b/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-04-PLAN.md @@ -0,0 +1,543 @@ +--- +phase: 06.2-restyle-app-pencil-design +plan: 04 +type: execute +wave: 2 +depends_on: ["06.2-01"] +files_modified: + - apps/web/src/styles/responsive.css + - apps/web/src/components/MatrixBackground.tsx + - apps/web/src/routes/Login.tsx +autonomous: true + +must_haves: + truths: + - "Mobile layout uses green color scheme" + - "Sidebar overlay has terminal styling on mobile" + - "Login page shows subtle matrix animation in background" + - "Matrix effect is performant (30fps, low opacity)" + artifacts: + - path: "apps/web/src/styles/responsive.css" + provides: "Mobile responsive styles with terminal aesthetic" + contains: "var(--color-green-primary)" + - path: "apps/web/src/components/MatrixBackground.tsx" + provides: "Canvas-based matrix rain animation" + min_lines: 50 + contains: "canvas" + key_links: + - from: "apps/web/src/routes/Login.tsx" + to: "apps/web/src/components/MatrixBackground.tsx" + via: "component import and render" + pattern: "import.*MatrixBackground" +--- + +<objective> +Update responsive styles for mobile and add matrix background animation to login page. + +Purpose: Mobile users need the same terminal aesthetic, and the login page needs the signature matrix rain effect for visual appeal. The animation should be subtle and performant. + +Output: Terminal-styled responsive layout and animated matrix background on login. +</objective> + +<execution_context> +@./.claude/get-shit-done/workflows/execute-plan.md +@./.claude/get-shit-done/templates/summary.md +</execution_context> + +<context> +@.planning/PROJECT.md +@.planning/ROADMAP.md +@.planning/phases/06.2-restyle-app-with-pencil-design/06.2-CONTEXT.md +@.planning/phases/06.2-restyle-app-with-pencil-design/06.2-RESEARCH.md +@.planning/phases/06.2-restyle-app-with-pencil-design/06.2-01-SUMMARY.md +</context> + +<tasks> + +<task type="auto"> + <name>Task 1: Update responsive.css with terminal aesthetic</name> + <files>apps/web/src/styles/responsive.css</files> + <action> +Replace the entire responsive.css with terminal-styled version using design tokens. + +```css +/** + * Responsive Styles - Terminal Aesthetic + * + * Mobile-first responsive design for the file browser. + * Breakpoint: 768px (tablet/desktop boundary) + * + * Mobile features: + * - Sidebar slides in as overlay + * - Hamburger toggle in toolbar + * - Backdrop behind sidebar + * - Touch-friendly sizing + */ + +/* ========================================================================== + Mobile Hamburger Toggle + ========================================================================== */ + +.file-browser-toggle { + display: flex; + align-items: center; + justify-content: center; + width: 2.5rem; + height: 2.5rem; + padding: 0; + background: transparent; + border: var(--border-thickness) solid var(--color-border); + border-radius: 0; + color: var(--color-text-primary); + font-size: 1.25rem; + cursor: pointer; + transition: background-color 0.15s ease, box-shadow 0.15s ease; + flex-shrink: 0; +} + +.file-browser-toggle:hover { + background-color: var(--color-green-darker); + box-shadow: var(--glow-green); +} + +.file-browser-toggle:focus { + outline: 2px solid var(--color-green-primary); + outline-offset: 2px; +} + +/* ========================================================================== + Mobile Sidebar Overlay + ========================================================================== */ + +/* Backdrop when sidebar is open */ +.file-browser-backdrop { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.8); + z-index: 99; + animation: fadeIn 0.2s ease; +} + +@keyframes fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +/* Sidebar close button (mobile) */ +.file-browser-sidebar-close { + position: absolute; + top: var(--spacing-sm); + right: var(--spacing-sm); + display: flex; + align-items: center; + justify-content: center; + width: 2rem; + height: 2rem; + padding: 0; + background: transparent; + border: var(--border-thickness) solid var(--color-border); + border-radius: 0; + color: var(--color-text-secondary); + font-size: 1.25rem; + cursor: pointer; + transition: color 0.15s ease, background-color 0.15s ease; + z-index: 1; +} + +.file-browser-sidebar-close:hover { + color: var(--color-text-primary); + background-color: var(--color-green-darker); +} + +/* ========================================================================== + Mobile Layout Overrides + ========================================================================== */ + +@media (max-width: 768px) { + /* Sidebar: fixed position overlay */ + .file-browser-sidebar { + position: fixed; + top: 0; + left: 0; + bottom: 0; + width: 280px; + max-width: 85vw; + transform: translateX(-100%); + transition: transform 0.3s ease; + z-index: 100; + background-color: var(--color-background); + border-right: var(--border-thickness) solid var(--color-border); + box-shadow: 4px 0 20px rgba(0, 0, 0, 0.5); + } + + .file-browser-sidebar--open { + transform: translateX(0); + } + + .file-browser-sidebar--closed { + transform: translateX(-100%); + } + + /* Adjust folder tree header for close button */ + .folder-tree-header { + padding-right: 3rem; + } + + /* Main content: full width */ + .file-browser-main { + padding: var(--spacing-sm); + } + + /* Toolbar: add gap for hamburger */ + .file-browser-toolbar { + gap: var(--spacing-xs); + flex-wrap: wrap; + } + + /* File list: 2 columns on mobile (NAME, SIZE) */ + .file-list-header, + .file-list-item { + grid-template-columns: 1fr 80px; + gap: var(--spacing-xs); + } + + /* Hide TYPE and DATE columns on mobile */ + .file-list-header-type, + .file-list-header-date, + .file-list-item-type, + .file-list-item-date { + display: none; + } + + /* File list items: touch-friendly sizing */ + .file-list-item { + padding: var(--spacing-sm) var(--spacing-md); + min-height: 3rem; + } + + /* Empty state: smaller margins */ + .empty-state { + margin: var(--spacing-md); + min-height: 200px; + } + + /* Context menu: touch-friendly */ + .context-menu { + min-width: 200px; + } + + .context-menu-item { + padding: var(--spacing-sm) var(--spacing-md); + font-size: var(--font-size-sm); + } + + /* Dialogs: full width on small screens */ + .modal-container { + max-width: calc(100vw - 2rem); + margin: var(--spacing-md); + } + + /* Login: adjust spacing */ + .login-container { + padding: var(--spacing-md); + } + + .login-container h1 { + font-size: 1.5rem; + } +} + +/* ========================================================================== + Desktop Layout (default) + ========================================================================== */ + +@media (min-width: 769px) { + /* Sidebar always visible on desktop */ + .file-browser-sidebar { + position: relative; + transform: none; + } + + .file-browser-sidebar--open, + .file-browser-sidebar--closed { + transform: none; + } + + /* Hide mobile-only elements */ + .file-browser-toggle, + .file-browser-backdrop, + .file-browser-sidebar-close { + display: none; + } +} + +/* ========================================================================== + Touch Interactions + ========================================================================== */ + +/* Prevent text selection during long-press */ +.file-list-item { + -webkit-touch-callout: none; + -webkit-user-select: none; + user-select: none; +} + +/* Visual feedback for touch */ +@media (pointer: coarse) { + .file-list-item:active { + background-color: var(--color-green-darker); + } + + .folder-tree-item:active { + background-color: var(--color-green-darker); + } +} +``` + +Key changes: +- Replace all rgba colors with design token variables +- Remove border-radius values +- Use green color scheme for all hover/active states +- Update file list to hide TYPE column on mobile (2 columns: NAME, SIZE) + </action> + <verify>Check file contains `var(--color-green-primary)` and `var(--color-green-darker)`</verify> + <done>Responsive styles use terminal aesthetic with green color scheme on mobile</done> +</task> + +<task type="auto"> + <name>Task 2: Create MatrixBackground component</name> + <files>apps/web/src/components/MatrixBackground.tsx</files> + <action> +Create a new file `apps/web/src/components/MatrixBackground.tsx` with the matrix rain animation. + +```tsx +import { useEffect, useRef } from 'react'; + +/** + * Matrix rain background effect for login page. + * Canvas-based animation with falling binary/hex characters. + * Performance-optimized: 30fps, low opacity, resize handling. + */ +export function MatrixBackground() { + const canvasRef = useRef<HTMLCanvasElement>(null); + const animationRef = useRef<number>(0); + + useEffect(() => { + const canvas = canvasRef.current; + if (!canvas) return; + + const ctx = canvas.getContext('2d'); + if (!ctx) return; + + // Configuration + const FONT_SIZE = 14; + const COLUMN_WIDTH = 20; + const FRAME_INTERVAL = 33; // ~30fps + const CHARACTERS = '01'; + const PRIMARY_COLOR = '#00D084'; + const DIM_COLOR = '#006644'; + + // State + let columns: number[] = []; + let lastFrameTime = 0; + + // Resize handler + function resize() { + canvas.width = window.innerWidth; + canvas.height = window.innerHeight; + + // Initialize/reset columns + const columnCount = Math.floor(canvas.width / COLUMN_WIDTH); + columns = Array(columnCount).fill(0).map(() => + Math.random() * -100 // Start at random positions above viewport + ); + } + + // Draw frame + function draw(timestamp: number) { + // Throttle to ~30fps + if (timestamp - lastFrameTime < FRAME_INTERVAL) { + animationRef.current = requestAnimationFrame(draw); + return; + } + lastFrameTime = timestamp; + + // Fade previous frame (creates trail effect) + ctx.fillStyle = 'rgba(0, 0, 0, 0.05)'; + ctx.fillRect(0, 0, canvas.width, canvas.height); + + // Draw characters + ctx.font = `${FONT_SIZE}px "JetBrains Mono", monospace`; + + for (let i = 0; i < columns.length; i++) { + const y = columns[i] * FONT_SIZE; + + // Random character + const char = CHARACTERS[Math.floor(Math.random() * CHARACTERS.length)]; + + // Leading character is brighter + ctx.fillStyle = PRIMARY_COLOR; + ctx.fillText(char, i * COLUMN_WIDTH, y); + + // Trail characters are dimmer + if (Math.random() > 0.98) { + ctx.fillStyle = DIM_COLOR; + ctx.fillText(char, i * COLUMN_WIDTH, y - FONT_SIZE); + } + + // Move column down + columns[i]++; + + // Reset when reaching bottom (with random chance for variation) + if (y > canvas.height && Math.random() > 0.975) { + columns[i] = 0; + } + } + + animationRef.current = requestAnimationFrame(draw); + } + + // Initialize + resize(); + window.addEventListener('resize', resize); + animationRef.current = requestAnimationFrame(draw); + + // Cleanup + return () => { + window.removeEventListener('resize', resize); + cancelAnimationFrame(animationRef.current); + }; + }, []); + + return ( + <canvas + ref={canvasRef} + className="matrix-background" + aria-hidden="true" + style={{ + position: 'fixed', + top: 0, + left: 0, + width: '100%', + height: '100%', + zIndex: -1, + opacity: 0.25, // Subtle, not overwhelming + pointerEvents: 'none', + }} + /> + ); +} +``` + +Key implementation details: +- Uses requestAnimationFrame for smooth animation +- Throttled to ~30fps to reduce CPU usage +- Low opacity (0.25) for subtle effect +- Handles window resize +- Cleanup on unmount +- Uses JetBrains Mono font for consistency +- aria-hidden for accessibility + </action> + <verify>Check file exists and contains `requestAnimationFrame` and `JetBrains Mono`</verify> + <done>MatrixBackground component created with performant canvas animation</done> +</task> + +<task type="auto"> + <name>Task 3: Add MatrixBackground to Login page</name> + <files>apps/web/src/routes/Login.tsx</files> + <action> +Update Login.tsx to import and render the MatrixBackground component. + +```tsx +import { useEffect } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { ApiStatusIndicator } from '../components/ApiStatusIndicator'; +import { AuthButton } from '../components/auth/AuthButton'; +import { MatrixBackground } from '../components/MatrixBackground'; +import { useAuth } from '../hooks/useAuth'; + +/** + * Login page with terminal aesthetic and matrix background. + * Per design: > CIPHERBOX branding, [CONNECT] button, green-on-black theme. + */ +export function Login() { + const { isAuthenticated, isLoading } = useAuth(); + const navigate = useNavigate(); + + // Redirect if already authenticated + useEffect(() => { + if (isAuthenticated) { + navigate('/dashboard'); + } + }, [isAuthenticated, navigate]); + + // Show loading state while checking authentication + if (isLoading) { + return ( + <div className="login-container"> + <MatrixBackground /> + <div className="loading">initializing...</div> + </div> + ); + } + + return ( + <div className="login-container"> + <MatrixBackground /> + <h1>CIPHERBOX</h1> + <p className="tagline">zero-knowledge encrypted storage</p> + <p className="login-description"> + your files, encrypted on your device. we never see your data. + </p> + <AuthButton /> + <ApiStatusIndicator /> + </div> + ); +} +``` + +Key changes: +- Import MatrixBackground component +- Render MatrixBackground as first child in login-container +- Update text to lowercase for terminal aesthetic +- Update tagline text to match design +- Loading state shows "initializing..." instead of "Loading..." + </action> + <verify>Run `pnpm --filter web dev` and verify login page shows matrix animation in background</verify> + <done>Login page displays matrix rain animation behind content</done> +</task> + +</tasks> + +<verification> +1. Open app on mobile viewport (390px width) + - Sidebar should slide in from left with green border + - File list should show 2 columns (NAME, SIZE) + - Touch interactions should show green highlights +2. Open login page + - Matrix animation visible in background (subtle, not distracting) + - Animation runs smoothly (~30fps) + - Text content readable over animation +3. Resize window - animation should resize properly +4. Navigate away from login - animation should stop (no memory leak) +</verification> + +<success_criteria> +- Mobile layout uses design tokens throughout +- Sidebar overlay has terminal styling (green border, black bg) +- Matrix background animation renders on login page +- Animation is performant (no visible lag or jank) +- Animation is subtle (low opacity, doesn't distract) +- Existing E2E tests still pass +</success_criteria> + +<output> +After completion, create `.planning/phases/06.2-restyle-app-with-pencil-design/06.2-04-SUMMARY.md` +</output> diff --git a/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-05-PLAN.md b/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-05-PLAN.md new file mode 100644 index 0000000000..373f8bd9d1 --- /dev/null +++ b/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-05-PLAN.md @@ -0,0 +1,233 @@ +--- +phase: 06.2-restyle-app-pencil-design +plan: 05 +type: execute +wave: 3 +depends_on: ["06.2-02", "06.2-03", "06.2-04"] +files_modified: + - apps/web/src/components/file-browser/FileListItem.tsx + - apps/web/src/components/file-browser/FolderTreeNode.tsx + - apps/web/src/components/file-browser/FileList.tsx + - apps/web/src/components/file-browser/FileBrowser.tsx + - apps/web/src/components/auth/AuthButton.tsx + - apps/web/src/routes/Dashboard.tsx +autonomous: true + +must_haves: + truths: + - "Files show [FILE] prefix instead of emoji icon" + - "Folders show [DIR] prefix instead of emoji icon" + - "File list header shows NAME, SIZE, TYPE, MODIFIED columns" + - "Toolbar buttons show --upload, --new-dir, --refresh text" + - "Login button shows [CONNECT] text" + - "Dashboard header shows > CIPHERBOX branding" + artifacts: + - path: "apps/web/src/components/file-browser/FileListItem.tsx" + provides: "File/folder items with text prefixes" + contains: "[DIR]" + - path: "apps/web/src/components/auth/AuthButton.tsx" + provides: "Terminal-styled connect button" + contains: "[CONNECT]" + key_links: + - from: "apps/web/src/components/file-browser/FileListItem.tsx" + to: "apps/web/src/styles/file-browser.css" + via: "CSS class names" + pattern: "file-list-item" +--- + +<objective> +Update React components to match terminal aesthetic - text prefixes, button labels, and header branding. + +Purpose: The CSS changes in previous plans styled the elements, but the actual content (icons, button text, headers) needs to match the Pencil design. This plan updates TSX files to use [DIR]/[FILE] prefixes and terminal-style button text. + +Output: Complete terminal aesthetic with correct text content throughout the UI. +</objective> + +<execution_context> +@./.claude/get-shit-done/workflows/execute-plan.md +@./.claude/get-shit-done/templates/summary.md +</execution_context> + +<context> +@.planning/PROJECT.md +@.planning/ROADMAP.md +@.planning/phases/06.2-restyle-app-with-pencil-design/06.2-CONTEXT.md +@.planning/phases/06.2-restyle-app-with-pencil-design/06.2-RESEARCH.md +@.planning/phases/06.2-restyle-app-with-pencil-design/06.2-02-SUMMARY.md +@.planning/phases/06.2-restyle-app-with-pencil-design/06.2-03-SUMMARY.md +@.planning/phases/06.2-restyle-app-with-pencil-design/06.2-04-SUMMARY.md +</context> + +<tasks> + +<task type="auto"> + <name>Task 1: Update FileListItem and FolderTreeNode with text prefixes</name> + <files>apps/web/src/components/file-browser/FileListItem.tsx, apps/web/src/components/file-browser/FolderTreeNode.tsx</files> + <action> +First, read the current FileListItem.tsx to understand its structure, then update the icon to use text prefix. + +In FileListItem.tsx, find the icon element (likely showing emoji like folder or file icon) and replace it with text prefix: + +Replace emoji icons with text: +- Folders: `[DIR]` instead of folder emoji +- Files: `[FILE]` instead of file emoji + +The icon span should become: +```tsx +<span className="file-list-item-icon"> + {entry.type === 'folder' ? '[DIR]' : '[FILE]'} +</span> +``` + +Also add TYPE column to display the file extension: +```tsx +<span className="file-list-item-type"> + {entry.type === 'folder' ? 'dir' : getFileExtension(entry.name)} +</span> +``` + +Add helper function at top of file (outside component): +```tsx +function getFileExtension(filename: string): string { + const ext = filename.split('.').pop(); + return ext && ext !== filename ? ext.toLowerCase() : '-'; +} +``` + +Similarly, in FolderTreeNode.tsx, update the folder icon: +```tsx +<span className="folder-tree-icon">[DIR]</span> +``` + +Remove any emoji icons and replace with text prefixes. + </action> + <verify>Check FileListItem.tsx contains `[DIR]` and `[FILE]` strings, check FolderTreeNode.tsx contains `[DIR]`</verify> + <done>File and folder items display text prefixes instead of emoji icons</done> +</task> + +<task type="auto"> + <name>Task 2: Update FileList header and FileBrowser toolbar</name> + <files>apps/web/src/components/file-browser/FileList.tsx, apps/web/src/components/file-browser/FileBrowser.tsx</files> + <action> +In FileList.tsx, update the header to show 4 columns with proper labels: + +Find the file list header and ensure it has these columns: +```tsx +<div className="file-list-header"> + <span className="file-list-header-name">NAME</span> + <span className="file-list-header-size">SIZE</span> + <span className="file-list-header-type">TYPE</span> + <span className="file-list-header-date">MODIFIED</span> +</div> +``` + +In FileBrowser.tsx, update the toolbar buttons to use terminal-style labels: + +Find the toolbar buttons and update their text: +- Upload button: `--upload` (primary style) +- New folder button: `--new-dir` (secondary style) +- Refresh button: `--refresh` (secondary style) + +Example structure: +```tsx +<div className="file-browser-toolbar"> + <button className="toolbar-button--primary" onClick={handleUpload}> + --upload + </button> + <button className="toolbar-button--secondary" onClick={handleNewFolder}> + --new-dir + </button> + <button className="toolbar-button--secondary" onClick={handleRefresh}> + --refresh + </button> + {/* breadcrumbs */} +</div> +``` + +Make sure to apply the correct CSS classes: +- `toolbar-button--primary` for upload (green filled) +- `toolbar-button--secondary` for new-dir and refresh (green outlined) + </action> + <verify>Check FileList.tsx contains header columns NAME, SIZE, TYPE, MODIFIED. Check FileBrowser.tsx contains button text `--upload`, `--new-dir`, `--refresh`</verify> + <done>File list header shows 4 columns, toolbar buttons have terminal-style labels</done> +</task> + +<task type="auto"> + <name>Task 3: Update AuthButton and Dashboard header</name> + <files>apps/web/src/components/auth/AuthButton.tsx, apps/web/src/routes/Dashboard.tsx</files> + <action> +In AuthButton.tsx, update the button text to terminal style: + +Find the button element and update its text to `[CONNECT]`: +```tsx +<button className="login-button" onClick={handleLogin} disabled={isLoading}> + {isLoading ? 'connecting...' : '[CONNECT]'} +</button> +``` + +Use lowercase text for loading state to match terminal aesthetic. + +In Dashboard.tsx, update the header to show terminal branding: + +Find the dashboard header and update it to show `> CIPHERBOX`: +```tsx +<header className="dashboard-header"> + <h1 className="app-title">> CIPHERBOX</h1> + {/* ... user info, logout link */} +</header> +``` + +Or if using a span/div: +```tsx +<span className="app-title">> CIPHERBOX</span> +``` + +Note: Use `>` for the `>` character in JSX, or wrap in curly braces: `{'> CIPHERBOX'}` + +Also ensure the logout link uses lowercase: +```tsx +<a href="#" className="logout-link" onClick={handleLogout}> + logout +</a> +``` + +If there's user info displayed, use lowercase format: +```tsx +<span className="user-email">{user?.email?.toLowerCase()}</span> +``` + </action> + <verify>Check AuthButton.tsx contains `[CONNECT]`, check Dashboard.tsx contains `> CIPHERBOX` or `> CIPHERBOX`</verify> + <done>Login button shows [CONNECT], dashboard header shows > CIPHERBOX branding</done> +</task> + +</tasks> + +<verification> +1. Login page: + - Button shows `[CONNECT]` text + - Loading state shows `connecting...` +2. Dashboard header: + - Shows `> CIPHERBOX` branding + - Logout link is lowercase +3. File browser: + - Toolbar has `--upload`, `--new-dir`, `--refresh` buttons + - File list header shows NAME, SIZE, TYPE, MODIFIED + - Files show `[FILE]` prefix + - Folders show `[DIR]` prefix +4. Folder tree: + - Folders show `[DIR]` prefix +5. Run E2E tests: `pnpm --filter e2e test` - all should pass +</verification> + +<success_criteria> +- All emoji icons replaced with text prefixes ([DIR], [FILE]) +- Toolbar buttons use terminal-style text (--upload, --new-dir, --refresh) +- Login button shows [CONNECT] +- Dashboard header shows > CIPHERBOX +- Text content is lowercase where appropriate +- Existing E2E tests pass (may need selector updates if tests use emoji) +</success_criteria> + +<output> +After completion, create `.planning/phases/06.2-restyle-app-with-pencil-design/06.2-05-SUMMARY.md` +</output> diff --git a/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-06-PLAN.md b/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-06-PLAN.md new file mode 100644 index 0000000000..58cc073341 --- /dev/null +++ b/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-06-PLAN.md @@ -0,0 +1,191 @@ +--- +phase: 06.2-restyle-app-pencil-design +plan: 06 +type: execute +wave: 4 +depends_on: ["06.2-05"] +files_modified: + - e2e/tests/file-browser.spec.ts + - e2e/tests/folder-operations.spec.ts + - e2e/page-objects/FileBrowserPage.ts +autonomous: false + +must_haves: + truths: + - "All E2E tests pass with new terminal styling" + - "Test selectors updated to match new text content" + - "Visual appearance matches Pencil design specification" + - "Responsive design works on mobile viewport" + artifacts: + - path: "e2e/tests/file-browser.spec.ts" + provides: "Updated E2E tests for restyled UI" + - path: "e2e/page-objects/FileBrowserPage.ts" + provides: "Updated page object selectors" + key_links: + - from: "e2e/page-objects/FileBrowserPage.ts" + to: "apps/web/src/components/file-browser/*.tsx" + via: "CSS selectors and text content" + pattern: "getByRole|getByText|locator" +--- + +<objective> +Update E2E tests for new styling and verify the complete restyle works correctly. + +Purpose: The UI changes may have affected selectors used in E2E tests. This plan ensures tests are updated to work with the new terminal styling, then verifies the complete restyle through automated and manual testing. + +Output: All E2E tests passing, visual verification complete. +</objective> + +<execution_context> +@./.claude/get-shit-done/workflows/execute-plan.md +@./.claude/get-shit-done/templates/summary.md +</execution_context> + +<context> +@.planning/PROJECT.md +@.planning/ROADMAP.md +@.planning/phases/06.2-restyle-app-with-pencil-design/06.2-CONTEXT.md +@.planning/phases/06.2-restyle-app-with-pencil-design/06.2-05-SUMMARY.md +@e2e/page-objects/FileBrowserPage.ts +@e2e/tests/file-browser.spec.ts +</context> + +<tasks> + +<task type="auto"> + <name>Task 1: Update E2E page objects and test selectors</name> + <files>e2e/page-objects/FileBrowserPage.ts, e2e/tests/file-browser.spec.ts, e2e/tests/folder-operations.spec.ts</files> + <action> +Read the existing page objects and test files to identify selectors that may need updating based on the UI changes: + +1. Button text changes: + - Upload button: now shows `--upload` instead of previous text + - New folder button: now shows `--new-dir` instead of previous text + - Refresh button: now shows `--refresh` instead of previous text + - Login button: now shows `[CONNECT]` instead of previous text + +2. Icon changes: + - Files now show `[FILE]` text instead of emoji + - Folders now show `[DIR]` text instead of emoji + +3. Header changes: + - Dashboard title now shows `> CIPHERBOX` + +Update any selectors in page objects that use: +- `getByRole('button', { name: '...' })` - update button names +- `getByText('...')` - update text content +- Emoji characters in selectors - replace with new text + +Common patterns to update: + +```typescript +// Before (if using button text) +this.uploadButton = page.getByRole('button', { name: /upload/i }); + +// After +this.uploadButton = page.getByRole('button', { name: '--upload' }); + +// Or use class selector (more stable) +this.uploadButton = page.locator('.toolbar-button--primary'); +``` + +For file/folder detection: +```typescript +// Before (if checking for emoji) +const isFolder = await item.locator('text=folder-emoji').isVisible(); + +// After +const isFolder = await item.locator('text=[DIR]').isVisible(); +``` + +Prefer CSS class selectors over text content where possible for stability: +- `.toolbar-button--primary` for upload +- `.toolbar-button--secondary` for new-dir and refresh +- `.file-list-item` for file items +- `.folder-tree-item` for folder tree items + </action> + <verify>Run `pnpm --filter e2e test` and check all tests pass</verify> + <done>E2E test selectors updated to match new terminal styling</done> +</task> + +<task type="checkpoint:human-verify" gate="blocking"> + <what-built>Complete terminal/hacker aesthetic restyle of CipherBox web app including: +- JetBrains Mono font throughout +- Green-on-black color scheme +- [DIR]/[FILE] text prefixes +- --upload, --new-dir, --refresh button labels +- Matrix background animation on login +- Terminal-styled modals, dialogs, and context menus +- Responsive mobile design with terminal aesthetic</what-built> + <how-to-verify> +1. Start the app: `pnpm dev` + +2. **Login Page** (http://localhost:5173): + - [ ] Black background with subtle matrix animation + - [ ] `> CIPHERBOX` title with monospace font + - [ ] `[CONNECT]` button (green, sharp corners) + - [ ] API status indicator in bottom-right + +3. **File Browser** (after login): + - [ ] Header shows `> CIPHERBOX` branding + - [ ] Sidebar has green right border + - [ ] Folder tree shows `[DIR]` prefixes + - [ ] Toolbar buttons: `--upload`, `--new-dir`, `--refresh` + - [ ] File list has green border + - [ ] Column headers: NAME, SIZE, TYPE, MODIFIED + - [ ] Files show `[FILE]` prefix, folders show `[DIR]` + - [ ] Hover states show green highlight + +4. **Context Menu** (right-click a file): + - [ ] Green border, black background + - [ ] Monospace font + - [ ] Delete option in red + +5. **Upload Dialog** (click --upload): + - [ ] Terminal-styled modal + - [ ] Green progress bar + - [ ] Sharp corners throughout + +6. **Rename Dialog** (right-click > Rename): + - [ ] Terminal-styled input field + - [ ] Green focus glow on input + - [ ] Proper button styling + +7. **Mobile** (resize to 390px width or use DevTools): + - [ ] Hamburger menu appears + - [ ] Sidebar slides in with green border + - [ ] File list shows 2 columns (NAME, SIZE) + - [ ] Touch interactions work + +8. **Run E2E Tests**: + ```bash + pnpm --filter e2e test + ``` + - [ ] All tests pass + </how-to-verify> + <resume-signal>Type "approved" if all checks pass, or describe any issues that need fixing</resume-signal> +</task> + +</tasks> + +<verification> +1. E2E test suite passes: `pnpm --filter e2e test` +2. Visual inspection matches Pencil design +3. No console errors in browser +4. Responsive design works at 390px and 1440px widths +5. Matrix animation is subtle and performant +6. All interactive elements work (upload, download, rename, delete, navigate) +</verification> + +<success_criteria> +- All E2E tests pass with updated selectors +- Visual appearance matches Pencil design specification +- Login shows matrix animation, [CONNECT] button, > CIPHERBOX branding +- File browser shows terminal aesthetic throughout +- Mobile responsive design maintains terminal theme +- No regressions in functionality +</success_criteria> + +<output> +After completion, create `.planning/phases/06.2-restyle-app-with-pencil-design/06.2-06-SUMMARY.md` +</output> From d69a933b7f8c6eabb6a4a8c40bb6eb61e5872dff Mon Sep 17 00:00:00 2001 From: Michael Yankelev <myankelev@gmail.com> Date: Fri, 23 Jan 2026 04:11:35 +0100 Subject: [PATCH 02/33] docs(6.2): create phase plans with user decisions Phase 6.2: Restyle App with Pencil Design - 6 plans in 4 waves User decisions captured: - Full matrix animation (not static fallback) - Mobile 2-row stacked layout per Pencil design (ZVAUX) - Row 1: [DIR]/[FILE] icon + filename - Row 2: Date (left) | Size (right) Plans: - 01: Design tokens and typography foundation - 02: File browser and breadcrumbs restyle - 03: Dialogs, menus, modals, upload restyle - 04: Responsive styles and matrix animation - 05: Component TSX updates (text prefixes, labels) - 06: E2E test updates and visual verification Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --- .../06.2-02-PLAN.md | 19 ++- .../06.2-04-PLAN.md | 69 ++++++--- .../06.2-05-PLAN.md | 61 ++++---- .../06.2-CONTEXT.md | 2 +- .../06.2-RESEARCH.md | 18 ++- designs/cipher-box-design.pen | 138 ++++++------------ 6 files changed, 156 insertions(+), 151 deletions(-) diff --git a/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-02-PLAN.md b/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-02-PLAN.md index 2d6d2e5e72..167e19f32e 100644 --- a/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-02-PLAN.md +++ b/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-02-PLAN.md @@ -297,10 +297,11 @@ Replace the entire file-browser.css with terminal-styled version using design to /* Container for file items */ } -/* File List Item */ +/* File List Item - Desktop uses grid, Mobile uses 2-row stacked layout */ .file-list-item { display: grid; grid-template-columns: 1fr 120px 120px 180px; + grid-template-areas: "name size type date"; gap: var(--spacing-md); padding: var(--spacing-sm) var(--spacing-md); cursor: pointer; @@ -326,21 +327,28 @@ Replace the entire file-browser.css with terminal-styled version using design to background-color: var(--color-green-darker); } -.file-list-item-name { +/* Row wrappers - on desktop, these act as containers within grid */ +.file-list-item-row-top { + grid-area: name; display: flex; align-items: center; - gap: var(--spacing-xs); + gap: 6px; min-width: 0; } +.file-list-item-row-bottom { + display: contents; /* Children participate directly in parent grid on desktop */ +} + .file-list-item-icon { font-family: var(--font-family-mono); font-size: var(--font-size-sm); + font-weight: var(--font-weight-semibold); flex-shrink: 0; color: var(--color-text-primary); } -.file-list-item-text { +.file-list-item-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; @@ -349,6 +357,7 @@ Replace the entire file-browser.css with terminal-styled version using design to } .file-list-item-size { + grid-area: size; display: flex; align-items: center; color: var(--color-text-secondary); @@ -356,6 +365,7 @@ Replace the entire file-browser.css with terminal-styled version using design to } .file-list-item-type { + grid-area: type; display: flex; align-items: center; color: var(--color-text-secondary); @@ -364,6 +374,7 @@ Replace the entire file-browser.css with terminal-styled version using design to } .file-list-item-date { + grid-area: date; display: flex; align-items: center; color: var(--color-text-secondary); diff --git a/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-04-PLAN.md b/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-04-PLAN.md index b4a21e5693..909855b527 100644 --- a/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-04-PLAN.md +++ b/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-04-PLAN.md @@ -13,8 +13,9 @@ autonomous: true must_haves: truths: - "Mobile layout uses green color scheme" + - "Mobile file list uses 2-row stacked layout (icon+name / date+size)" - "Sidebar overlay has terminal styling on mobile" - - "Login page shows subtle matrix animation in background" + - "Login page shows FULL matrix animation in background" - "Matrix effect is performant (30fps, low opacity)" artifacts: - path: "apps/web/src/styles/responsive.css" @@ -32,9 +33,9 @@ must_haves: --- <objective> -Update responsive styles for mobile and add matrix background animation to login page. +Update responsive styles for mobile and add FULL matrix background animation to login page. -Purpose: Mobile users need the same terminal aesthetic, and the login page needs the signature matrix rain effect for visual appeal. The animation should be subtle and performant. +Purpose: Mobile users need the same terminal aesthetic, and the login page needs the signature matrix rain effect for visual appeal. Per user decision: implement the full animated matrix rain effect (not static fallback). The animation should be subtle and performant. Output: Terminal-styled responsive layout and animated matrix background on login. </objective> @@ -201,25 +202,59 @@ Replace the entire responsive.css with terminal-styled version using design toke flex-wrap: wrap; } - /* File list: 2 columns on mobile (NAME, SIZE) */ - .file-list-header, + /* File list: hide header on mobile (2-row item layout) */ + .file-list-header { + display: none; + } + + /* File list items: 2-row stacked layout per Pencil design */ .file-list-item { - grid-template-columns: 1fr 80px; - gap: var(--spacing-xs); + display: flex; + flex-direction: column; + gap: 4px; + padding: 10px 12px; + min-height: auto; } - /* Hide TYPE and DATE columns on mobile */ - .file-list-header-type, - .file-list-header-date, - .file-list-item-type, - .file-list-item-date { - display: none; + /* Row 1: Icon + Name (left aligned) */ + .file-list-item-row-top { + display: flex; + align-items: center; + gap: 6px; + width: 100%; } - /* File list items: touch-friendly sizing */ - .file-list-item { - padding: var(--spacing-sm) var(--spacing-md); - min-height: 3rem; + .file-list-item-icon { + font-size: 10px; + font-weight: 600; + } + + .file-list-item-name { + font-size: 11px; + flex: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + /* Row 2: Modified (left) | Size (right) - space-between */ + .file-list-item-row-bottom { + display: flex; + justify-content: space-between; + align-items: center; + gap: 12px; + width: 100%; + } + + .file-list-item-date, + .file-list-item-size { + font-size: 9px; + color: var(--color-text-secondary); + } + + /* Hide TYPE column on mobile (shown in row layout via icon) */ + .file-list-item-type { + display: none; } /* Empty state: smaller margins */ diff --git a/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-05-PLAN.md b/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-05-PLAN.md index 373f8bd9d1..dd3753ac1d 100644 --- a/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-05-PLAN.md +++ b/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-05-PLAN.md @@ -17,14 +17,16 @@ must_haves: truths: - "Files show [FILE] prefix instead of emoji icon" - "Folders show [DIR] prefix instead of emoji icon" + - "File list items have row-top (icon+name) and row-bottom (date+size) structure" + - "Mobile layout shows 2-row stacked items per Pencil design" - "File list header shows NAME, SIZE, TYPE, MODIFIED columns" - "Toolbar buttons show --upload, --new-dir, --refresh text" - "Login button shows [CONNECT] text" - "Dashboard header shows > CIPHERBOX branding" artifacts: - path: "apps/web/src/components/file-browser/FileListItem.tsx" - provides: "File/folder items with text prefixes" - contains: "[DIR]" + provides: "File/folder items with text prefixes and 2-row mobile structure" + contains: "file-list-item-row-top" - path: "apps/web/src/components/auth/AuthButton.tsx" provides: "Terminal-styled connect button" contains: "[CONNECT]" @@ -61,39 +63,48 @@ Output: Complete terminal aesthetic with correct text content throughout the UI. <tasks> <task type="auto"> - <name>Task 1: Update FileListItem and FolderTreeNode with text prefixes</name> + <name>Task 1: Update FileListItem and FolderTreeNode with text prefixes and 2-row mobile layout</name> <files>apps/web/src/components/file-browser/FileListItem.tsx, apps/web/src/components/file-browser/FolderTreeNode.tsx</files> <action> -First, read the current FileListItem.tsx to understand its structure, then update the icon to use text prefix. +First, read the current FileListItem.tsx to understand its structure, then restructure for 2-row mobile layout. -In FileListItem.tsx, find the icon element (likely showing emoji like folder or file icon) and replace it with text prefix: +**IMPORTANT:** The mobile layout uses a 2-row stacked design per Pencil design (node ZVAUX): +- Row 1: [DIR]/[FILE] icon + filename +- Row 2: Modified date (left) | Size (right) -Replace emoji icons with text: -- Folders: `[DIR]` instead of folder emoji -- Files: `[FILE]` instead of file emoji +Restructure FileListItem.tsx with wrapper divs for mobile CSS targeting: -The icon span should become: -```tsx -<span className="file-list-item-icon"> - {entry.type === 'folder' ? '[DIR]' : '[FILE]'} -</span> -``` - -Also add TYPE column to display the file extension: -```tsx -<span className="file-list-item-type"> - {entry.type === 'folder' ? 'dir' : getFileExtension(entry.name)} -</span> -``` - -Add helper function at top of file (outside component): ```tsx function getFileExtension(filename: string): string { const ext = filename.split('.').pop(); return ext && ext !== filename ? ext.toLowerCase() : '-'; } + +// In the component render: +<div className="file-list-item" onClick={...} onContextMenu={...}> + {/* Row 1: Icon + Name (for mobile top row) */} + <div className="file-list-item-row-top"> + <span className="file-list-item-icon"> + {entry.type === 'folder' ? '[DIR]' : '[FILE]'} + </span> + <span className="file-list-item-name">{entry.name}</span> + </div> + + {/* Row 2: Date + Size (for mobile bottom row) */} + <div className="file-list-item-row-bottom"> + <span className="file-list-item-date">{formatDate(entry.modified)}</span> + <span className="file-list-item-size">{formatSize(entry.size)}</span> + </div> + + {/* TYPE column - hidden on mobile via CSS */} + <span className="file-list-item-type"> + {entry.type === 'folder' ? 'dir' : getFileExtension(entry.name)} + </span> +</div> ``` +On desktop, CSS grid will position these correctly. On mobile, the row wrappers enable the 2-row stacked layout. + Similarly, in FolderTreeNode.tsx, update the folder icon: ```tsx <span className="folder-tree-icon">[DIR]</span> @@ -101,8 +112,8 @@ Similarly, in FolderTreeNode.tsx, update the folder icon: Remove any emoji icons and replace with text prefixes. </action> - <verify>Check FileListItem.tsx contains `[DIR]` and `[FILE]` strings, check FolderTreeNode.tsx contains `[DIR]`</verify> - <done>File and folder items display text prefixes instead of emoji icons</done> + <verify>Check FileListItem.tsx contains `[DIR]`, `[FILE]`, `file-list-item-row-top`, and `file-list-item-row-bottom` classes</verify> + <done>File and folder items display text prefixes with 2-row mobile layout structure</done> </task> <task type="auto"> diff --git a/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-CONTEXT.md b/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-CONTEXT.md index 2ee22ef9e8..4633d757dc 100644 --- a/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-CONTEXT.md +++ b/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-CONTEXT.md @@ -25,7 +25,7 @@ Complete UI redesign of the CipherBox web app using the Pencil design file as th - **Primary color:** Black background (`#000000`) - **Accent color:** Green (`#00D084`) for borders, highlights, buttons, text - **Secondary colors:** Add red for errors, yellow for warnings (semantic colors alongside green) -- **Matrix background:** Subtle animation on login if implementation complexity is reasonable, otherwise static +- **Matrix background:** Full animated matrix rain effect (user confirmed — not static fallback) ### Component Scope - Restyle everything at once: login + file browser + modals together diff --git a/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-RESEARCH.md b/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-RESEARCH.md index bed8b36efd..d0a66532a7 100644 --- a/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-RESEARCH.md +++ b/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-RESEARCH.md @@ -529,15 +529,17 @@ Login Mobile (`3OkP2`, `77MPO`, `j6TYH`): Things that couldn't be fully resolved: -1. **Matrix animation implementation complexity** +1. **Matrix animation implementation complexity** — **RESOLVED: Use full animation** - What we know: Canvas-based approach is standard, ~100 lines recommended - - What's unclear: Whether user wants full animation or static decoration - - Recommendation: Start with static design, add animation as optional enhancement if user confirms interest - -2. **Mobile column visibility** - - What we know: Desktop shows 4 columns (NAME, SIZE, TYPE, MODIFIED), current responsive.css hides date - - What's unclear: Exact mobile design column structure from Pencil file (need to render mobile frame to confirm) - - Recommendation: Keep existing responsive behavior (hide date on mobile), verify against rendered design + - Decision: User confirmed full animated matrix rain effect (not static) + - Implementation: Canvas-based, ~30fps, requestAnimationFrame, low opacity (0.25) + +2. **Mobile column visibility** — **RESOLVED: Use 2-row stacked layout** + - What we know: Desktop shows 4 columns (NAME, SIZE, TYPE, MODIFIED) + - Decision: Mobile uses 2-row stacked layout per Pencil design (node ZVAUX) + - Row 1: [DIR]/[FILE] icon + filename (left aligned) + - Row 2: Modified date (left) | Size (right) — space-between + - Implementation: Change mobile CSS from grid columns to vertical flex layout 3. **Error/warning colors** - What we know: CONTEXT.md mentions "add red for errors, yellow for warnings" diff --git a/designs/cipher-box-design.pen b/designs/cipher-box-design.pen index 19558cdf1d..2606e2bff1 100644 --- a/designs/cipher-box-design.pen +++ b/designs/cipher-box-design.pen @@ -1661,16 +1661,6 @@ "fontWeight": "normal" } ] - }, - { - "type": "text", - "id": "UuUso", - "name": "mRow2Size", - "fill": "#006644", - "content": "4.2 GB", - "fontFamily": "JetBrains Mono", - "fontSize": 10, - "fontWeight": "normal" } ] }, @@ -1680,23 +1670,24 @@ "name": "mRow2Bottom", "width": "fill_container", "gap": 12, + "justifyContent": "space_between", "children": [ { "type": "text", - "id": "Oczq6", - "name": "mRow2Type", + "id": "fISJ6", + "name": "mRow2Modified", "fill": "#006644", - "content": "dir", + "content": "2026-01-20 14:32", "fontFamily": "JetBrains Mono", "fontSize": 9, "fontWeight": "normal" }, { "type": "text", - "id": "fISJ6", - "name": "mRow2Modified", + "id": "bBDIP", + "name": "mRow2Size", "fill": "#006644", - "content": "2026-01-20 14:32", + "content": "4.2 GB", "fontFamily": "JetBrains Mono", "fontSize": 9, "fontWeight": "normal" @@ -1760,16 +1751,6 @@ "fontWeight": "normal" } ] - }, - { - "type": "text", - "id": "quPft", - "name": "mRow3Size", - "fill": "#006644", - "content": "1.8 GB", - "fontFamily": "JetBrains Mono", - "fontSize": 10, - "fontWeight": "normal" } ] }, @@ -1779,23 +1760,24 @@ "name": "mRow3Bottom", "width": "fill_container", "gap": 12, + "justifyContent": "space_between", "children": [ { "type": "text", - "id": "7wWjA", - "name": "mRow3Type", + "id": "4OQUu", + "name": "mRow3Modified", "fill": "#006644", - "content": "dir", + "content": "2026-01-22 09:15", "fontFamily": "JetBrains Mono", "fontSize": 9, "fontWeight": "normal" }, { "type": "text", - "id": "4OQUu", - "name": "mRow3Modified", + "id": "s2zqk", + "name": "mRow3Size", "fill": "#006644", - "content": "2026-01-22 09:15", + "content": "1.8 GB", "fontFamily": "JetBrains Mono", "fontSize": 9, "fontWeight": "normal" @@ -1859,16 +1841,6 @@ "fontWeight": "normal" } ] - }, - { - "type": "text", - "id": "Lhljr", - "name": "mRow4Size", - "fill": "#006644", - "content": "7.5 GB", - "fontFamily": "JetBrains Mono", - "fontSize": 10, - "fontWeight": "normal" } ] }, @@ -1878,23 +1850,24 @@ "name": "mRow4Bottom", "width": "fill_container", "gap": 12, + "justifyContent": "space_between", "children": [ { "type": "text", - "id": "CLjWS", - "name": "mRow4Type", + "id": "Yx41C", + "name": "mRow4Modified", "fill": "#006644", - "content": "dir", + "content": "2026-01-23 11:45", "fontFamily": "JetBrains Mono", "fontSize": 9, "fontWeight": "normal" }, { "type": "text", - "id": "Yx41C", - "name": "mRow4Modified", + "id": "rRWMs", + "name": "mRow4Size", "fill": "#006644", - "content": "2026-01-23 11:45", + "content": "7.5 GB", "fontFamily": "JetBrains Mono", "fontSize": 9, "fontWeight": "normal" @@ -1958,16 +1931,6 @@ "fontWeight": "normal" } ] - }, - { - "type": "text", - "id": "85UJI", - "name": "mRow5Size", - "fill": "#006644", - "content": "2.4 MB", - "fontFamily": "JetBrains Mono", - "fontSize": 10, - "fontWeight": "normal" } ] }, @@ -1977,23 +1940,24 @@ "name": "mRow5Bottom", "width": "fill_container", "gap": 12, + "justifyContent": "space_between", "children": [ { "type": "text", - "id": "2rycB", - "name": "mRow5Type", + "id": "jcJiO", + "name": "mRow5Modified", "fill": "#006644", - "content": "pdf", + "content": "2026-01-21 16:20", "fontFamily": "JetBrains Mono", "fontSize": 9, "fontWeight": "normal" }, { "type": "text", - "id": "jcJiO", - "name": "mRow5Modified", + "id": "vJoZq", + "name": "mRow5Size", "fill": "#006644", - "content": "2026-01-21 16:20", + "content": "2.4 MB", "fontFamily": "JetBrains Mono", "fontSize": 9, "fontWeight": "normal" @@ -2057,16 +2021,6 @@ "fontWeight": "normal" } ] - }, - { - "type": "text", - "id": "qkRp0", - "name": "mRow6Size", - "fill": "#006644", - "content": "856 KB", - "fontFamily": "JetBrains Mono", - "fontSize": 10, - "fontWeight": "normal" } ] }, @@ -2076,23 +2030,24 @@ "name": "mRow6Bottom", "width": "fill_container", "gap": 12, + "justifyContent": "space_between", "children": [ { "type": "text", - "id": "q9JhN", - "name": "mRow6Type", + "id": "P6ZHl", + "name": "mRow6Modified", "fill": "#006644", - "content": "docx", + "content": "2026-01-22 13:08", "fontFamily": "JetBrains Mono", "fontSize": 9, "fontWeight": "normal" }, { "type": "text", - "id": "P6ZHl", - "name": "mRow6Modified", + "id": "MUupx", + "name": "mRow6Size", "fill": "#006644", - "content": "2026-01-22 13:08", + "content": "856 KB", "fontFamily": "JetBrains Mono", "fontSize": 9, "fontWeight": "normal" @@ -2156,16 +2111,6 @@ "fontWeight": "normal" } ] - }, - { - "type": "text", - "id": "XLqMB", - "name": "mRow7Size", - "fill": "#006644", - "content": "14.2 MB", - "fontFamily": "JetBrains Mono", - "fontSize": 10, - "fontWeight": "normal" } ] }, @@ -2175,23 +2120,24 @@ "name": "mRow7Bottom", "width": "fill_container", "gap": 12, + "justifyContent": "space_between", "children": [ { "type": "text", - "id": "OPhfh", - "name": "mRow7Type", + "id": "QnS6X", + "name": "mRow7Modified", "fill": "#006644", - "content": "csv", + "content": "2026-01-19 08:42", "fontFamily": "JetBrains Mono", "fontSize": 9, "fontWeight": "normal" }, { "type": "text", - "id": "QnS6X", - "name": "mRow7Modified", + "id": "gSbTn", + "name": "mRow7Size", "fill": "#006644", - "content": "2026-01-19 08:42", + "content": "14.2 MB", "fontFamily": "JetBrains Mono", "fontSize": 9, "fontWeight": "normal" From d3743d34e1e722a235ccf4f6fda6f00db1c5dc11 Mon Sep 17 00:00:00 2001 From: Michael Yankelev <myankelev@gmail.com> Date: Fri, 23 Jan 2026 04:18:22 +0100 Subject: [PATCH 03/33] feat(06.2-01): add JetBrains Mono font to index.html - Add Google Fonts preconnect for performance - Load JetBrains Mono with weights 400, 600, 700 - Positioned before title tag in head section - Enables monospace typography for terminal aesthetic --- apps/web/index.html | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/apps/web/index.html b/apps/web/index.html index 9fa40a1463..7e73e831f6 100644 --- a/apps/web/index.html +++ b/apps/web/index.html @@ -4,6 +4,14 @@ <meta charset="UTF-8" /> <link rel="icon" type="image/png" href="/favicon.png" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + + <!-- Preconnect to Google Fonts --> + <link rel="preconnect" href="https://fonts.googleapis.com"> + <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> + + <!-- Load JetBrains Mono (400, 600, 700 weights) --> + <link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;600;700&display=swap" rel="stylesheet"> + <title>CipherBox From de77844a8a3dde021c927f3932ad08af03f90666 Mon Sep 17 00:00:00 2001 From: Michael Yankelev Date: Fri, 23 Jan 2026 04:18:56 +0100 Subject: [PATCH 04/33] feat(06.2-01): create design tokens in index.css - Replace Inter font with JetBrains Mono monospace - Change background from #242424 to pure black #000000 - Add complete CSS custom properties system: - Color primitives (green primary #00D084, black, dim variants) - Semantic colors (error, warning) - Typography tokens (font sizes, weights) - Spacing scale (8px to 32px) - Effects (green glow, border thickness) - Remove place-items: center from body layout - Add accessibility focus styles and selection colors - Foundation for terminal/hacker aesthetic --- apps/web/src/index.css | 106 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 93 insertions(+), 13 deletions(-) diff --git a/apps/web/src/index.css b/apps/web/src/index.css index e4af02fc21..309ee4dca4 100644 --- a/apps/web/src/index.css +++ b/apps/web/src/index.css @@ -1,30 +1,110 @@ +/* ========================================================================== + Design Tokens - Terminal/Hacker Aesthetic + ========================================================================== */ + :root { - font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; - line-height: 1.5; - font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: #242424; - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; + /* Color Primitives */ + --color-black: #000000; + --color-green-primary: #00D084; + --color-green-dim: #006644; + --color-green-darker: #003322; + --color-green-glow: #00D08466; /* 40% opacity for shadows */ + + /* Semantic Colors - Error/Warning */ + --color-error: #EF4444; + --color-error-dim: #7F1D1D; + --color-warning: #F59E0B; + --color-warning-dim: #78350F; + + /* Background & Text */ + --color-background: var(--color-black); + --color-border: var(--color-green-primary); + --color-border-dim: var(--color-green-darker); + --color-text-primary: var(--color-green-primary); + --color-text-secondary: var(--color-green-dim); + + /* Typography */ + --font-family-mono: "JetBrains Mono", monospace; + --font-size-xs: 10px; /* Status text */ + --font-size-sm: 11px; /* Body, buttons, file list */ + --font-size-md: 14px; /* App name */ + --font-size-lg: 18px; /* Prompt symbol */ + --font-size-xl: 24px; /* Login logo */ + + /* Font Weights */ + --font-weight-normal: 400; + --font-weight-semibold: 600; + --font-weight-bold: 700; + + /* Spacing (from design file) */ + --spacing-xs: 8px; + --spacing-sm: 12px; + --spacing-md: 16px; + --spacing-lg: 24px; + --spacing-xl: 32px; + + /* Effects */ + --glow-green: 0 0 10px var(--color-green-glow); + --border-thickness: 1px; + + /* Remove color-scheme to enforce dark mode only */ + color-scheme: dark; } +/* ========================================================================== + Global Resets + ========================================================================== */ + * { box-sizing: border-box; margin: 0; padding: 0; } +/* ========================================================================== + Base Styles + ========================================================================== */ + +html { + font-family: var(--font-family-mono); + font-size: var(--font-size-sm); + line-height: 1.5; + font-weight: var(--font-weight-normal); + color: var(--color-text-primary); + background-color: var(--color-background); + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + body { min-height: 100vh; - display: flex; - place-items: center; - justify-content: center; } #root { width: 100%; min-height: 100vh; } + +/* Links */ +a { + color: var(--color-text-primary); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +/* Focus styles for accessibility */ +:focus-visible { + outline: 2px solid var(--color-green-primary); + outline-offset: 2px; +} + +/* Selection */ +::selection { + background-color: var(--color-green-primary); + color: var(--color-black); +} From feeb4ae1a7c331b9539e0995cc1daf32ff2193f9 Mon Sep 17 00:00:00 2001 From: Michael Yankelev Date: Fri, 23 Jan 2026 04:19:31 +0100 Subject: [PATCH 05/33] feat(06.2-01): restyle login page in App.css - Update login container with terminal aesthetic styling - Add > CIPHERBOX prompt using ::before pseudo-element - Convert login button to sharp corners (border-radius: 0) - Change button from gradient to solid green (#00D084) - Add uppercase text transform and letter spacing - Update dashboard header to use design tokens - Convert API status indicator to use CSS variables - Use monospace font throughout - All colors now reference CSS custom properties - Terminal/hacker aesthetic with green-on-black theme --- apps/web/src/App.css | 139 +++++++++++++++++++++++++++++++------------ 1 file changed, 101 insertions(+), 38 deletions(-) diff --git a/apps/web/src/App.css b/apps/web/src/App.css index b7c6fcbf1a..87b7ec2d4b 100644 --- a/apps/web/src/App.css +++ b/apps/web/src/App.css @@ -3,95 +3,158 @@ @import './styles/breadcrumbs.css'; @import './styles/responsive.css'; +/* ========================================================================== + Login Page - Terminal Aesthetic + ========================================================================== */ + .login-container { display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 100vh; - padding: 2rem; + padding: var(--spacing-lg); text-align: center; + position: relative; + overflow: hidden; } +/* Logo: > CIPHERBOX with terminal prompt */ .login-container h1 { - font-size: 3rem; - margin-bottom: 0.5rem; + font-family: var(--font-family-mono); + font-size: var(--font-size-xl); + font-weight: var(--font-weight-bold); + color: var(--color-text-primary); + margin-bottom: var(--spacing-xs); + letter-spacing: 0.05em; +} + +.login-container h1::before { + content: "> "; + color: var(--color-text-primary); +} + +/* Tagline */ +.login-container .tagline { + font-size: var(--font-size-sm); + color: var(--color-text-secondary); + margin-bottom: var(--spacing-md); + text-transform: uppercase; + letter-spacing: 0.1em; } -.login-container p { - color: rgba(255, 255, 255, 0.6); - margin-bottom: 2rem; +.login-container .login-description { + font-size: var(--font-size-sm); + color: var(--color-text-secondary); + margin-bottom: var(--spacing-lg); + max-width: 400px; } +/* Terminal-style connect button */ .login-button { - padding: 1rem 2rem; - font-size: 1.1rem; - font-weight: 500; - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); - color: white; + padding: var(--spacing-sm) var(--spacing-lg); + font-family: var(--font-family-mono); + font-size: var(--font-size-sm); + font-weight: var(--font-weight-semibold); + background-color: var(--color-green-primary); + color: var(--color-black); border: none; - border-radius: 8px; + border-radius: 0; /* Sharp corners for terminal aesthetic */ cursor: pointer; - transition: transform 0.2s, box-shadow 0.2s; + transition: box-shadow 0.2s ease, transform 0.1s ease; + text-transform: uppercase; + letter-spacing: 0.05em; } .login-button:hover { - transform: translateY(-2px); - box-shadow: 0 4px 20px rgba(102, 126, 234, 0.4); + box-shadow: var(--glow-green); + transform: translateY(-1px); +} + +.login-button:active { + transform: translateY(0); +} + +.login-button:disabled { + opacity: 0.6; + cursor: not-allowed; } .login-note { - margin-top: 2rem; - font-size: 0.875rem; - color: rgba(255, 255, 255, 0.4); + margin-top: var(--spacing-lg); + font-size: var(--font-size-xs); + color: var(--color-text-secondary); } +/* ========================================================================== + Dashboard Layout + ========================================================================== */ + .dashboard-container { display: flex; flex-direction: column; min-height: 100vh; + background-color: var(--color-background); } .dashboard-header { display: flex; justify-content: space-between; align-items: center; - padding: 1rem 2rem; - border-bottom: 1px solid rgba(255, 255, 255, 0.1); + padding: var(--spacing-sm) var(--spacing-md); + border-bottom: var(--border-thickness) solid var(--color-border); + background-color: var(--color-background); +} + +/* Header branding: > CIPHERBOX */ +.dashboard-header h1, +.dashboard-header .app-title { + font-family: var(--font-family-mono); + font-size: var(--font-size-md); + font-weight: var(--font-weight-semibold); + color: var(--color-text-primary); } .logout-link { - color: rgba(255, 255, 255, 0.6); + font-family: var(--font-family-mono); + font-size: var(--font-size-sm); + color: var(--color-text-secondary); text-decoration: none; + text-transform: lowercase; } .logout-link:hover { - color: white; + color: var(--color-text-primary); + text-decoration: none; } .dashboard-main { display: flex; flex: 1; + background-color: var(--color-background); } -/* Note: file-browser and folder-tree styles are in file-browser.css */ - .placeholder-text { - color: rgba(255, 255, 255, 0.3); - font-style: italic; - margin-top: 1rem; + color: var(--color-text-secondary); + font-style: normal; + margin-top: var(--spacing-md); } -/* API Status Indicator */ +/* ========================================================================== + API Status Indicator + ========================================================================== */ + .api-status { position: fixed; - bottom: 1rem; - right: 1rem; + bottom: var(--spacing-md); + right: var(--spacing-md); display: flex; align-items: center; - gap: 0.5rem; - font-size: 0.75rem; - color: rgba(255, 255, 255, 0.6); + gap: var(--spacing-xs); + font-family: var(--font-family-mono); + font-size: var(--font-size-xs); + color: var(--color-text-secondary); + text-transform: lowercase; } .status-dot { @@ -101,15 +164,15 @@ } .status-dot.online { - background-color: #22c55e; - box-shadow: 0 0 6px #22c55e; + background-color: var(--color-green-primary); + box-shadow: 0 0 6px var(--color-green-primary); } .status-dot.offline { - background-color: #ef4444; - box-shadow: 0 0 6px #ef4444; + background-color: var(--color-error); + box-shadow: 0 0 6px var(--color-error); } .status-dot.loading { - background-color: #6b7280; + background-color: var(--color-text-secondary); } From bd787d6e9e9dba244f514a13b2a728ab4d6b59d9 Mon Sep 17 00:00:00 2001 From: Michael Yankelev Date: Fri, 23 Jan 2026 04:22:06 +0100 Subject: [PATCH 06/33] docs(06.2-01): complete design foundation plan Tasks completed: 3/3 - Task 1: Add JetBrains Mono font to index.html - Task 2: Create design tokens in index.css - Task 3: Restyle login page in App.css SUMMARY: .planning/phases/06.2-restyle-app-with-pencil-design/06.2-01-SUMMARY.md --- .planning/STATE.md | 35 ++-- .../06.2-01-SUMMARY.md | 155 ++++++++++++++++++ 2 files changed, 176 insertions(+), 14 deletions(-) create mode 100644 .planning/phases/06.2-restyle-app-with-pencil-design/06.2-01-SUMMARY.md diff --git a/.planning/STATE.md b/.planning/STATE.md index 9d878e525c..02b5de3347 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -9,20 +9,20 @@ See: .planning/PROJECT.md (updated 2026-01-20) ## Current Position -Phase: 6.1 of 11 (Webapp Automation Testing) - COMPLETE -Plan: 6 of 6 in Phase 6.1 complete -Status: Complete - All E2E tests and CI integration done -Last activity: 2026-01-22 - Completed quick task 001: API status indicator on login page +Phase: 6.2 of 11 (Restyle App with Pencil Design) - IN PROGRESS +Plan: 1 of 7 in Phase 6.2 complete +Status: In progress - Design foundation established +Last activity: 2026-01-23 - Completed 06.2-01-PLAN.md (Design Foundation) -Progress: [#######...] 72% (34 of 47 plans) +Progress: [#######...] 74% (35 of 47 plans) ## Performance Metrics **Velocity:** -- Total plans completed: 34 -- Average duration: 5.1 min -- Total execution time: 2.9 hours +- Total plans completed: 35 +- Average duration: 5.0 min +- Total execution time: 3.0 hours **By Phase:** @@ -37,11 +37,12 @@ Progress: [#######...] 72% (34 of 47 plans) | 05-folder-system | 4/4 | 18 min | 4.5 min | | 06-file-browser-ui | 4/4 | 19 min | 4.8 min | | 06.1-webapp-automation | 6/6 | 25 min | 4.2 min | +| 06.2-pencil-restyle | 1/7 | 3 min | 2.5 min | **Recent Trend:** -- Last 5 plans: 4m, 4m, 3m, 4m, 2m -- Trend: Consistent, improving +- Last 5 plans: 4m, 3m, 4m, 2m, 2.5m +- Trend: Consistent, excellent velocity _Updated after each plan completion_ @@ -151,6 +152,12 @@ Recent decisions affecting current work: | ESM for E2E test files | 06.1-03 | Consistent with monorepo type:module, avoids require() issues | | Separate E2E workspace package | 06.1-03 | Isolated dependencies, independent test execution from unit tests | | Multi-browser testing (Chromium/Firefox/WebKit) | 06.1-03 | Cross-browser compatibility validation catches browser-specific bugs | +| Google Fonts CDN for JetBrains Mono | 06.2-01 | Simpler than self-hosting, leverages CDN performance | +| CSS custom properties for design tokens | 06.2-01 | All colors, typography, spacing via CSS variables for consistency | +| Pure black background (#000000) | 06.2-01 | Maximum contrast for terminal aesthetic, not near-black | +| Terminal prompt (>) via ::before pseudo-element | 06.2-01 | CSS-only implementation, not hardcoded in JSX components | +| Sharp corners (border-radius: 0) for terminal UX | 06.2-01 | Matches terminal/hacker aesthetic, no rounded corners | +| Green glow effects at 40% opacity | 06.2-01 | Hover states use box-shadow with --color-green-glow (40% alpha) | ### Pending Todos @@ -188,12 +195,12 @@ Recent decisions affecting current work: ## Session Continuity -Last session: 2026-01-22 -Stopped at: Phase 6.1 Complete - Webapp Automation Testing verified +Last session: 2026-01-23 +Stopped at: Completed 06.2-01-PLAN.md - Design Foundation established Resume file: None -Next phase: Phase 6.2 (Restyle App with Pencil Design) +Next plan: 06.2-02 (Component Styling) --- _State initialized: 2026-01-20_ -_Last updated: 2026-01-22 after 06.1-03 completion_ +_Last updated: 2026-01-23 after 06.2-01 completion_ diff --git a/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-01-SUMMARY.md b/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-01-SUMMARY.md new file mode 100644 index 0000000000..5c88a5d11d --- /dev/null +++ b/.planning/phases/06.2-restyle-app-with-pencil-design/06.2-01-SUMMARY.md @@ -0,0 +1,155 @@ +--- +phase: 06.2-restyle-app-pencil-design +plan: 01 +subsystem: ui +tags: [css, design-tokens, typography, jetbrains-mono, terminal-aesthetic] + +# Dependency graph +requires: + - phase: 06.1-webapp-automation + provides: Working web application with login and dashboard +provides: + - CSS custom properties system for colors, typography, spacing, effects + - JetBrains Mono monospace font loaded from Google Fonts + - Terminal/hacker aesthetic design foundation + - Pure black background with green accent colors + - Design tokens ready for component styling +affects: [06.2-02, 06.2-03, 06.2-04, 06.2-05, 06.2-06, 06.2-07] + +# Tech tracking +tech-stack: + added: [JetBrains Mono from Google Fonts] + patterns: + - CSS custom properties for design tokens + - Terminal prompt symbol (>) using ::before pseudo-element + - Sharp corners (border-radius: 0) for terminal aesthetic + - Green glow effects on interactive elements + +key-files: + created: [] + modified: + - apps/web/index.html + - apps/web/src/index.css + - apps/web/src/App.css + +key-decisions: + - 'Use JetBrains Mono with weights 400, 600, 700 for complete typography system' + - 'Pure black (#000000) background instead of gray (#242424)' + - 'Green primary color #00D084 from Pencil design specification' + - 'CSS custom properties in :root for all design tokens (colors, typography, spacing)' + - 'Terminal prompt symbol > added via CSS ::before for CIPHERBOX branding' + - 'Sharp corners (border-radius: 0) for all buttons to match terminal aesthetic' + +patterns-established: + - 'Design tokens pattern: All colors, fonts, spacing via CSS variables' + - 'Naming convention: --color-*, --font-*, --spacing-*, --glow-*' + - 'Monospace typography throughout entire application' + - 'Terminal aesthetic: green-on-black with sharp corners and glow effects' + +# Metrics +duration: 2.5min +completed: 2026-01-23 +--- + +# Phase 6.2 Plan 01: Design Foundation Summary + +**JetBrains Mono monospace typography system with pure black background, green accent colors (#00D084), and complete CSS custom properties for terminal/hacker aesthetic** + +## Performance + +- **Duration:** 2.5 min (150 seconds) +- **Started:** 2026-01-23T03:17:59Z +- **Completed:** 2026-01-23T03:20:24Z +- **Tasks:** 3 +- **Files modified:** 3 + +## Accomplishments + +- Loaded JetBrains Mono font (400, 600, 700 weights) from Google Fonts with preconnect optimization +- Created comprehensive CSS custom properties system with color primitives, semantic colors, typography scales, spacing tokens, and effects +- Restyled login page and dashboard header to terminal aesthetic with > CIPHERBOX prompt branding +- Replaced gradient buttons with solid green on black, sharp corners, and green glow hover effects +- Established design token foundation that all subsequent component styling plans depend on + +## Task Commits + +Each task was committed atomically: + +1. **Task 1: Add JetBrains Mono font to index.html** - `d3743d3` (feat) +2. **Task 2: Create design tokens in index.css** - `de77844` (feat) +3. **Task 3: Restyle login page in App.css** - `feeb4ae` (feat) + +## Files Created/Modified + +- `apps/web/index.html` - Added Google Fonts preconnect and JetBrains Mono stylesheet link +- `apps/web/src/index.css` - Complete design token system: colors (green primary #00D084, black background), typography (JetBrains Mono with size/weight scales), spacing (8px-32px), effects (green glow) +- `apps/web/src/App.css` - Login page terminal aesthetic: > CIPHERBOX prompt branding, sharp corner buttons, green-on-black theme, design token integration for dashboard and API status indicator + +## Decisions Made + +**Font Loading Strategy:** + +- Use Google Fonts CDN instead of self-hosted fonts for simplicity and CDN performance +- Preconnect to fonts.googleapis.com and fonts.gstatic.com for faster font loading +- Load only weights 400 (normal), 600 (semibold), 700 (bold) as specified in design + +**Design Token Organization:** + +- Organize CSS variables by category: color primitives → semantic colors → typography → spacing → effects +- Use semantic naming: --color-text-primary instead of --green-1 +- Reference primitives in semantic tokens: --color-text-primary: var(--color-green-primary) +- Document intended usage in comments (e.g., --font-size-xs: 10px; /_ Status text _/) + +**Terminal Aesthetic Implementation:** + +- Terminal prompt symbol (>) implemented via ::before pseudo-element (not hardcoded in JSX) +- Sharp corners (border-radius: 0) for all buttons to match terminal/hacker aesthetic +- Green glow effect (box-shadow with 40% opacity green) on hover states +- Uppercase text transform with letter spacing for buttons and UI chrome + +**Color System:** + +- Pure black (#000000) instead of near-black for maximum contrast +- Green variants: primary (#00D084), dim (#006644), darker (#003322) for hierarchy +- Green glow (#00D08466) at 40% opacity for shadow effects +- Separate error/warning colors (red/orange) for future use + +## Deviations from Plan + +None - plan executed exactly as written. + +## Issues Encountered + +None - all tasks completed as planned with successful build verification. + +## User Setup Required + +None - no external service configuration required. + +## Next Phase Readiness + +**Ready for component styling:** + +- All CSS custom properties available in :root for use across components +- JetBrains Mono font loaded and set as default via --font-family-mono +- Color system established with primary green, background black, and text colors +- Spacing scale (--spacing-xs through --spacing-xl) ready for consistent layouts +- Effects (--glow-green) available for interactive states + +**Design token usage pattern:** + +```css +.my-component { + background-color: var(--color-background); + color: var(--color-text-primary); + font-family: var(--font-family-mono); + padding: var(--spacing-md); +} +``` + +**No blockers or concerns** - foundation complete and verified with successful build. + +--- + +_Phase: 06.2-restyle-app-pencil-design_ +_Completed: 2026-01-23_ From ad043a8f9225272b66f83f27317609c86665bef6 Mon Sep 17 00:00:00 2001 From: Michael Yankelev Date: Fri, 23 Jan 2026 04:26:49 +0100 Subject: [PATCH 07/33] style(06.2-03): restyle context menu with terminal aesthetic - Remove all light mode CSS and prefers-color-scheme queries - Use design token variables throughout - Remove border-radius (sharp corners) - Add green glow to box-shadow - Monospace font for menu items - Green hover states and focus indicators --- apps/web/src/styles/context-menu.css | 94 +++++++++++++++------------- 1 file changed, 49 insertions(+), 45 deletions(-) diff --git a/apps/web/src/styles/context-menu.css b/apps/web/src/styles/context-menu.css index bf01fa005a..053ead78ad 100644 --- a/apps/web/src/styles/context-menu.css +++ b/apps/web/src/styles/context-menu.css @@ -1,49 +1,39 @@ -/* Context Menu Container */ +/** + * Context Menu Styles - Terminal Aesthetic + * + * Right-click menu for file/folder actions + * Green border, black background, monospace font + */ + +/* ========================================================================== + Context Menu Container + ========================================================================== */ + .context-menu { position: absolute; z-index: 1100; - min-width: 160px; - padding: 4px 0; + min-width: 180px; + padding: var(--spacing-xs) 0; overflow: hidden; - background-color: var(--context-menu-bg, #ffffff); - border: 1px solid var(--context-menu-border, #e5e7eb); - border-radius: 6px; - box-shadow: - 0 4px 6px -1px rgba(0, 0, 0, 0.1), - 0 2px 4px -1px rgba(0, 0, 0, 0.06); + background-color: var(--color-background); + border: var(--border-thickness) solid var(--color-border); + border-radius: 0; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5), var(--glow-green); } -/* Dark mode support */ -@media (prefers-color-scheme: dark) { - .context-menu { - --context-menu-bg: #1f2937; - --context-menu-border: #374151; - --context-menu-text: #f9fafb; - --context-menu-hover: #374151; - --context-menu-destructive: #ef4444; - --context-menu-destructive-hover: rgba(239, 68, 68, 0.1); - } -} - -/* Light mode defaults */ -:root { - --context-menu-bg: #ffffff; - --context-menu-border: #e5e7eb; - --context-menu-text: #374151; - --context-menu-hover: #f3f4f6; - --context-menu-destructive: #dc2626; - --context-menu-destructive-hover: rgba(220, 38, 38, 0.1); -} +/* ========================================================================== + Menu Item + ========================================================================== */ -/* Menu Item */ .context-menu-item { display: flex; align-items: center; - gap: 8px; + gap: var(--spacing-xs); width: 100%; - padding: 8px 12px; - font-size: 0.875rem; - color: var(--context-menu-text); + padding: var(--spacing-xs) var(--spacing-sm); + font-family: var(--font-family-mono); + font-size: var(--font-size-sm); + color: var(--color-text-primary); text-align: left; cursor: pointer; background: transparent; @@ -53,37 +43,51 @@ .context-menu-item:hover, .context-menu-item:focus { - background-color: var(--context-menu-hover); + background-color: var(--color-green-darker); outline: none; } .context-menu-item:focus-visible { - outline: 2px solid #3b82f6; + outline: 2px solid var(--color-green-primary); outline-offset: -2px; } -/* Menu Item Icon */ +/* ========================================================================== + Menu Item Icon + ========================================================================== */ + .context-menu-item-icon { display: inline-flex; align-items: center; justify-content: center; width: 16px; - font-size: 0.875rem; + font-size: var(--font-size-sm); + color: var(--color-text-secondary); } -/* Destructive Action (Delete) */ +/* ========================================================================== + Destructive Action (Delete) + ========================================================================== */ + .context-menu-item--destructive { - color: var(--context-menu-destructive); + color: var(--color-error); +} + +.context-menu-item--destructive .context-menu-item-icon { + color: var(--color-error); } .context-menu-item--destructive:hover, .context-menu-item--destructive:focus { - background-color: var(--context-menu-destructive-hover); + background-color: var(--color-error-dim); } -/* Divider */ +/* ========================================================================== + Divider + ========================================================================== */ + .context-menu-divider { height: 1px; - margin: 4px 0; - background-color: var(--context-menu-border); + margin: var(--spacing-xs) 0; + background-color: var(--color-border-dim); } From 61e2fd15e49d582461beae7538a767946d0a7201 Mon Sep 17 00:00:00 2001 From: Michael Yankelev Date: Fri, 23 Jan 2026 04:26:56 +0100 Subject: [PATCH 08/33] feat(06.2-04): update responsive.css with terminal aesthetic - Replace all rgba colors with design token variables - Remove border-radius values (set to 0 for terminal aesthetic) - Use green color scheme for all hover/active states - Update file list to use 2-row stacked layout on mobile - Hide TYPE column on mobile - Add terminal styling to sidebar overlay Co-Authored-By: Claude Opus 4.5 --- apps/web/src/styles/responsive.css | 125 ++++++++++++++++++++--------- 1 file changed, 87 insertions(+), 38 deletions(-) diff --git a/apps/web/src/styles/responsive.css b/apps/web/src/styles/responsive.css index a46f9225d0..bd9511ed26 100644 --- a/apps/web/src/styles/responsive.css +++ b/apps/web/src/styles/responsive.css @@ -1,5 +1,5 @@ /** - * Responsive Styles + * Responsive Styles - Terminal Aesthetic * * Mobile-first responsive design for the file browser. * Breakpoint: 768px (tablet/desktop boundary) @@ -23,22 +23,22 @@ height: 2.5rem; padding: 0; background: transparent; - border: 1px solid rgba(255, 255, 255, 0.2); - border-radius: 6px; - color: rgba(255, 255, 255, 0.9); + border: var(--border-thickness) solid var(--color-border); + border-radius: 0; + color: var(--color-text-primary); font-size: 1.25rem; cursor: pointer; - transition: background-color 0.15s ease, border-color 0.15s ease; + transition: background-color 0.15s ease, box-shadow 0.15s ease; flex-shrink: 0; } .file-browser-toggle:hover { - background: rgba(255, 255, 255, 0.1); - border-color: rgba(255, 255, 255, 0.3); + background-color: var(--color-green-darker); + box-shadow: var(--glow-green); } .file-browser-toggle:focus { - outline: 2px solid rgba(102, 126, 234, 0.6); + outline: 2px solid var(--color-green-primary); outline-offset: 2px; } @@ -53,7 +53,7 @@ left: 0; right: 0; bottom: 0; - background: rgba(0, 0, 0, 0.5); + background: rgba(0, 0, 0, 0.8); z-index: 99; animation: fadeIn 0.2s ease; } @@ -70,8 +70,8 @@ /* Sidebar close button (mobile) */ .file-browser-sidebar-close { position: absolute; - top: 0.75rem; - right: 0.75rem; + top: var(--spacing-sm); + right: var(--spacing-sm); display: flex; align-items: center; justify-content: center; @@ -79,16 +79,18 @@ height: 2rem; padding: 0; background: transparent; - border: none; - color: rgba(255, 255, 255, 0.6); + border: var(--border-thickness) solid var(--color-border); + border-radius: 0; + color: var(--color-text-secondary); font-size: 1.25rem; cursor: pointer; - transition: color 0.15s ease; + transition: color 0.15s ease, background-color 0.15s ease; z-index: 1; } .file-browser-sidebar-close:hover { - color: rgba(255, 255, 255, 0.9); + color: var(--color-text-primary); + background-color: var(--color-green-darker); } /* ========================================================================== @@ -107,8 +109,9 @@ transform: translateX(-100%); transition: transform 0.3s ease; z-index: 100; - background: #1a1a2e; - box-shadow: 4px 0 20px rgba(0, 0, 0, 0.3); + background-color: var(--color-background); + border-right: var(--border-thickness) solid var(--color-border); + box-shadow: 4px 0 20px rgba(0, 0, 0, 0.5); } .file-browser-sidebar--open { @@ -126,53 +129,99 @@ /* Main content: full width */ .file-browser-main { - padding: 0.75rem; + padding: var(--spacing-sm); } /* Toolbar: add gap for hamburger */ .file-browser-toolbar { - gap: 0.5rem; + gap: var(--spacing-xs); flex-wrap: wrap; } - /* File list: hide date column, reduce size column */ - .file-list-header, + /* File list: hide header on mobile (2-row item layout) */ + .file-list-header { + display: none; + } + + /* File list items: 2-row stacked layout per Pencil design */ .file-list-item { - grid-template-columns: 1fr 80px; - gap: 0.5rem; + display: flex; + flex-direction: column; + gap: 4px; + padding: 10px 12px; + min-height: auto; } - .file-list-header-date, - .file-list-item-date { - display: none; + /* Row 1: Icon + Name (left aligned) */ + .file-list-item-row-top { + display: flex; + align-items: center; + gap: 6px; + width: 100%; } - /* File list items: touch-friendly sizing */ - .file-list-item { - padding: 0.875rem 1rem; - min-height: 3rem; + .file-list-item-icon { + font-size: 10px; + font-weight: 600; + } + + .file-list-item-name { + font-size: 11px; + flex: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + /* Row 2: Modified (left) | Size (right) - space-between */ + .file-list-item-row-bottom { + display: flex; + justify-content: space-between; + align-items: center; + gap: 12px; + width: 100%; + } + + .file-list-item-date, + .file-list-item-size { + font-size: 9px; + color: var(--color-text-secondary); + } + + /* Hide TYPE column on mobile (shown in row layout via icon) */ + .file-list-item-type { + display: none; } /* Empty state: smaller margins */ .empty-state { - margin: 1rem; + margin: var(--spacing-md); min-height: 200px; } /* Context menu: touch-friendly */ .context-menu { - min-width: 180px; + min-width: 200px; } .context-menu-item { - padding: 0.875rem 1rem; - font-size: 1rem; + padding: var(--spacing-sm) var(--spacing-md); + font-size: var(--font-size-sm); } /* Dialogs: full width on small screens */ - .modal-content { + .modal-container { max-width: calc(100vw - 2rem); - margin: 1rem; + margin: var(--spacing-md); + } + + /* Login: adjust spacing */ + .login-container { + padding: var(--spacing-md); + } + + .login-container h1 { + font-size: 1.5rem; } } @@ -214,10 +263,10 @@ /* Visual feedback for touch */ @media (pointer: coarse) { .file-list-item:active { - background: rgba(255, 255, 255, 0.1); + background-color: var(--color-green-darker); } .folder-tree-item:active { - background: rgba(255, 255, 255, 0.15); + background-color: var(--color-green-darker); } } From b69d5bf3216dfe4f78c3ad05075d24d420046f79 Mon Sep 17 00:00:00 2001 From: Michael Yankelev Date: Fri, 23 Jan 2026 04:27:13 +0100 Subject: [PATCH 09/33] style(06.2-02): restyle file browser with terminal aesthetic - Replace all rgba() colors with CSS design tokens - Add green borders (--color-border) on sidebar and file list - Change to 4-column grid (NAME, SIZE, TYPE, MODIFIED) - Remove border-radius for sharp terminal edges - Add green hover/active states using --color-green-darker - Add left border highlight for selected items - Use monospace font family (--font-family-mono) throughout - Apply terminal glow effect (--glow-green) on hover --- apps/web/src/styles/file-browser.css | 252 +++++++++++++++++---------- 1 file changed, 163 insertions(+), 89 deletions(-) diff --git a/apps/web/src/styles/file-browser.css b/apps/web/src/styles/file-browser.css index 16524509d9..47d87b4694 100644 --- a/apps/web/src/styles/file-browser.css +++ b/apps/web/src/styles/file-browser.css @@ -1,5 +1,5 @@ /** - * File Browser Component Styles + * File Browser Component Styles - Terminal Aesthetic * * Styling for the file browser UI including: * - Main layout (sidebar + content) @@ -15,32 +15,73 @@ .file-browser { display: flex; flex: 1; - min-height: 0; /* Allow shrinking in flex container */ + min-height: 0; + background-color: var(--color-background); } .file-browser-sidebar { width: 250px; min-width: 200px; max-width: 350px; - border-right: 1px solid rgba(255, 255, 255, 0.1); + border-right: var(--border-thickness) solid var(--color-border); overflow-y: auto; - background: rgba(0, 0, 0, 0.2); + background-color: var(--color-background); } .file-browser-main { flex: 1; - min-width: 0; /* Allow shrinking in flex container */ + min-width: 0; overflow-y: auto; - padding: 1rem; + padding: var(--spacing-md); + background-color: var(--color-background); } .file-browser-toolbar { display: flex; align-items: center; - gap: 1rem; - padding-bottom: 1rem; - border-bottom: 1px solid rgba(255, 255, 255, 0.1); - margin-bottom: 1rem; + gap: var(--spacing-md); + padding-bottom: var(--spacing-md); + border-bottom: var(--border-thickness) solid var(--color-border-dim); + margin-bottom: var(--spacing-md); +} + +/* Toolbar buttons - Terminal flag style */ +.file-browser-toolbar button, +.toolbar-button { + padding: var(--spacing-xs) var(--spacing-md); + font-family: var(--font-family-mono); + font-size: var(--font-size-sm); + font-weight: var(--font-weight-normal); + border-radius: 0; + cursor: pointer; + transition: box-shadow 0.15s ease; +} + +/* Primary action button (--upload) */ +.toolbar-button--primary, +.file-browser-toolbar .btn-primary { + background-color: var(--color-green-primary); + color: var(--color-black); + border: none; + font-weight: var(--font-weight-semibold); +} + +.toolbar-button--primary:hover, +.file-browser-toolbar .btn-primary:hover { + box-shadow: var(--glow-green); +} + +/* Secondary action buttons (--new-dir, --refresh) */ +.toolbar-button--secondary, +.file-browser-toolbar .btn-secondary { + background-color: transparent; + color: var(--color-text-primary); + border: var(--border-thickness) solid var(--color-border); +} + +.toolbar-button--secondary:hover, +.file-browser-toolbar .btn-secondary:hover { + box-shadow: var(--glow-green); } .file-browser-loading { @@ -48,11 +89,12 @@ align-items: center; justify-content: center; height: 200px; - color: rgba(255, 255, 255, 0.5); + color: var(--color-text-secondary); + font-family: var(--font-family-mono); } .file-browser-loading-spinner { - font-size: 0.875rem; + font-size: var(--font-size-sm); } /* ========================================================================== @@ -66,30 +108,31 @@ } .folder-tree-header { - padding: 1rem; - border-bottom: 1px solid rgba(255, 255, 255, 0.1); + padding: var(--spacing-md); + border-bottom: var(--border-thickness) solid var(--color-border-dim); } .folder-tree-title { margin: 0; - font-size: 0.875rem; - font-weight: 600; + font-family: var(--font-family-mono); + font-size: var(--font-size-xs); + font-weight: var(--font-weight-semibold); text-transform: uppercase; - letter-spacing: 0.05em; - color: rgba(255, 255, 255, 0.6); + letter-spacing: 0.1em; + color: var(--color-text-secondary); } .folder-tree-content { flex: 1; overflow-y: auto; - padding: 0.5rem 0; + padding: var(--spacing-xs) 0; } .folder-tree-placeholder { - padding: 1rem; - color: rgba(255, 255, 255, 0.4); - font-style: italic; - font-size: 0.875rem; + padding: var(--spacing-md); + color: var(--color-text-secondary); + font-style: normal; + font-size: var(--font-size-sm); } /* Folder Tree Node */ @@ -100,37 +143,40 @@ .folder-tree-item { display: flex; align-items: center; - gap: 0.25rem; - padding: 0.5rem 0.75rem; + gap: var(--spacing-xs); + padding: var(--spacing-xs) var(--spacing-sm); cursor: pointer; transition: background-color 0.15s ease; - border-radius: 4px; - margin: 0 0.5rem; + border-radius: 0; + margin: 0 var(--spacing-xs); + border-left: 2px solid transparent; } .folder-tree-item:hover { - background: rgba(255, 255, 255, 0.1); + background-color: var(--color-green-darker); + border-left-color: var(--color-green-dim); } .folder-tree-item--active { - background: rgba(102, 126, 234, 0.3); + background-color: var(--color-green-darker); + border-left-color: var(--color-green-primary); } .folder-tree-item--active:hover { - background: rgba(102, 126, 234, 0.4); + background-color: var(--color-green-darker); } .folder-tree-item--drag-over { - background: rgba(102, 126, 234, 0.5); - outline: 2px dashed rgba(102, 126, 234, 0.8); - outline-offset: -2px; + background-color: var(--color-green-darker); + border-left-color: var(--color-green-primary); + box-shadow: inset 0 0 0 1px var(--color-green-dim); } .folder-tree-toggle { width: 16px; flex-shrink: 0; - font-size: 0.625rem; - color: rgba(255, 255, 255, 0.5); + font-size: 10px; + color: var(--color-text-secondary); cursor: pointer; } @@ -139,8 +185,9 @@ } .folder-tree-icon { - font-size: 1rem; + font-size: var(--font-size-sm); flex-shrink: 0; + color: var(--color-text-primary); } .folder-tree-name { @@ -148,19 +195,17 @@ white-space: nowrap; overflow: hidden; text-overflow: ellipsis; - font-size: 0.875rem; + font-family: var(--font-family-mono); + font-size: var(--font-size-sm); + color: var(--color-text-primary); } .folder-tree-loading { - color: rgba(255, 255, 255, 0.4); - font-size: 0.75rem; + color: var(--color-text-secondary); + font-size: var(--font-size-xs); margin-left: auto; } -.folder-tree-children { - /* Child indentation handled inline via paddingLeft */ -} - /* ========================================================================== File List ========================================================================== */ @@ -168,84 +213,110 @@ .file-list { display: flex; flex-direction: column; + border: var(--border-thickness) solid var(--color-border); } .file-list-header { display: grid; - grid-template-columns: 1fr 100px 150px; - gap: 1rem; - padding: 0.75rem 1rem; - border-bottom: 1px solid rgba(255, 255, 255, 0.1); - font-size: 0.75rem; - font-weight: 600; + grid-template-columns: 1fr 120px 120px 180px; + gap: var(--spacing-md); + padding: var(--spacing-sm) var(--spacing-md); + border-bottom: var(--border-thickness) solid var(--color-border); + font-family: var(--font-family-mono); + font-size: var(--font-size-xs); + font-weight: var(--font-weight-semibold); text-transform: uppercase; - letter-spacing: 0.05em; - color: rgba(255, 255, 255, 0.5); -} - -.file-list-header-name, -.file-list-header-size, -.file-list-header-date { - /* Column styles */ + letter-spacing: 0.1em; + color: var(--color-text-primary); + background-color: var(--color-background); } .file-list-body { - /* Container for items */ + /* Container for file items */ } -/* File List Item */ +/* File List Item - Desktop uses grid, Mobile uses 2-row stacked layout */ .file-list-item { display: grid; - grid-template-columns: 1fr 100px 150px; - gap: 1rem; - padding: 0.75rem 1rem; + grid-template-columns: 1fr 120px 120px 180px; + grid-template-areas: "name size type date"; + gap: var(--spacing-md); + padding: var(--spacing-sm) var(--spacing-md); cursor: pointer; transition: background-color 0.15s ease; - border-bottom: 1px solid rgba(255, 255, 255, 0.05); + border-bottom: var(--border-thickness) solid var(--color-border-dim); + font-family: var(--font-family-mono); +} + +.file-list-item:last-child { + border-bottom: none; } .file-list-item:hover { - background: rgba(255, 255, 255, 0.05); + background-color: var(--color-green-darker); } .file-list-item--selected { - background: rgba(102, 126, 234, 0.2); + background-color: var(--color-green-darker); + border-left: 2px solid var(--color-green-primary); } .file-list-item--selected:hover { - background: rgba(102, 126, 234, 0.3); + background-color: var(--color-green-darker); } -.file-list-item-name { +/* Row wrappers - on desktop, these act as containers within grid */ +.file-list-item-row-top { + grid-area: name; display: flex; align-items: center; - gap: 0.5rem; - min-width: 0; /* Allow text truncation */ + gap: 6px; + min-width: 0; +} + +.file-list-item-row-bottom { + display: contents; /* Children participate directly in parent grid on desktop */ } .file-list-item-icon { - font-size: 1.25rem; + font-family: var(--font-family-mono); + font-size: var(--font-size-sm); + font-weight: var(--font-weight-semibold); flex-shrink: 0; + color: var(--color-text-primary); } -.file-list-item-text { +.file-list-item-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; + color: var(--color-text-primary); + font-size: var(--font-size-sm); } .file-list-item-size { + grid-area: size; + display: flex; + align-items: center; + color: var(--color-text-secondary); + font-size: var(--font-size-sm); +} + +.file-list-item-type { + grid-area: type; display: flex; align-items: center; - color: rgba(255, 255, 255, 0.6); - font-size: 0.875rem; + color: var(--color-text-secondary); + font-size: var(--font-size-sm); + text-transform: lowercase; } .file-list-item-date { + grid-area: date; display: flex; align-items: center; - color: rgba(255, 255, 255, 0.6); - font-size: 0.875rem; + color: var(--color-text-secondary); + font-size: var(--font-size-sm); } /* ========================================================================== @@ -257,43 +328,46 @@ align-items: center; justify-content: center; min-height: 300px; - border: 2px dashed rgba(255, 255, 255, 0.2); - border-radius: 12px; - margin: 2rem; + border: var(--border-thickness) dashed var(--color-border); + border-radius: 0; + margin: var(--spacing-lg); cursor: pointer; transition: border-color 0.2s ease, background-color 0.2s ease; } .empty-state:hover { - border-color: rgba(102, 126, 234, 0.5); - background: rgba(102, 126, 234, 0.05); + border-color: var(--color-green-primary); + background-color: var(--color-green-darker); } .empty-state-content { text-align: center; - padding: 2rem; + padding: var(--spacing-lg); } .empty-state-icon { - font-size: 3rem; + font-size: 2rem; display: block; - margin-bottom: 1rem; + margin-bottom: var(--spacing-md); + color: var(--color-text-secondary); } .empty-state-text { - font-size: 1.125rem; - margin: 0 0 0.5rem 0; - color: rgba(255, 255, 255, 0.8); + font-family: var(--font-family-mono); + font-size: var(--font-size-sm); + margin: 0 0 var(--spacing-xs) 0; + color: var(--color-text-primary); } .empty-state-hint { - font-size: 0.875rem; + font-family: var(--font-family-mono); + font-size: var(--font-size-xs); margin: 0; - color: rgba(255, 255, 255, 0.4); + color: var(--color-text-secondary); } .empty-state-upload { - margin-top: 1.5rem; + margin-top: var(--spacing-md); } /* Note: Mobile responsive styles are in responsive.css */ From e33e353b1663f085e6cfdbedea56fbdb0fe52266 Mon Sep 17 00:00:00 2001 From: Michael Yankelev Date: Fri, 23 Jan 2026 04:27:14 +0100 Subject: [PATCH 10/33] style(06.2-03): restyle dialogs with terminal aesthetic - Remove all light mode CSS and prefers-color-scheme queries - Use design token variables throughout - Remove border-radius (sharp corners) - Add green glow effects on focus/hover - Monospace font for all dialog text - Green primary button, red destructive button styling --- apps/web/src/styles/dialogs.css | 195 ++++++++++++++++++-------------- 1 file changed, 107 insertions(+), 88 deletions(-) diff --git a/apps/web/src/styles/dialogs.css b/apps/web/src/styles/dialogs.css index bc66e60b01..249fe4ed56 100644 --- a/apps/web/src/styles/dialogs.css +++ b/apps/web/src/styles/dialogs.css @@ -1,166 +1,185 @@ -/* Dialog Content */ +/** + * Dialog Styles - Terminal Aesthetic + * + * Dialog content for rename, delete confirmation, etc. + * Green accents, monospace font, dark only + */ + +/* ========================================================================== + Dialog Content + ========================================================================== */ + .dialog-content { display: flex; flex-direction: column; - gap: 1rem; + gap: var(--spacing-md); } -/* Dialog Message */ +/* ========================================================================== + Dialog Message + ========================================================================== */ + .dialog-message { margin: 0; - font-size: 0.9375rem; - line-height: 1.5; - color: var(--dialog-text, #4b5563); + font-family: var(--font-family-mono); + font-size: var(--font-size-sm); + line-height: 1.6; + color: var(--color-text-primary); } -/* Dialog Field */ +/* ========================================================================== + Dialog Field + ========================================================================== */ + .dialog-field { display: flex; flex-direction: column; - gap: 0.375rem; + gap: var(--spacing-xs); } -/* Dialog Label */ +/* ========================================================================== + Dialog Label + ========================================================================== */ + .dialog-label { - font-size: 0.875rem; - font-weight: 500; - color: var(--dialog-text, #374151); + font-family: var(--font-family-mono); + font-size: var(--font-size-xs); + font-weight: var(--font-weight-semibold); + text-transform: uppercase; + letter-spacing: 0.05em; + color: var(--color-text-secondary); } -/* Dialog Input */ +/* ========================================================================== + Dialog Input + ========================================================================== */ + .dialog-input { width: 100%; - padding: 0.625rem 0.75rem; - font-size: 0.9375rem; + padding: var(--spacing-xs) var(--spacing-sm); + font-family: var(--font-family-mono); + font-size: var(--font-size-sm); line-height: 1.5; - color: var(--dialog-text, #111827); - background-color: var(--dialog-input-bg, #ffffff); - border: 1px solid var(--dialog-input-border, #d1d5db); - border-radius: 6px; + color: var(--color-text-primary); + background-color: var(--color-background); + border: var(--border-thickness) solid var(--color-border); + border-radius: 0; outline: none; - transition: - border-color 0.15s ease, - box-shadow 0.15s ease; + transition: border-color 0.15s ease, box-shadow 0.15s ease; } .dialog-input:focus { - border-color: var(--dialog-input-focus, #3b82f6); - box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15); + border-color: var(--color-green-primary); + box-shadow: var(--glow-green); } .dialog-input--error { - border-color: var(--dialog-error-color, #dc2626); + border-color: var(--color-error); } .dialog-input--error:focus { - border-color: var(--dialog-error-color, #dc2626); - box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.15); + border-color: var(--color-error); + box-shadow: 0 0 10px rgba(239, 68, 68, 0.4); } .dialog-input:disabled { - opacity: 0.6; + opacity: 0.5; cursor: not-allowed; } -/* Dialog Error */ +.dialog-input::placeholder { + color: var(--color-text-secondary); +} + +/* ========================================================================== + Dialog Error + ========================================================================== */ + .dialog-error { - font-size: 0.8125rem; - color: var(--dialog-error-color, #dc2626); + font-family: var(--font-family-mono); + font-size: var(--font-size-xs); + color: var(--color-error); } -/* Dialog Actions */ +/* ========================================================================== + Dialog Actions + ========================================================================== */ + .dialog-actions { display: flex; - gap: 0.75rem; + gap: var(--spacing-sm); justify-content: flex-end; - margin-top: 0.5rem; + margin-top: var(--spacing-xs); } -/* Dialog Button Base */ +/* ========================================================================== + Dialog Button Base + ========================================================================== */ + .dialog-button { display: inline-flex; align-items: center; justify-content: center; - padding: 0.5rem 1rem; - font-size: 0.875rem; - font-weight: 500; + padding: var(--spacing-xs) var(--spacing-md); + font-family: var(--font-family-mono); + font-size: var(--font-size-sm); + font-weight: var(--font-weight-normal); line-height: 1.5; border: none; - border-radius: 6px; + border-radius: 0; cursor: pointer; - transition: - background-color 0.15s ease, - opacity 0.15s ease; + transition: background-color 0.15s ease, box-shadow 0.15s ease; } .dialog-button:disabled { - opacity: 0.6; + opacity: 0.5; cursor: not-allowed; } .dialog-button:focus-visible { - outline: 2px solid #3b82f6; + outline: 2px solid var(--color-green-primary); outline-offset: 2px; } -/* Secondary Button */ +/* ========================================================================== + Secondary Button (Cancel) + ========================================================================== */ + .dialog-button--secondary { - color: var(--dialog-text, #374151); - background-color: var(--dialog-button-secondary-bg, #f3f4f6); + color: var(--color-text-primary); + background-color: transparent; + border: var(--border-thickness) solid var(--color-border); } .dialog-button--secondary:hover:not(:disabled) { - background-color: var(--dialog-button-secondary-hover, #e5e7eb); + background-color: var(--color-green-darker); + box-shadow: var(--glow-green); } -/* Primary Button */ +/* ========================================================================== + Primary Button (Confirm) + ========================================================================== */ + .dialog-button--primary { - color: #ffffff; - background-color: var(--dialog-button-primary-bg, #3b82f6); + color: var(--color-black); + background-color: var(--color-green-primary); + font-weight: var(--font-weight-semibold); } .dialog-button--primary:hover:not(:disabled) { - background-color: var(--dialog-button-primary-hover, #2563eb); + box-shadow: var(--glow-green); } -/* Destructive Button */ +/* ========================================================================== + Destructive Button (Delete) + ========================================================================== */ + .dialog-button--destructive { - color: #ffffff; - background-color: var(--dialog-button-destructive-bg, #dc2626); + color: var(--color-black); + background-color: var(--color-error); + font-weight: var(--font-weight-semibold); } .dialog-button--destructive:hover:not(:disabled) { - background-color: var(--dialog-button-destructive-hover, #b91c1c); -} - -/* Dark mode support */ -@media (prefers-color-scheme: dark) { - :root { - --dialog-text: #f9fafb; - --dialog-input-bg: #374151; - --dialog-input-border: #4b5563; - --dialog-input-focus: #60a5fa; - --dialog-error-color: #f87171; - --dialog-button-secondary-bg: #374151; - --dialog-button-secondary-hover: #4b5563; - --dialog-button-primary-bg: #3b82f6; - --dialog-button-primary-hover: #2563eb; - --dialog-button-destructive-bg: #dc2626; - --dialog-button-destructive-hover: #b91c1c; - } -} - -/* Light mode defaults */ -:root { - --dialog-text: #374151; - --dialog-input-bg: #ffffff; - --dialog-input-border: #d1d5db; - --dialog-input-focus: #3b82f6; - --dialog-error-color: #dc2626; - --dialog-button-secondary-bg: #f3f4f6; - --dialog-button-secondary-hover: #e5e7eb; - --dialog-button-primary-bg: #3b82f6; - --dialog-button-primary-hover: #2563eb; - --dialog-button-destructive-bg: #dc2626; - --dialog-button-destructive-hover: #b91c1c; + box-shadow: 0 0 10px rgba(239, 68, 68, 0.6); } From 0758b4467860b501bdaa63022c19fb966ed53889 Mon Sep 17 00:00:00 2001 From: Michael Yankelev Date: Fri, 23 Jan 2026 04:27:26 +0100 Subject: [PATCH 11/33] feat(06.2-04): create MatrixBackground component - Canvas-based matrix rain animation - Performance-optimized: 30fps throttled rendering - Low opacity (0.25) for subtle effect - Handles window resize with cleanup - Uses JetBrains Mono font for consistency - aria-hidden for accessibility - Cleanup on unmount prevents memory leaks Co-Authored-By: Claude Opus 4.5 --- apps/web/src/components/MatrixBackground.tsx | 118 +++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 apps/web/src/components/MatrixBackground.tsx diff --git a/apps/web/src/components/MatrixBackground.tsx b/apps/web/src/components/MatrixBackground.tsx new file mode 100644 index 0000000000..0c0188f71f --- /dev/null +++ b/apps/web/src/components/MatrixBackground.tsx @@ -0,0 +1,118 @@ +import { useEffect, useRef } from 'react'; + +/** + * Matrix rain background effect for login page. + * Canvas-based animation with falling binary/hex characters. + * Performance-optimized: 30fps, low opacity, resize handling. + */ +export function MatrixBackground() { + const canvasRef = useRef(null); + const animationRef = useRef(0); + + useEffect(() => { + const canvas = canvasRef.current; + if (!canvas) return; + + const ctx = canvas.getContext('2d'); + if (!ctx) return; + + // Configuration + const FONT_SIZE = 14; + const COLUMN_WIDTH = 20; + const FRAME_INTERVAL = 33; // ~30fps + const CHARACTERS = '01'; + const PRIMARY_COLOR = '#00D084'; + const DIM_COLOR = '#006644'; + + // State + let columns: number[] = []; + let lastFrameTime = 0; + + // Resize handler + function resize() { + canvas.width = window.innerWidth; + canvas.height = window.innerHeight; + + // Initialize/reset columns + const columnCount = Math.floor(canvas.width / COLUMN_WIDTH); + columns = Array(columnCount) + .fill(0) + .map( + () => Math.random() * -100 // Start at random positions above viewport + ); + } + + // Draw frame + function draw(timestamp: number) { + // Throttle to ~30fps + if (timestamp - lastFrameTime < FRAME_INTERVAL) { + animationRef.current = requestAnimationFrame(draw); + return; + } + lastFrameTime = timestamp; + + // Fade previous frame (creates trail effect) + ctx.fillStyle = 'rgba(0, 0, 0, 0.05)'; + ctx.fillRect(0, 0, canvas.width, canvas.height); + + // Draw characters + ctx.font = `${FONT_SIZE}px "JetBrains Mono", monospace`; + + for (let i = 0; i < columns.length; i++) { + const y = columns[i] * FONT_SIZE; + + // Random character + const char = CHARACTERS[Math.floor(Math.random() * CHARACTERS.length)]; + + // Leading character is brighter + ctx.fillStyle = PRIMARY_COLOR; + ctx.fillText(char, i * COLUMN_WIDTH, y); + + // Trail characters are dimmer + if (Math.random() > 0.98) { + ctx.fillStyle = DIM_COLOR; + ctx.fillText(char, i * COLUMN_WIDTH, y - FONT_SIZE); + } + + // Move column down + columns[i]++; + + // Reset when reaching bottom (with random chance for variation) + if (y > canvas.height && Math.random() > 0.975) { + columns[i] = 0; + } + } + + animationRef.current = requestAnimationFrame(draw); + } + + // Initialize + resize(); + window.addEventListener('resize', resize); + animationRef.current = requestAnimationFrame(draw); + + // Cleanup + return () => { + window.removeEventListener('resize', resize); + cancelAnimationFrame(animationRef.current); + }; + }, []); + + return ( +