From f29c0f42b5f05a4fb28197cb3762589f80545844 Mon Sep 17 00:00:00 2001 From: AKHIL Date: Wed, 5 Aug 2026 02:16:42 +0530 Subject: [PATCH 1/5] refactor(ui): drop icons from app headers Remove the MyDevTools logo mark from the desktop top bar (wordmark only, now visible at every width) and the per-tool icon chips from ToolHeader and ToolPageHeader. The `icon`/`toolId` props stay accepted so the ~70 call sites are unchanged. Co-Authored-By: Claude Opus 5 (1M context) --- .../src/components/shell/top-bar.tsx | 7 ++---- .../src/components/tools/tool-header.tsx | 17 ++----------- .../src/components/tools/tool-page-header.tsx | 24 ++++++------------- 3 files changed, 11 insertions(+), 37 deletions(-) diff --git a/apps/desktop-ui/src/components/shell/top-bar.tsx b/apps/desktop-ui/src/components/shell/top-bar.tsx index 80589882..9bff8c3d 100644 --- a/apps/desktop-ui/src/components/shell/top-bar.tsx +++ b/apps/desktop-ui/src/components/shell/top-bar.tsx @@ -5,7 +5,6 @@ import Image from 'next/image' import Link from 'next/link' import { useRouter } from 'next/navigation' import { Settings, LogOut, User as UserIcon, HelpCircle, Moon, Grid2x2Plus } from 'lucide-react' -import { Logo } from '@/components/logo' import { ModeToggle } from '@/components/modeToggle' import { TooltipProvider } from '@/components/ui/tooltip' import { TopNavStrip, NavIcon } from '@/components/shell/top-nav-strip' @@ -80,15 +79,13 @@ export function TopBar() { !isTauri ? 'px-4' : isFullscreen ? 'pl-4 pr-6' : 'pl-[74px] pr-6', )} > - {/* Brand → dashboard. Icon (logo mark) + a larger wordmark, sized - independently so the wordmark can grow without the mark. */} + {/* Brand → dashboard. Wordmark only — no logo mark. */} diff --git a/apps/desktop/src-tauri/tauri.conf.json b/apps/desktop/src-tauri/tauri.conf.json index 3fd28789..cb30023e 100644 --- a/apps/desktop/src-tauri/tauri.conf.json +++ b/apps/desktop/src-tauri/tauri.conf.json @@ -20,7 +20,7 @@ "center": true, "titleBarStyle": "Overlay", "hiddenTitle": true, - "trafficLightPosition": { "x": 14, "y": 21 } + "trafficLightPosition": { "x": 14, "y": 27 } } ], "security": { From bcf78bec43e33462a911b461adf28ec5227d3759 Mon Sep 17 00:00:00 2001 From: AKHIL Date: Wed, 5 Aug 2026 02:55:14 +0530 Subject: [PATCH 3/5] docs(desktop-ui): spec the left rail shell Design for replacing the top bar with a left navigation rail: brand, Dashboard, a reorderable curated Apps section, Pinned, open tabs, and the profile menu, with a thin drag strip left at the window top for the macOS traffic lights and the command palette button. Co-Authored-By: Claude Opus 5 (1M context) --- .../2026-08-05-left-rail-shell-design.md | 192 ++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 docs/superpowers/specs/2026-08-05-left-rail-shell-design.md diff --git a/docs/superpowers/specs/2026-08-05-left-rail-shell-design.md b/docs/superpowers/specs/2026-08-05-left-rail-shell-design.md new file mode 100644 index 00000000..e14e2b86 --- /dev/null +++ b/docs/superpowers/specs/2026-08-05-left-rail-shell-design.md @@ -0,0 +1,192 @@ +# Left rail shell — design + +Date: 2026-08-05 +Scope: `apps/desktop-ui` +Status: approved, ready for implementation plan + +## Goal + +Replace the top bar with a left navigation rail. The rail carries the brand, Dashboard, +a curated **Apps** section, Pinned tools, open tool tabs, and the profile menu. A thin +drag strip remains at the very top of the window solely to host the macOS traffic lights +and the ⌘K button. + +## Current state + +- `components/sidebar/client-layout.tsx` renders `` then a single `
`. No + left panel is rendered at all. +- `components/shell/top-bar.tsx` (187 lines) — brand, ``, ⌘K `NavIcon`, + avatar dropdown (Profile / Settings / Help / Theme / Sign out), macOS traffic-light + inset + fullscreen detection. +- `components/shell/top-nav-strip.tsx` (427 lines) — Dashboard icon, hover-open Pinned + dropdown, horizontally scrolling open-tab chips with edge fades, ⌥1–9 / ⌥W keyboard + handling. Exports `NavIcon`, consumed by `top-bar.tsx`. +- `components/sidebar/app-sidebar.tsx` (87 lines) — orphaned. Uses the shadcn `Sidebar` + with `collapsible="icon" variant="floating"`, a Dashboard row and a Pinned `NavGroup`. + Nothing imports it. +- `components/sidebar/nav-user.tsx` (227 lines) — orphaned profile card. +- `SidebarProvider` is already mounted in `client-layout.tsx`, so the shadcn sidebar + context, ⌘B toggle and persisted collapse state exist and are unused. + +## Target layout + +``` +┌──────────┬────────────────────────────┐ +│ ●●● │ (drag) ⌘K │ h-9 TopStrip, full width +├──────────┼────────────────────────────┤ +│ mydevtools.tech │ +│ ⌂ Dashboard │ +│ │ +│ APPS ⚙ │ +│ ⚡ API Client • │ +│ ▤ Data Explorer │ +│ ✎ Notes • × │ +│ │ +│ PINNED │ +│ { } JSON Formatter │ +│ │ +│ OPEN │ +│ ⌗ Regex Tester × │ +│──────────│ │ +│ (A) akhil│ tool content │ +└──────────┴────────────────────────────┘ +``` + +Rail: 240px expanded, 48px icon-only collapsed (tooltips on hover), ⌘B toggle, collapse +state persisted by the existing shadcn sidebar cookie. Below the `md` breakpoint the rail +becomes the shadcn offcanvas Sheet; the existing `MobileNav` bottom bar is untouched. + +## Components + +### `components/shell/top-strip.tsx` (new) + +Replaces `top-bar.tsx`. `h-9`, `data-tauri-drag-region`, `border-b`, +`bg-[hsl(var(--surface-2))]`. + +Carried over verbatim from `top-bar.tsx`: + +- the `isTauri` / `isFullscreen` mounted-guarded state and the resulting left padding + (`px-4` on web, `pl-[74px]` in a non-fullscreen Tauri window, `pl-4` fullscreen); +- the `NavIcon` component itself, moved here from `top-nav-strip.tsx` (it is the only + surviving consumer); +- the ⌘K button dispatching `new CustomEvent('open-command-palette')`. + +Everything else in `top-bar.tsx` moves to the rail (brand, account dropdown) or is +deleted (`TopNavStrip`). + +### `hooks/use-tab-shortcuts.ts` (new) + +The ⌥1–9 / ⌥W `keydown` effect lifted out of `TopNavStrip`, unchanged in behaviour, +including the `e.code`-based (layout-independent) key matching and the input/textarea/ +contenteditable guard. Also exports the `closeTabAndNavigate(path)` callback that both +the shortcut handler and the rail's row `×` buttons use, so close-and-pick-next-tab logic +lives in exactly one place. Called once from `AppSidebar`. + +### `components/sidebar/app-sidebar.tsx` (rewrite) + +Keeps `Sidebar collapsible="icon" variant="floating"`. Sections top to bottom: + +1. **Brand row** — `mydevtools.tech` wordmark in Courier Prime, navigates to + `/dashboard`. Hidden when collapsed (the icon rail shows nothing in its place). +2. **Dashboard row** — the existing row with the framer-motion `layoutId="sidebar-active-pill"` + active indicator. +3. **APPS** — `NavGroup` rows in user order. `NavGroup` gains one optional prop, + `onReorder?: (paths: string[]) => void`; when supplied it wraps its rows in a + framer-motion `Reorder.Group` / `Reorder.Item` pair, and when omitted it renders exactly + as today (so Pinned and Open are unaffected). A `⚙` button in the section header opens a + `DropdownMenu` checklist of every default app to hide/show. Drag and the `⚙` menu are + disabled while the rail is collapsed. +4. **PINNED** — the existing `NavGroup` fed by `buildPinnedNavItems`, unchanged. The + empty-state block ("No pinned tools yet") is retained. +5. **OPEN** — a `NavGroup` listing open tabs whose path is in neither the visible Apps + list nor the Pinned list. Section is not rendered when empty. +6. **Footer** — `NavUser`. + +Row labels and icons resolve through the existing `getSidebarToolMeta` and +`getToolMessageKey` helpers, matching how the top strip resolves them today. + +### `components/sidebar/nav-group.tsx` (edit) + +The open-tab affordance is added once, inside the shared row renderer, so Apps, Pinned and +Open all inherit it: + +- subscribe to `useTabStore` and mark a row open when its path matches an open tab; +- open + not active → a 4px dot at the row's right edge; +- hovered (or active) and open → the dot is replaced by a `×` calling + `closeTabAndNavigate`; +- collapsed rail → dot only, no `×` (no room, and the tooltip already carries the label). + +A closed tool row behaves exactly as today. + +### `components/sidebar/nav-user.tsx` (edit) + +Currently an orphaned profile card. It absorbs the menu that dies with `top-bar.tsx`: +Profile, Settings, Help, the `ModeToggle` theme row, and Sign out (destructive styling), +plus the logged-out variant showing only Theme and Sign in. Data comes from the existing +`useAppUser` / `useSignOut` hooks. Displays avatar + name expanded, avatar only collapsed. + +### `components/sidebar/client-layout.tsx` (edit) + +`` → ``, and `` is rendered as the first child of the +existing `
` row, before `
`. The existing +`state === 'collapsed'` padding branch on `
` stays. + +### Deleted + +`components/shell/top-bar.tsx`, `components/shell/top-nav-strip.tsx`. + +## State + +New `store/app-rail-store.ts`, shaped after `store/pinned-tools-store.ts`: + +```ts +interface AppRailStore { + orderByWorkspace: Record // app paths, user order + hiddenByWorkspace: Record // app paths the user hid + setOrder: (workspaceId: string, paths: string[]) => void + toggleHidden: (workspaceId: string, path: string) => void +} +``` + +zustand `persist`, key `app-rail-storage`, version 1, localStorage only. Deliberately **not** +synced to the backend: pinned tools are a server-owned preference, but rail order is local +window chrome. + +A selector resolves the visible list: start from `DEFAULT_APPS`, order by the stored array, +append any default app missing from it (so apps shipped in a later release show up at the +bottom instead of vanishing), drop the hidden ones, drop paths no longer in `DEFAULT_APPS`. + +`DEFAULT_APPS` — the eleven heavyweight tools that have real routes: + +``` +/app/api-client /app/data-explorer /app/sql-client +/app/s3-drive /app/redis-commander /app/notes +/app/bookmarks /app/snippet-manager /app/to-do +/app/password-manager /app/environment-manager +``` + +`api-key-vault` is excluded — it is a component, not a route. + +## i18n + +New `Navigation` keys — `apps`, `open`, `manageApps` — plus `dashboard` and `pinned`, which +the dying top strip hardcoded in English. Added to `messages/en.json` and all 26 other +locales. No ICU plurals involved, so no per-locale plural-category work. + +## Testing + +- `store/__tests__/app-rail-store.test.ts` — reorder persists; hide removes a row from the + visible list; a `DEFAULT_APPS` entry absent from a stored order appears at the end; a + stored path no longer in `DEFAULT_APPS` is dropped. +- `components/sidebar/__tests__/app-sidebar-rbac.test.tsx` — existing suite, updated for + the new rail structure. +- Manual: `pnpm dev:tauri` — traffic lights draggable and not overlapped, ⌘B collapse, + ⌥1–9 / ⌥W still switch and close tabs, close `×` on a row picks the neighbouring tab. + +## Out of scope + +- Drag-resizable rail width (collapse to icons only). +- Backend sync of app order or hidden apps. +- Mobile redesign — the rail uses the shadcn offcanvas Sheet below `md` and `MobileNav` + stays as is. +- Any change to tool pages, `NavBar`, or `TabContent`. From f3e48e46c44f414c62756d9561f81234ced81123 Mon Sep 17 00:00:00 2001 From: AKHIL Date: Wed, 5 Aug 2026 02:57:23 +0530 Subject: [PATCH 4/5] Update top-bar.tsx --- apps/desktop-ui/src/components/shell/top-bar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/desktop-ui/src/components/shell/top-bar.tsx b/apps/desktop-ui/src/components/shell/top-bar.tsx index 8bec553f..97c5cb6d 100644 --- a/apps/desktop-ui/src/components/shell/top-bar.tsx +++ b/apps/desktop-ui/src/components/shell/top-bar.tsx @@ -88,7 +88,7 @@ export function TopBar() { className="text-[15px] font-bold leading-none tracking-wide" style={{ fontFamily: 'var(--font-courier-prime), ui-monospace, monospace' }} > - mydevtools.tech + mydevtools.tech From 30ee4ef371270ebdd1d2e04898a6637c5783626f Mon Sep 17 00:00:00 2001 From: AKHIL Date: Wed, 5 Aug 2026 03:00:51 +0530 Subject: [PATCH 5/5] Update top-bar.tsx --- apps/desktop-ui/src/components/shell/top-bar.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/desktop-ui/src/components/shell/top-bar.tsx b/apps/desktop-ui/src/components/shell/top-bar.tsx index 97c5cb6d..10681aeb 100644 --- a/apps/desktop-ui/src/components/shell/top-bar.tsx +++ b/apps/desktop-ui/src/components/shell/top-bar.tsx @@ -75,8 +75,9 @@ export function TopBar() { data-tauri-drag-region className={cn( 'flex h-14 w-full shrink-0 items-center gap-3 border-b border-border bg-[hsl(var(--surface-2))]', - !isTauri ? 'px-4' : isFullscreen ? 'pl-4 pr-6' : 'pl-[74px] pr-6', + !isTauri ? 'px-4' : 'pr-6', )} + style={isTauri ? { paddingLeft: isFullscreen ? 16 : 92 } : undefined} > {/* Brand → dashboard. Text wordmark in Courier Prime, no logo mark. */}