diff --git a/README.en.md b/README.en.md index 8f586fa1..12febf01 100644 --- a/README.en.md +++ b/README.en.md @@ -1,7 +1,10 @@ # Claude Code Haha

- Claude Code Haha + + + Claude Code Haha +

diff --git a/README.md b/README.md index 8940170c..c51a6387 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,10 @@ # Claude Code Haha

- Claude Code Haha + + + Claude Code Haha +

diff --git a/desktop/docs/redesign-paper-ink-seal.md b/desktop/docs/redesign-paper-ink-seal.md index 5c632137..8d8e094e 100644 --- a/desktop/docs/redesign-paper-ink-seal.md +++ b/desktop/docs/redesign-paper-ink-seal.md @@ -60,7 +60,7 @@ - `Button` — `primary` 已是墨色实心 + hover 转陶土 + 上浮 1px + `active:scale(.97)`;禁用态是不透明的 `--s1`/`--t3`。 - `Card` — 新增 `shadow`(`none`/`card`/`composer`)与 `lift`(hover 抬起 2px)两个 prop,以及 `radius="2xl"`。**`lift` 与 `shadow` 不要同时传**,两个 `shadow-[…]` 不会叠加。 - `IconButton` / `Badge` / `Modal`(圆角已是 24)/ `SegmentedControl` / `Switch` / `Progress` — 都已走 token,跟随主题。 -- `composite/BrandSeal` — 印章「哈」,`sm`24 / `md`32 / `lg`38 / `xl`80。 +- `composite/BrandSeal` — 品牌标记 cc-haha(原 app-icon 的矢量重建),`sm`24 / `md`32 / `lg`38 / `xl`80,随尺寸减件(星芒只在 `xl`,光标到 `sm` 去掉)。 焦点态统一:`focus-visible:ring-2 focus-visible:ring-[var(--color-border-focus)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--color-surface)]`。 diff --git a/desktop/public/app-icon.png b/desktop/public/app-icon.png index b17c5527..c856de8e 100644 Binary files a/desktop/public/app-icon.png and b/desktop/public/app-icon.png differ diff --git a/desktop/public/app-icon.svg b/desktop/public/app-icon.svg index 05a6e427..d9cc7265 100644 --- a/desktop/public/app-icon.svg +++ b/desktop/public/app-icon.svg @@ -1,3 +1,10 @@ - - + + + + + + + + + diff --git a/desktop/src-tauri/app-icon-macos.svg b/desktop/src-tauri/app-icon-macos.svg index 05a6e427..d9cc7265 100644 --- a/desktop/src-tauri/app-icon-macos.svg +++ b/desktop/src-tauri/app-icon-macos.svg @@ -1,3 +1,10 @@ - - + + + + + + + + + diff --git a/desktop/src-tauri/app-icon.svg b/desktop/src-tauri/app-icon.svg index 05a6e427..d9cc7265 100644 --- a/desktop/src-tauri/app-icon.svg +++ b/desktop/src-tauri/app-icon.svg @@ -1,3 +1,10 @@ - - + + + + + + + + + diff --git a/desktop/src-tauri/icons/128x128.png b/desktop/src-tauri/icons/128x128.png index 5fb1518c..8ac8da5b 100644 Binary files a/desktop/src-tauri/icons/128x128.png and b/desktop/src-tauri/icons/128x128.png differ diff --git a/desktop/src-tauri/icons/128x128@2x.png b/desktop/src-tauri/icons/128x128@2x.png index d6333c1e..6c19fa38 100644 Binary files a/desktop/src-tauri/icons/128x128@2x.png and b/desktop/src-tauri/icons/128x128@2x.png differ diff --git a/desktop/src-tauri/icons/32x32.png b/desktop/src-tauri/icons/32x32.png index 753fd1e8..b83417fa 100644 Binary files a/desktop/src-tauri/icons/32x32.png and b/desktop/src-tauri/icons/32x32.png differ diff --git a/desktop/src-tauri/icons/64x64.png b/desktop/src-tauri/icons/64x64.png index dd7b5d98..2afd34c6 100644 Binary files a/desktop/src-tauri/icons/64x64.png and b/desktop/src-tauri/icons/64x64.png differ diff --git a/desktop/src-tauri/icons/Square107x107Logo.png b/desktop/src-tauri/icons/Square107x107Logo.png index 85c4870c..14aee330 100644 Binary files a/desktop/src-tauri/icons/Square107x107Logo.png and b/desktop/src-tauri/icons/Square107x107Logo.png differ diff --git a/desktop/src-tauri/icons/Square142x142Logo.png b/desktop/src-tauri/icons/Square142x142Logo.png index 598ce77e..f952dec5 100644 Binary files a/desktop/src-tauri/icons/Square142x142Logo.png and b/desktop/src-tauri/icons/Square142x142Logo.png differ diff --git a/desktop/src-tauri/icons/Square150x150Logo.png b/desktop/src-tauri/icons/Square150x150Logo.png index a05518ac..6ccf4b5f 100644 Binary files a/desktop/src-tauri/icons/Square150x150Logo.png and b/desktop/src-tauri/icons/Square150x150Logo.png differ diff --git a/desktop/src-tauri/icons/Square284x284Logo.png b/desktop/src-tauri/icons/Square284x284Logo.png index 2bda1a90..e6ccc393 100644 Binary files a/desktop/src-tauri/icons/Square284x284Logo.png and b/desktop/src-tauri/icons/Square284x284Logo.png differ diff --git a/desktop/src-tauri/icons/Square30x30Logo.png b/desktop/src-tauri/icons/Square30x30Logo.png index e6bf07e0..f769df23 100644 Binary files a/desktop/src-tauri/icons/Square30x30Logo.png and b/desktop/src-tauri/icons/Square30x30Logo.png differ diff --git a/desktop/src-tauri/icons/Square310x310Logo.png b/desktop/src-tauri/icons/Square310x310Logo.png index 572bd6b6..cc55cfa3 100644 Binary files a/desktop/src-tauri/icons/Square310x310Logo.png and b/desktop/src-tauri/icons/Square310x310Logo.png differ diff --git a/desktop/src-tauri/icons/Square44x44Logo.png b/desktop/src-tauri/icons/Square44x44Logo.png index d1cd2b82..7cdc4446 100644 Binary files a/desktop/src-tauri/icons/Square44x44Logo.png and b/desktop/src-tauri/icons/Square44x44Logo.png differ diff --git a/desktop/src-tauri/icons/Square71x71Logo.png b/desktop/src-tauri/icons/Square71x71Logo.png index 67017216..8e4155fb 100644 Binary files a/desktop/src-tauri/icons/Square71x71Logo.png and b/desktop/src-tauri/icons/Square71x71Logo.png differ diff --git a/desktop/src-tauri/icons/Square89x89Logo.png b/desktop/src-tauri/icons/Square89x89Logo.png index ecd51ce1..b7c6fdb0 100644 Binary files a/desktop/src-tauri/icons/Square89x89Logo.png and b/desktop/src-tauri/icons/Square89x89Logo.png differ diff --git a/desktop/src-tauri/icons/StoreLogo.png b/desktop/src-tauri/icons/StoreLogo.png index ee54452d..676cd6b4 100644 Binary files a/desktop/src-tauri/icons/StoreLogo.png and b/desktop/src-tauri/icons/StoreLogo.png differ diff --git a/desktop/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png b/desktop/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png index 95b25ea5..0881616d 100644 Binary files a/desktop/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png and b/desktop/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png differ diff --git a/desktop/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png b/desktop/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png index a12b8518..765cbffa 100644 Binary files a/desktop/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png and b/desktop/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png differ diff --git a/desktop/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png b/desktop/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png index 481e6e2c..0881616d 100644 Binary files a/desktop/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png and b/desktop/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png differ diff --git a/desktop/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png b/desktop/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png index 2532a07c..97ae06a6 100644 Binary files a/desktop/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png and b/desktop/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png differ diff --git a/desktop/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png b/desktop/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png index 70a4823e..7c32306c 100644 Binary files a/desktop/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png and b/desktop/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png differ diff --git a/desktop/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png b/desktop/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png index 6654096f..97ae06a6 100644 Binary files a/desktop/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png and b/desktop/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png differ diff --git a/desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png b/desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png index c95ccba2..fd38ac5b 100644 Binary files a/desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png and b/desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png differ diff --git a/desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png b/desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png index 4e638bd5..b2971c7d 100644 Binary files a/desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png and b/desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png differ diff --git a/desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png b/desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png index d199c6a7..fd38ac5b 100644 Binary files a/desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png and b/desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png b/desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png index bf48c1f9..5f5c14a0 100644 Binary files a/desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png and b/desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png differ diff --git a/desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png b/desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png index 25aaf82d..b674f090 100644 Binary files a/desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png and b/desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png differ diff --git a/desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png b/desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png index 0607fe93..5f5c14a0 100644 Binary files a/desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png and b/desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png b/desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png index 6410bbce..baa42baa 100644 Binary files a/desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png and b/desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png b/desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png index b7824dd9..8fb34d96 100644 Binary files a/desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png and b/desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png differ diff --git a/desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png b/desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png index 103041e5..baa42baa 100644 Binary files a/desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png and b/desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/desktop/src-tauri/icons/icon.icns b/desktop/src-tauri/icons/icon.icns index 49712d21..11e47b2c 100644 Binary files a/desktop/src-tauri/icons/icon.icns and b/desktop/src-tauri/icons/icon.icns differ diff --git a/desktop/src-tauri/icons/icon.ico b/desktop/src-tauri/icons/icon.ico index afa55693..58038b86 100644 Binary files a/desktop/src-tauri/icons/icon.ico and b/desktop/src-tauri/icons/icon.ico differ diff --git a/desktop/src-tauri/icons/icon.png b/desktop/src-tauri/icons/icon.png index 55f095da..6bcaed6d 100644 Binary files a/desktop/src-tauri/icons/icon.png and b/desktop/src-tauri/icons/icon.png differ diff --git a/desktop/src-tauri/icons/ios/AppIcon-20x20@1x.png b/desktop/src-tauri/icons/ios/AppIcon-20x20@1x.png index 708c0c2e..485975ef 100644 Binary files a/desktop/src-tauri/icons/ios/AppIcon-20x20@1x.png and b/desktop/src-tauri/icons/ios/AppIcon-20x20@1x.png differ diff --git a/desktop/src-tauri/icons/ios/AppIcon-20x20@2x-1.png b/desktop/src-tauri/icons/ios/AppIcon-20x20@2x-1.png index 637b6e4c..3f72d2cc 100644 Binary files a/desktop/src-tauri/icons/ios/AppIcon-20x20@2x-1.png and b/desktop/src-tauri/icons/ios/AppIcon-20x20@2x-1.png differ diff --git a/desktop/src-tauri/icons/ios/AppIcon-20x20@2x.png b/desktop/src-tauri/icons/ios/AppIcon-20x20@2x.png index 637b6e4c..3f72d2cc 100644 Binary files a/desktop/src-tauri/icons/ios/AppIcon-20x20@2x.png and b/desktop/src-tauri/icons/ios/AppIcon-20x20@2x.png differ diff --git a/desktop/src-tauri/icons/ios/AppIcon-20x20@3x.png b/desktop/src-tauri/icons/ios/AppIcon-20x20@3x.png index fdf73148..3f2590cc 100644 Binary files a/desktop/src-tauri/icons/ios/AppIcon-20x20@3x.png and b/desktop/src-tauri/icons/ios/AppIcon-20x20@3x.png differ diff --git a/desktop/src-tauri/icons/ios/AppIcon-29x29@1x.png b/desktop/src-tauri/icons/ios/AppIcon-29x29@1x.png index 83a6000a..825f2a0d 100644 Binary files a/desktop/src-tauri/icons/ios/AppIcon-29x29@1x.png and b/desktop/src-tauri/icons/ios/AppIcon-29x29@1x.png differ diff --git a/desktop/src-tauri/icons/ios/AppIcon-29x29@2x-1.png b/desktop/src-tauri/icons/ios/AppIcon-29x29@2x-1.png index 39cdcf5e..5ae6cb67 100644 Binary files a/desktop/src-tauri/icons/ios/AppIcon-29x29@2x-1.png and b/desktop/src-tauri/icons/ios/AppIcon-29x29@2x-1.png differ diff --git a/desktop/src-tauri/icons/ios/AppIcon-29x29@2x.png b/desktop/src-tauri/icons/ios/AppIcon-29x29@2x.png index 39cdcf5e..5ae6cb67 100644 Binary files a/desktop/src-tauri/icons/ios/AppIcon-29x29@2x.png and b/desktop/src-tauri/icons/ios/AppIcon-29x29@2x.png differ diff --git a/desktop/src-tauri/icons/ios/AppIcon-29x29@3x.png b/desktop/src-tauri/icons/ios/AppIcon-29x29@3x.png index fb6e3b12..e86e66cb 100644 Binary files a/desktop/src-tauri/icons/ios/AppIcon-29x29@3x.png and b/desktop/src-tauri/icons/ios/AppIcon-29x29@3x.png differ diff --git a/desktop/src-tauri/icons/ios/AppIcon-40x40@1x.png b/desktop/src-tauri/icons/ios/AppIcon-40x40@1x.png index 637b6e4c..3f72d2cc 100644 Binary files a/desktop/src-tauri/icons/ios/AppIcon-40x40@1x.png and b/desktop/src-tauri/icons/ios/AppIcon-40x40@1x.png differ diff --git a/desktop/src-tauri/icons/ios/AppIcon-40x40@2x-1.png b/desktop/src-tauri/icons/ios/AppIcon-40x40@2x-1.png index 1a542695..ff28a4bf 100644 Binary files a/desktop/src-tauri/icons/ios/AppIcon-40x40@2x-1.png and b/desktop/src-tauri/icons/ios/AppIcon-40x40@2x-1.png differ diff --git a/desktop/src-tauri/icons/ios/AppIcon-40x40@2x.png b/desktop/src-tauri/icons/ios/AppIcon-40x40@2x.png index 1a542695..ff28a4bf 100644 Binary files a/desktop/src-tauri/icons/ios/AppIcon-40x40@2x.png and b/desktop/src-tauri/icons/ios/AppIcon-40x40@2x.png differ diff --git a/desktop/src-tauri/icons/ios/AppIcon-40x40@3x.png b/desktop/src-tauri/icons/ios/AppIcon-40x40@3x.png index 5914b982..c346e90c 100644 Binary files a/desktop/src-tauri/icons/ios/AppIcon-40x40@3x.png and b/desktop/src-tauri/icons/ios/AppIcon-40x40@3x.png differ diff --git a/desktop/src-tauri/icons/ios/AppIcon-512@2x.png b/desktop/src-tauri/icons/ios/AppIcon-512@2x.png index 048843b4..c856de8e 100644 Binary files a/desktop/src-tauri/icons/ios/AppIcon-512@2x.png and b/desktop/src-tauri/icons/ios/AppIcon-512@2x.png differ diff --git a/desktop/src-tauri/icons/ios/AppIcon-60x60@2x.png b/desktop/src-tauri/icons/ios/AppIcon-60x60@2x.png index 5914b982..c346e90c 100644 Binary files a/desktop/src-tauri/icons/ios/AppIcon-60x60@2x.png and b/desktop/src-tauri/icons/ios/AppIcon-60x60@2x.png differ diff --git a/desktop/src-tauri/icons/ios/AppIcon-60x60@3x.png b/desktop/src-tauri/icons/ios/AppIcon-60x60@3x.png index 816efd25..2d0bb188 100644 Binary files a/desktop/src-tauri/icons/ios/AppIcon-60x60@3x.png and b/desktop/src-tauri/icons/ios/AppIcon-60x60@3x.png differ diff --git a/desktop/src-tauri/icons/ios/AppIcon-76x76@1x.png b/desktop/src-tauri/icons/ios/AppIcon-76x76@1x.png index 1ae4ef19..0a2a3a82 100644 Binary files a/desktop/src-tauri/icons/ios/AppIcon-76x76@1x.png and b/desktop/src-tauri/icons/ios/AppIcon-76x76@1x.png differ diff --git a/desktop/src-tauri/icons/ios/AppIcon-76x76@2x.png b/desktop/src-tauri/icons/ios/AppIcon-76x76@2x.png index 609b8e36..ee335c46 100644 Binary files a/desktop/src-tauri/icons/ios/AppIcon-76x76@2x.png and b/desktop/src-tauri/icons/ios/AppIcon-76x76@2x.png differ diff --git a/desktop/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png b/desktop/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png index 5a1c345c..f494869b 100644 Binary files a/desktop/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png and b/desktop/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png differ diff --git a/desktop/src/components/AGENTS.md b/desktop/src/components/AGENTS.md index 7f9573c9..3a732b9b 100644 --- a/desktop/src/components/AGENTS.md +++ b/desktop/src/components/AGENTS.md @@ -41,7 +41,7 @@ | 复制按钮 | `CopyButton` | `ui/CopyButton.tsx` | | 目录选择 | `DirectoryPicker` | `composite/DirectoryPicker.tsx` | | 「用 X 打开」菜单 | `OpenWithMenu` | `composite/OpenWithMenu.tsx` | -| 品牌印章「哈」 | `BrandSeal` | `composite/BrandSeal.tsx` | +| 品牌标记 cc-haha | `BrandSeal` | `composite/BrandSeal.tsx` | ### 两个 hook diff --git a/desktop/src/components/composite/BrandSeal.test.tsx b/desktop/src/components/composite/BrandSeal.test.tsx index 24f7b1a9..eb025d6c 100644 --- a/desktop/src/components/composite/BrandSeal.test.tsx +++ b/desktop/src/components/composite/BrandSeal.test.tsx @@ -4,40 +4,65 @@ import { describe, expect, it } from 'vitest' import { BrandSeal } from './BrandSeal' +const SIZES = ['sm', 'md', 'lg', 'xl'] as const + describe('BrandSeal', () => { it('is decorative and hidden from assistive tech', () => { - // The product name always sits beside the seal (sidebar) or under it - // (empty state); announcing the glyph as well reads the brand twice. + // The product name always sits beside the mark (sidebar) or under it + // (empty state); announcing the brand again reads it twice. const { container } = render() expect(container.firstElementChild).toHaveAttribute('aria-hidden', 'true') }) - it('renders the 哈 glyph in the headline serif at every size', () => { - for (const size of ['sm', 'md', 'lg', 'xl'] as const) { + it('draws the two C strokes at every size', () => { + // Whatever else is shed, the double C is the mark. If this count drops the + // remaining shape is no longer recognizable as the logo. + for (const size of SIZES) { const { container, unmount } = render() - const glyph = container.querySelector('span span:last-child') as HTMLElement - expect(glyph.textContent).toBe('哈') - expect(glyph.style.fontFamily).toContain('var(--font-headline)') + const strokes = container.querySelectorAll('g[stroke="var(--color-text-primary)"] path') + expect(strokes).toHaveLength(3) // big C + the second C's two arcs unmount() } }) - it('fills with the brand token so all six palettes recolor it', () => { - // This is why the seal replaced the raster app icon: a bitmap kept its own - // colors under every theme while the chrome around it moved. - const { container } = render() - expect(container.firstElementChild?.className).toContain('bg-[var(--color-brand)]') + it('paints from tokens so all six palettes recolor it', () => { + // This is why the vector replaced the raster app icon: a bitmap kept its + // own blue and orange under every theme while the chrome around it moved. + const { container } = render() + const svg = container.firstElementChild! + expect(svg.querySelector('[stroke="var(--color-text-primary)"]')).not.toBeNull() + expect(svg.querySelector('[stroke="var(--color-brand)"]')).not.toBeNull() + expect(svg.querySelector('[fill="var(--color-brand)"]')).not.toBeNull() + // No literal hex anywhere — that would survive a theme switch unchanged. + expect(svg.innerHTML).not.toMatch(/#[0-9a-f]{3,8}\b/i) }) - it('engraves the inner rule only at the empty-state size', () => { - // At 38px and below the 1.5px inset ring closes up into a smudge; the - // handoff only draws it on the 80px seal. - const { container: xl } = render() - expect(xl.querySelector('.border-\\[1\\.5px\\]')).not.toBeNull() - - for (const size of ['sm', 'md', 'lg'] as const) { + it('sheds parts as it shrinks instead of turning to mush', () => { + // At 38px a sparkle is under 2px across and reads as dirt; at 24px the + // cursor merges into the second C. + const count = (size: (typeof SIZES)[number]) => { const { container, unmount } = render() - expect(container.querySelector('.border-\\[1\\.5px\\]')).toBeNull() + const filled = container.querySelectorAll('path[fill="var(--color-brand)"]').length + unmount() + return filled + } + expect(count('xl')).toBe(3) // cursor + two sparkles + expect(count('lg')).toBe(1) // cursor only + expect(count('md')).toBe(1) + expect(count('sm')).toBe(0) // the C's and the bar + }) + + it('crops the viewBox to the ink so the mark fills its box', () => { + // A full 0 0 1024 1024 viewBox would letterbox the mark to roughly half + // the height of its container at every size. + for (const size of SIZES) { + const { container, unmount } = render() + const viewBox = container.firstElementChild!.getAttribute('viewBox')! + const [x, y, w, h] = viewBox.split(' ').map(Number) + expect(x).toBeGreaterThan(200) + expect(y).toBeGreaterThan(200) + expect(w).toBeLessThan(1024) + expect(h).toBeLessThan(1024) unmount() } }) diff --git a/desktop/src/components/composite/BrandSeal.tsx b/desktop/src/components/composite/BrandSeal.tsx index bd7ec901..2b7dfadb 100644 --- a/desktop/src/components/composite/BrandSeal.tsx +++ b/desktop/src/components/composite/BrandSeal.tsx @@ -1,38 +1,58 @@ import { cx } from '@/lib/cx' /** - * The 「哈」 seal — the "印" of 「纸 · 墨 · 印」. + * The cc-haha mark — the double C of "Claude Code" with one stroke of 朱 on it. * - * A terracotta rounded square holding one serif glyph. It replaces the raster - * app icon inside the app chrome: the icon is a fixed bitmap, so it kept its - * own colors under all six palettes while everything around it moved, and it - * had no size below 32px that stayed legible. + * Geometry is a vector rebuild of the original `app-icon.png`, measured off the + * bitmap pixel by pixel (arc centers, radii, stroke widths and opening angles + * were fitted, then rounded to symmetric values). Two things the raster could + * not do: * - * The glyph is Chinese, and only the latin cut of Noto Serif SC is - * self-hosted, so it renders in the platform serif named by `--font-headline` - * (Songti SC on macOS, Source Han Serif / SimSun elsewhere). That is the same - * fallback the handoff prototype relies on. + * 1. Recolor. The PNG carried its own blue/cyan/orange under all six palettes + * while everything around it moved. Here the C's take `--color-text-primary` + * and the accents take `--color-brand`, so every theme repaints the mark. + * 2. Shrink. Four ideas — the two C's, the bar, the cursor and two sparkles — + * collapse into noise below 24px. So the mark sheds parts as it gets + * smaller (see `SIZES`) instead of turning to mush. */ export type BrandSealSize = 'sm' | 'md' | 'lg' | 'xl' +/** Which elements survive at each size. */ +type MarkParts = 'ccbar' | 'nostars' | 'full' + /** - * The three sizes the handoff calls for — sidebar 32, collapsed rail 38, empty - * state 80 — plus a 24px one for dense chrome. The inner rule only appears at - * `xl`: at 38px and below it closes up into a smudge. + * The sizes the layout calls for — sidebar 32, collapsed rail 38, empty state + * 80 — plus a 24px one for dense chrome. + * + * `viewBox` is cropped to the ink bounds of that part set (measured from a + * render, not guessed) so the mark fills its box at every size; `w` follows + * from the crop's aspect ratio, which is why the boxes are not square. + * + * The sparkles only appear at `xl`: at 38px they are under 2px across and read + * as dirt. The cursor goes at `sm` for the same reason. */ -const SIZES: Record = { - sm: { box: 'h-6 w-6', radius: 'rounded-[7px]', glyph: 'text-[12px]', shadow: 'shadow-[0_1px_2px_rgba(64,30,12,0.28)]', rule: false }, - md: { box: 'h-8 w-8', radius: 'rounded-[9px]', glyph: 'text-[16px]', shadow: 'shadow-[0_1px_3px_rgba(64,30,12,0.3)]', rule: false }, - lg: { box: 'h-[38px] w-[38px]', radius: 'rounded-[11px]', glyph: 'text-[18px]', shadow: 'shadow-[0_1px_3px_rgba(64,30,12,0.3)]', rule: false }, - xl: { box: 'h-20 w-20', radius: 'rounded-[22px]', glyph: 'text-[42px]', shadow: 'shadow-[0_10px_28px_rgba(100,45,20,0.3)]', rule: true }, +const SIZES: Record = { + sm: { box: 'h-6 w-[31px]', viewBox: '252 403 415 326', parts: 'ccbar' }, + md: { box: 'h-8 w-[41px]', viewBox: '252 381 444 348', parts: 'nostars' }, + lg: { box: 'h-[38px] w-[48px]', viewBox: '252 381 444 348', parts: 'nostars' }, + xl: { box: 'h-20 w-[98px]', viewBox: '252 306 519 423', parts: 'full' }, } +const INK = 'var(--color-text-primary)' +const SEAL = 'var(--color-brand)' + +/** Big C: open 160°, symmetric about the horizontal axis. */ +const BIG_C = 'M437.75 695.01A131 131 0 1 1 437.75 436.99' +/** Second C, cut into two arcs of 68° each. */ +const SMALL_C_UPPER = 'M505.06 535.98A117 117 0 0 1 610.92 459.07' +const SMALL_C_LOWER = 'M635.32 691.22A117 117 0 0 1 515.78 638.00' +/** The bar that runs through the second C's gap. */ +const BAR = 'M441.5 576H517.5' +/** Cursor arrow: tip up-right, two tails and a notch. */ +const CURSOR = 'M683.79 384.80Q698.00 380.00 692.43 393.93L665.57 461.07Q660.00 475.00 655.71 460.63L645.00 424.71Q643.00 418.00 636.59 415.18L629.25 411.95Q618.00 407.00 631.26 402.52L683.79 384.80Z' +const SPARKLE_LG = 'M717.00 308.00Q724.07 325.43 741.50 332.50Q724.07 339.57 717.00 357.00Q709.93 339.57 692.50 332.50Q709.93 325.43 717.00 308.00Z' +const SPARKLE_SM = 'M755.50 365.00Q759.04 374.96 769.00 378.50Q759.04 382.04 755.50 392.00Q751.96 382.04 742.00 378.50Q751.96 374.96 755.50 365.00Z' + export type BrandSealProps = { size?: BrandSealSize className?: string @@ -42,27 +62,27 @@ export function BrandSeal({ size = 'md', className }: BrandSealProps) { const spec = SIZES[size] return ( -
-
+
diff --git a/desktop/src/pages/Settings.tsx b/desktop/src/pages/Settings.tsx index 44053bfa..7713e650 100644 --- a/desktop/src/pages/Settings.tsx +++ b/desktop/src/pages/Settings.tsx @@ -76,6 +76,7 @@ import { formatBytes } from '../lib/formatBytes' import { isDesktopRuntime } from '../lib/desktopRuntime' import { getDesktopHost } from '../lib/desktopHost' import { publicAssetPath } from '../lib/publicAsset' +import { BrandSeal } from '../components/composite/BrandSeal' import { isBrowserSafePort } from '../lib/browserSafePort' import { getDesktopNotificationPermission, @@ -4141,7 +4142,7 @@ function AboutSettings() { return (
{/* Logo + App Name + Version */} - Claude Code Haha +

Claude Code Haha

{version && (
diff --git a/docs/images/app-icon-dark.png b/docs/images/app-icon-dark.png index b17c5527..07bedebd 100644 Binary files a/docs/images/app-icon-dark.png and b/docs/images/app-icon-dark.png differ diff --git a/docs/images/app-icon-dark.svg b/docs/images/app-icon-dark.svg index 05a6e427..34ccf8cf 100644 --- a/docs/images/app-icon-dark.svg +++ b/docs/images/app-icon-dark.svg @@ -1,3 +1,10 @@ - - + + + + + + + + + diff --git a/docs/images/app-icon-light.png b/docs/images/app-icon-light.png index b17c5527..c856de8e 100644 Binary files a/docs/images/app-icon-light.png and b/docs/images/app-icon-light.png differ diff --git a/docs/images/app-icon-light.svg b/docs/images/app-icon-light.svg index 05a6e427..d9cc7265 100644 --- a/docs/images/app-icon-light.svg +++ b/docs/images/app-icon-light.svg @@ -1,3 +1,10 @@ - - + + + + + + + + + diff --git a/docs/images/app-icon.png b/docs/images/app-icon.png index b17c5527..c856de8e 100644 Binary files a/docs/images/app-icon.png and b/docs/images/app-icon.png differ diff --git a/docs/images/app-icon.svg b/docs/images/app-icon.svg index 05a6e427..d9cc7265 100644 --- a/docs/images/app-icon.svg +++ b/docs/images/app-icon.svg @@ -1,3 +1,10 @@ - - + + + + + + + + + diff --git a/docs/images/banner.png b/docs/images/banner.png index 770d1494..7c4682e9 100644 Binary files a/docs/images/banner.png and b/docs/images/banner.png differ diff --git a/docs/images/banner.svg b/docs/images/banner.svg index fa26b192..447907c4 100644 --- a/docs/images/banner.svg +++ b/docs/images/banner.svg @@ -1,9 +1,15 @@ - - - - Claude Code - Haha - - + + + + + + + + + + Claude Code + Haha + + diff --git a/docs/images/logo-horizontal-dark.png b/docs/images/logo-horizontal-dark.png new file mode 100644 index 00000000..566fca3c Binary files /dev/null and b/docs/images/logo-horizontal-dark.png differ diff --git a/docs/images/logo-horizontal-dark.svg b/docs/images/logo-horizontal-dark.svg new file mode 100644 index 00000000..a9ee37ce --- /dev/null +++ b/docs/images/logo-horizontal-dark.svg @@ -0,0 +1,14 @@ + + + + + + + + + + Claude Code + Haha + + + diff --git a/docs/images/logo-horizontal.png b/docs/images/logo-horizontal.png index 819124e4..10de35fc 100644 Binary files a/docs/images/logo-horizontal.png and b/docs/images/logo-horizontal.png differ diff --git a/docs/images/logo-horizontal.svg b/docs/images/logo-horizontal.svg index 10ab84df..c4cf6676 100644 --- a/docs/images/logo-horizontal.svg +++ b/docs/images/logo-horizontal.svg @@ -1,8 +1,14 @@ - - - Claude Code - Haha - - + + + + + + + + + Claude Code + Haha + +