diff --git a/.claude/commands/redesign-sidebar.md b/.claude/commands/redesign-sidebar.md new file mode 100644 index 00000000..a5f811b3 --- /dev/null +++ b/.claude/commands/redesign-sidebar.md @@ -0,0 +1,501 @@ +--- +description: Redesign the app UI from a top nav bar to a modern SaaS vertical sidebar layout +--- + +# Redesign: Top Nav to Vertical Sidebar + +Transform this Vue 3 app from a horizontal top-nav layout into a modern SaaS-style layout with a fixed 240px dark vertical sidebar. Follow the steps below exactly. All `.vue` file changes **must** be delegated to the `vue-expert` subagent via the Agent tool. + +--- + +## Target Layout + +``` +┌──────────────────────┬────────────────────────────────────────┐ +│ Brand Name │ │ +│ Subtitle │ [router-view — page content] │ +├──────────────────────│ │ +│ ○ Overview │ │ +│ ○ Inventory │ │ +│ ○ Orders │ │ +│ ○ Finance │ │ +│ ○ Demand Forecast │ │ +│ ○ Reports │ │ +├──────────────────────│ │ +│ FILTERS │ │ +│ Time Period ▾ │ │ +│ Location ▾ │ │ +│ Category ▾ │ │ +│ Status ▾ │ │ +│ [ Reset ] │ │ +├──────────────────────│ │ +│ 🌐 English │ │ +│ [JD] Jane Doe │ │ +└──────────────────────┴────────────────────────────────────────┘ + 240px fixed, #0f172a flex:1, margin-left:240px +``` + +--- + +## Design Tokens (do not deviate) + +| Element | Value | +|---------|-------| +| Sidebar width | `240px` | +| Sidebar background | `#0f172a` | +| Sidebar position | `fixed; left:0; top:0; bottom:0; z-index:100; overflow-y:auto` | +| Logo zone height | `64px` | +| Active nav background | `#2563eb` | +| Nav link default color | `rgba(255,255,255,0.65)` | +| Nav link active color | `#ffffff` | +| Nav link hover background | `rgba(255,255,255,0.07)` | +| Dividers | `1px solid rgba(255,255,255,0.08)` | +| Filter select background | `rgba(255,255,255,0.08)` | +| Filter select border | `1px solid rgba(255,255,255,0.12)` | +| Filter select color | `rgba(255,255,255,0.85)` | +| Filter label color | `rgba(255,255,255,0.4)` | +| Main content margin | `margin-left:240px` | +| Main content padding | `padding:1.5rem 2rem` | + +--- + +## Step 1 — Read Current Files + +Before touching anything, read these four files: +- `client/src/App.vue` +- `client/src/components/FilterBar.vue` +- `client/src/components/LanguageSwitcher.vue` +- `client/src/components/ProfileMenu.vue` + +Note the exact structure of each — especially: +- The nav route paths and their `t()` translation keys in `App.vue` +- The event names emitted by `ProfileMenu.vue` (`show-profile-details`, `show-tasks`) +- The CSS class names for dropdowns in `LanguageSwitcher.vue` and `ProfileMenu.vue` +- The task management refs/methods in `App.vue` script (keep them all) + +--- + +## Step 2 — Create AppSidebar.vue (via vue-expert) + +Use the Agent tool with `subagent_type: "vue-expert"` to create `client/src/components/AppSidebar.vue`. + +Provide this full spec to vue-expert: + +--- +**File to create:** `client/src/components/AppSidebar.vue` + +**Purpose:** Fixed left sidebar containing logo, navigation, global filters, language switcher, and profile menu. Replaces the `.top-nav` header and wraps `FilterBar`, `LanguageSwitcher`, and `ProfileMenu`. + +**Imports needed:** +- `FilterBar` from `'./FilterBar.vue'` +- `LanguageSwitcher` from `'./LanguageSwitcher.vue'` +- `ProfileMenu` from `'./ProfileMenu.vue'` +- `useI18n` from `'../composables/useI18n'` +- `RouterLink` and `useRoute` from `'vue-router'` + +**Emits:** `['show-profile-details', 'show-tasks']` + +**Setup:** +```js +const { t } = useI18n() +const route = useRoute() +``` + +**Template structure:** +```html + +``` + +**Scoped styles:** +```css +.app-sidebar { + position: fixed; + left: 0; + top: 0; + bottom: 0; + width: 240px; + background: #0f172a; + z-index: 100; + display: flex; + flex-direction: column; + overflow-y: auto; +} + +.sidebar-logo { + height: 64px; + min-height: 64px; + padding: 0 1.25rem; + display: flex; + flex-direction: column; + justify-content: center; + border-bottom: 1px solid rgba(255, 255, 255, 0.08); +} + +.sidebar-brand { + font-size: 0.938rem; + font-weight: 700; + color: #ffffff; + letter-spacing: -0.02em; + line-height: 1.2; +} + +.sidebar-tagline { + font-size: 0.688rem; + color: rgba(255, 255, 255, 0.4); + margin-top: 0.125rem; + line-height: 1.3; +} + +.sidebar-nav { + padding: 0.75rem; + flex: 1; + display: flex; + flex-direction: column; + gap: 2px; +} + +.nav-link { + display: flex; + align-items: center; + gap: 0.625rem; + padding: 0.5rem 0.75rem; + border-radius: 6px; + color: rgba(255, 255, 255, 0.65); + font-size: 0.875rem; + font-weight: 500; + text-decoration: none; + transition: background 0.15s ease, color 0.15s ease; +} + +.nav-link:hover { + background: rgba(255, 255, 255, 0.07); + color: rgba(255, 255, 255, 0.9); +} + +.nav-link.active { + background: #2563eb; + color: #ffffff; +} + +.sidebar-filters { + padding: 0.75rem 0; + border-top: 1px solid rgba(255, 255, 255, 0.06); +} + +.sidebar-filters-label { + font-size: 0.688rem; + font-weight: 600; + color: rgba(255, 255, 255, 0.35); + text-transform: uppercase; + letter-spacing: 0.08em; + padding: 0 1.25rem; + margin-bottom: 0.5rem; +} + +.sidebar-bottom { + padding: 0.75rem; + border-top: 1px solid rgba(255, 255, 255, 0.08); + display: flex; + flex-direction: column; + gap: 0.375rem; +} + +/* Make language and profile buttons full-width and fit dark sidebar */ +.sidebar-bottom :deep(.language-button), +.sidebar-bottom :deep(.profile-button) { + width: 100%; + background: rgba(255, 255, 255, 0.06); + border-color: rgba(255, 255, 255, 0.12); + color: rgba(255, 255, 255, 0.8); +} + +.sidebar-bottom :deep(.language-button):hover, +.sidebar-bottom :deep(.profile-button):hover { + background: rgba(255, 255, 255, 0.1); + border-color: rgba(255, 255, 255, 0.2); + color: #ffffff; +} + +.sidebar-bottom :deep(.lang-name), +.sidebar-bottom :deep(.profile-name) { + color: rgba(255, 255, 255, 0.8); +} + +.sidebar-bottom :deep(.chevron-icon) { + color: rgba(255, 255, 255, 0.4); +} + +/* Open dropdowns upward and to the right to avoid sidebar clipping */ +.sidebar-bottom :deep(.dropdown-menu) { + bottom: calc(100% + 0.5rem); + top: auto; + left: 0; + right: auto; + min-width: 200px; +} +``` +--- + +## Step 3 — Modify App.vue (via vue-expert) + +Use the Agent tool with `subagent_type: "vue-expert"` to modify `client/src/App.vue`. + +Provide this full spec to vue-expert: + +--- +**File to modify:** `client/src/App.vue` + +**Template — replace the entire `