mirror of
https://github.com/NanmiCoder/claude-code-haha.git
synced 2026-10-10 20:03:13 +08:00
8eba29bdd4
Three things about the left column, all reported from the same screenshot. The brand mark beside the wordmark was clutter. Expanded, the sidebar already says "Claude Code Haha" in the headline face, and the 32px seal next to it repeats what the words carry. Removing it outright emptied the header on the 72px rail, though — the copy there is width-clamped to zero by `.sidebar-copy--hidden`, so nothing was left to identify the app. The mark now renders only when collapsed, at `sm`: two C's and the seal bar, without the cursor arrow that reads as a stray orange wedge at that size. BrandSeal already sheds parts as it shrinks, so this is the size ladder doing its job rather than a new variant. The settings rail was 260px for a column whose longest label is two words. It is now 220px. 200px was the first choice and it was wrong: measured in a real browser against the live stylesheet, the Japanese "コンピューター操作" needs 122px of text box and 200px leaves 115px, so it truncated. The threshold sits at 210px; 220px keeps ten pixels of headroom over the worst locale. The sidebar itself is now resizable. An 8px handle on its right edge drives the width between 240 and 480px, persisted to localStorage, with a double click back to 300 and arrow-key steps for the keyboard. Dragging left past 240 pins there until the pointer crosses 180, which collapses to the rail; coming back out past 200 re-opens it. The 20px gap between those two thresholds is hysteresis — with one boundary the sidebar flickers open and closed on any tremor of the hand. A drag that ends in a collapse deliberately does not commit its width, so re-opening from the toggle restores the size the user chose rather than whatever value the pointer happened to sweep through. The live width travels as a CSS variable written imperatively onto the shell, never through React state. Sidebar re-renders during a streaming turn would otherwise land between drag frames and fight the pointer, which is the failure that made the pet animation stutter. The store is written once, when the drag settles. That variable exposed a bug the unit tests could not see. `#sidebar-shell` sits behind AppShell's startup gate, so it mounts a render later than the hook. With a plain object ref, `shellRef.current` is still null on the single pass the width effect ever runs, and because neither dependency changes afterwards the effect never fires again — the remembered width never reaches the DOM and every launch silently falls back to the stylesheet's 300px. Only visible by loading the real app: the harness in a test mounts the shell and the hook together. Fixed with a callback ref, and `useSidebarResize.test.tsx` now models the gate; that case was confirmed to fail against the object-ref version. Verified in a browser against the dev server: drag 300→420 persists as "420", crossing 150 settles the shell at the 72px rail while localStorage still holds the chosen width, and the truncation thresholds above were measured by substituting each locale's longest label into a live tab.
Claude Code Haha Desktop
基于 Tauri 2 + React 的桌面客户端。
开发
bun install
bun run tauri dev
构建
# macOS (Apple Silicon)
./scripts/build-macos-arm64.sh
# Windows (x64, MSI only)
.\scripts\build-windows-x64.ps1
构建产物位于 build-artifacts/ 目录,文件名会显式包含平台、架构和包类型。
常见问题
macOS 提示"已损坏,无法打开"
xattr -cr /Applications/Claude\ Code\ Haha.app