refactor(ui): overhaul icon system and migrate Avatar to shadcn/radix#12858
refactor(ui): overhaul icon system and migrate Avatar to shadcn/radix#12858kangfenmao merged 32 commits intov2from
Conversation
Add MonoIcon component and generate-mono-icons script for creating monochrome versions of provider logos. Update existing SVG logos (DMXAPI, aiOnly, cephalon, cherryin, lanyun, ph8, tokenflux) and add tng.svg. Co-Authored-By: Claude Opus 4.6 <[email protected]>
|
Note This comment was translated by Claude. Were the tsx files generated by executing the icon generation command? Original Content是通过执行icon生成的命令生成的tsx吗 |
Refactor logo icon exports to use compound component pattern: <Anthropic /> — Color (default) <Anthropic.Color /> — Color (explicit) <Anthropic.Mono /> — Mono (currentColor) - Update logos/index.ts to export compound components via Object.assign - Add #__PURE__ annotations for proper tree-shaking - Remove logos-mono/index.ts barrel (mono accessed via .Mono) - Remove LogosMono namespace export from icons/index.ts - Update generate-mono-icons.ts to produce compound barrel Co-Authored-By: Claude Opus 4.6 <[email protected]>
对 |
Replace @svgr/core ConfigPlugin with proper svgo types, add local svgo AST type definitions, and consolidate duplicated helper functions (toCamelCase, ensureViewBox, isImageBased, etc.) into svg-utils.ts. Co-Authored-By: Claude Opus 4.6 <[email protected]>
…enerated catalogs
Implement a centralized icon resolution system in packages/ui that replaces
the old PNG/WebP-based logo imports with CompoundIcon components. Adds
MODEL_ICON_PATTERNS, MODEL_TO_PROVIDER_PATTERNS, and PROVIDER_ID_ALIASES
for regex-based model-to-icon matching with three-tier fallback chain.
Integrates catalog.ts auto-generation into the icon pipeline so new icons
are automatically included. Migrates all renderer consumers (ModelAvatar,
ProviderAvatar, painting pages, mention panel, etc.) from <Avatar src={url}>
to <Icon.Avatar />.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
…and replace MCP market logos - Use `as const satisfies` for PROVIDER_ICON_CATALOG and MODEL_ICON_CATALOG to enable compile-time key validation and export ProviderIconKey/ModelIconKey types - Update codegen script to generate type-safe catalogs automatically - Extract shared getWebSearchProviderLogo() to eliminate 4 duplicate icon mappings - Replace URL-based logos in McpMarketList with PROVIDER_ICON_CATALOG entries - Add new provider icons and remove deprecated image assets Co-Authored-By: Claude Opus 4.6 <[email protected]>
- Replace shadow-lg with shadow-none in Avatar primitive - Remove hardcoded border-[0.5px] from generated avatars - Unify full-bleed variant to use Avatar primitive instead of raw div - Regenerate all 187 provider and model avatar components Co-Authored-By: Claude Opus 4.6 <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Use execSync to run biome format on all ts-morph generated files (index.ts, meta.ts, barrel index, catalog) to remove semicolons and match project formatting conventions. Co-Authored-By: Claude Opus 4.6 <[email protected]>
Replace repeated IIFE patterns for CompoundIcon vs string logo rendering with a reusable LogoAvatar component. Extract MCP provider icon mapping into a dedicated getMCPProviderLogo helper function. Co-Authored-By: Claude Opus 4.6 <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>
…egen Fix typo in Stability AI icon name across SVG, generated components, catalog, barrel index, and registry. Remove per-file biome formatting from codegen to avoid slow generation — format externally instead. Co-Authored-By: Claude Opus 4.6 <[email protected]>
Replace HeroUI Avatar with shadcn-style Avatar + AvatarFallback. Move EmojiAvatar from primitives to composites. Regenerate all avatar components to use the new AvatarFallback pattern. Update renderer components to use the new Avatar API. Co-Authored-By: Claude Opus 4.6 <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Prevents unwanted gray background on icons with transparent SVGs. Background is now opt-in via className (e.g. bg-background for padded). Co-Authored-By: Claude Opus 4.6 <[email protected]>
The radix-ui meta-package was removed but avatar.tsx still imported from it, breaking typecheck. Add the specific @radix-ui/react-avatar package and update the import. Co-Authored-By: Claude Opus 4.6 <[email protected]>
Remove `export * from './icons'` from components/index.ts, replacing it with type-only exports. All icon imports now go through the dedicated `@cherrystudio/ui/icons` subpath. For 7 consumer files that only used static PROVIDER_ICON_CATALOG access, replace with direct named icon imports to enable per-icon tree-shaking. Co-Authored-By: Claude Opus 4.6 <[email protected]>
- package.json: keep both test:pkg:ui and test:shared scripts - minapps.ts: use icon catalog functions (PR) with supportedRegions/bodered/style (v2) - logo.ts: keep simplified getModelLogoById using resolveModelIcon (PR) - CodeToolsPage.tsx: use AnthropicProviderListPopover component (v2) - PpioPage.tsx: use simplified navigation without useLocation (v2) - types/index.ts: keep supportedRegions (v2) with logo type supporting objects (PR) - pnpm-lock.yaml: regenerated from merged package.json Co-Authored-By: Claude Opus 4.6 <[email protected]> Signed-off-by: suyao <[email protected]>
There was a problem hiding this comment.
Reviewed the icon-system overhaul and the Avatar migration paths. I focused on the higher-risk areas first: generated logo exports, provider/model logo mapping, and the renderer-side Avatar consumers. I didn't find a concrete blocking regression in the current revision, and the remaining comments I saw were mostly about style/story completeness rather than functional breakage. LGTM.
There was a problem hiding this comment.
Note
This review was translated by Claude.
Review by kimi-k2.5
Overall Assessment
This is a high-quality large-scale refactoring PR that implements a comprehensive overhaul of the icon system and migrates the Avatar component to shadcn/radix. The code design is excellent, with thorough test coverage and full compliance with project standards.
Recommended Status: Approve ✓
Review Summary
| Category | Rating | Description |
|---|---|---|
| Code Quality | ⭐⭐⭐⭐⭐ | Excellent type safety, clear API design |
| Architecture Design | ⭐⭐⭐⭐⭐ | Elegant Compound Icon pattern, tree-shaking friendly |
| Test Coverage | ⭐⭐⭐⭐⭐ | SVG utility functions have complete unit tests |
| Documentation | ⭐⭐⭐⭐ | Comprehensive README, though some internal implementations lack JSDoc |
| Security | ⭐⭐⭐⭐⭐ | No security issues |
| Performance | ⭐⭐⭐⭐⭐ | Supports tree-shaking, AvatarFallback prevents unnecessary image loading |
Key Highlights
- Excellent Compound Icon API Design -
.Color,.Mono,.Avatarsub-components are uniformly exposed with type safety - Reasonable Icon Resolution Strategy - Three-level fallback mechanism (Model → Provider → Provider ID) provides comprehensive coverage
- High-Quality Code Generation - Uses ts-morph for AST-level generation, ensuring code consistency
- Complete Avatar Migration - Correctly migrated to @radix-ui/react-avatar with size/shape variant support
- Adequate Test Coverage - SVG utility functions handle edge cases appropriately
Minor Suggestions (Non-Blocking)
src/renderer/src/components/Icons/LogoAvatar.tsx:19
// Current
const Icon = logo as CompoundIcon
// Suggestion: use type guard for safer approach
if (typeof logo !== 'string' && 'Avatar' in logo) {
return <logo.Avatar size={size} shape={shape} className={className} />
}Verification Checklist
- ✅ Code logic is correct
- ✅ Good type safety
- ✅ Adequate test coverage
- ✅ No security vulnerabilities
- ✅ Supports tree-shaking
- ✅ Follows project coding standards
- ✅ Breaking changes are clearly documented
⚠️ Minor type assertions can be optimized later
This is a high-quality PR with reasonable refactoring design and complete implementation. It can be merged with confidence. The icon system refactoring will significantly improve project maintainability and performance.
Original Content
Review by kimi-k2.5
总体评价
这是一个高质量的大型重构 PR,实现了图标系统的全面改造和 Avatar 组件的 shadcn/radix 迁移。代码设计良好,测试覆盖充分,符合项目规范。
建议状态: Approve ✓
审查摘要
| 类别 | 评分 | 说明 |
|---|---|---|
| 代码质量 | ⭐⭐⭐⭐⭐ | 良好的类型安全、清晰的 API 设计 |
| 架构设计 | ⭐⭐⭐⭐⭐ | Compound Icon 模式优雅,tree-shaking 友好 |
| 测试覆盖 | ⭐⭐⭐⭐⭐ | SVG 处理工具函数有完整单元测试 |
| 文档 | ⭐⭐⭐⭐ | README 详尽,但部分内部实现缺少 JSDoc |
| 安全性 | ⭐⭐⭐⭐⭐ | 无安全问题 |
| 性能 | ⭐⭐⭐⭐⭐ | 支持 tree-shaking,AvatarFallback 避免图片加载 |
主要亮点
- Compound Icon API 设计优秀 -
.Color、.Mono、.Avatar子组件统一暴露,类型安全 - 图标解析策略合理 - 三级回退机制(Model → Provider → Provider ID)覆盖全面
- 代码生成质量高 - 使用 ts-morph 进行 AST 级别生成,保证代码一致性
- Avatar 迁移完整 - 正确迁移到 @radix-ui/react-avatar,支持 size/shape 变体
- 测试覆盖充分 - SVG 工具函数边界情况处理得当
轻微建议(非阻塞)
src/renderer/src/components/Icons/LogoAvatar.tsx:19
// 当前
const Icon = logo as CompoundIcon
// 建议:使用类型守卫更安全
if (typeof logo !== 'string' && 'Avatar' in logo) {
return <logo.Avatar size={size} shape={shape} className={className} />
}验证检查清单
- ✅ 代码逻辑正确
- ✅ 类型安全良好
- ✅ 测试覆盖充分
- ✅ 无安全漏洞
- ✅ 支持 tree-shaking
- ✅ 符合项目代码规范
- ✅ Breaking changes 已明确记录
⚠️ 轻微类型断言可后续优化
这是一个高质量的 PR,重构设计合理,实现完整,可以放心合并。图标系统的重构将大大改善项目的可维护性和性能。
… package The icon-system overhaul (#12858) removed legacy PNG/WebP/SVG logos from assets/images/apps|models|providers, breaking 20 renderer tests that transitively imported minapps.ts. Replace all 57 dead image imports with CompoundIcon references from @cherrystudio/ui/icons, keeping only application.png (custom-app fallback) and ima.svg (no catalog entry yet). Signed-off-by: fullex <[email protected]>
…#12858) ### What this PR does Before this PR: - Provider/model icons were scattered image imports (PNG/WebP) with no unified API - Avatar primitive was based on HeroUI with hardcoded `shadow-lg` and `border-[0.5px]` - Full-bleed and padded avatar variants used different rendering approaches - Multiple files duplicated IIFE patterns for rendering CompoundIcon vs string logos - No type-safe icon catalogs After this PR: - **Compound Icon API**: Each icon exposes `.Color`, `.Mono`, and `.Avatar` sub-components via a unified `CompoundIcon` interface - **Auto-generated catalogs**: `PROVIDER_ICON_CATALOG` and `MODEL_ICON_CATALOG` with `resolveProviderIcon` / `resolveModelIcon` helpers - **SVG pipeline**: Codegen processes SVGs → generates Color/Mono/Avatar components - **Avatar migrated to shadcn/radix**: Replaced HeroUI Avatar with `Avatar` + `AvatarFallback` pattern, removed hardcoded shadow/border - **EmojiAvatar moved**: From `primitives/Avatar/` to `composites/EmojiAvatar/` - **LogoAvatar component**: Reusable component replacing repeated IIFE patterns across 5+ files - **getMCPProviderLogo helper**: Centralized MCP provider icon mapping - 80+ monochrome icon components, stroke attribute support, deprecated logos cleanup <img width="714" height="820" alt="image" src="https://github.com/user-attachments/assets/a3f14348-5781-494a-8c3b-1f40391e2ec0" /> <img width="1008" height="593" alt="image" src="https://github.com/user-attachments/assets/8ba7fa42-fa33-4e49-ba76-647ba1438e0c" /> ### Why we need it and why it was done in this way The v2 refactoring requires moving away from HeroUI toward shadcn/radix primitives, and needs a scalable, type-safe icon system to replace scattered image imports. The compound icon pattern (`Icon.Color`, `Icon.Mono`, `Icon.Avatar`) provides a consistent API while enabling tree-shaking. The Avatar primitive now uses radix-based `Avatar` + `AvatarFallback`, aligning with the project's shadcn migration. The following tradeoffs were made: - Each icon is a separate TSX file for tree-shaking and lazy loading support - Avatar components use `AvatarFallback` to render icons — no image loading overhead The following alternatives were considered: - Runtime SVG color manipulation — rejected for better performance and consistency - Keeping HeroUI Avatar — rejected as it conflicts with v2 shadcn migration goals ### Breaking changes - Avatar primitive API changed: `HeroUI Avatar` → shadcn `Avatar` + `AvatarFallback` + `AvatarImage` - `EmojiAvatar` moved from `primitives/Avatar` to `composites/EmojiAvatar` - `shadow-lg` and `border-[0.5px]` removed from generated avatars — now opt-in via `className` ### Special notes for your reviewer - ~214 files changed, but the bulk are auto-generated avatar/icon components under `packages/ui/src/components/icons/` - Key files to review: - `packages/ui/src/components/primitives/avatar.tsx` — new shadcn Avatar primitive - `packages/ui/scripts/codegen.ts` — avatar generation using AvatarFallback - `src/renderer/src/components/Icons/LogoAvatar.tsx` — reusable logo renderer - Renderer files using the new Avatar API (Sidebar, UserPopup, ModelAvatar, etc.) ### Checklist - [x] PR: The PR description is expressive enough and will help future contributors - [x] Code: Write code that humans can understand and Keep it simple - [x] Refactor: You have left the code cleaner than you found it (Boy Scout Rule) - [ ] Upgrade: Impact of this change on upgrade flows was considered and addressed if required - [ ] Documentation: N/A - internal component changes ### Release note ```release-note NONE ``` 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: suyao <[email protected]> Co-authored-by: Claude Opus 4.6 <[email protected]> Co-authored-by: icarus <[email protected]>
… package The icon-system overhaul (#12858) removed legacy PNG/WebP/SVG logos from assets/images/apps|models|providers, breaking 20 renderer tests that transitively imported minapps.ts. Replace all 57 dead image imports with CompoundIcon references from @cherrystudio/ui/icons, keeping only application.png (custom-app fallback) and ima.svg (no catalog entry yet). Signed-off-by: fullex <[email protected]>
What this PR does
Before this PR:
shadow-lgandborder-[0.5px]After this PR:
.Color,.Mono, and.Avatarsub-components via a unifiedCompoundIconinterfacePROVIDER_ICON_CATALOGandMODEL_ICON_CATALOGwithresolveProviderIcon/resolveModelIconhelpersAvatar+AvatarFallbackpattern, removed hardcoded shadow/borderprimitives/Avatar/tocomposites/EmojiAvatar/Why we need it and why it was done in this way
The v2 refactoring requires moving away from HeroUI toward shadcn/radix primitives, and needs a scalable, type-safe icon system to replace scattered image imports. The compound icon pattern (
Icon.Color,Icon.Mono,Icon.Avatar) provides a consistent API while enabling tree-shaking. The Avatar primitive now uses radix-basedAvatar+AvatarFallback, aligning with the project's shadcn migration.The following tradeoffs were made:
AvatarFallbackto render icons — no image loading overheadThe following alternatives were considered:
Breaking changes
HeroUI Avatar→ shadcnAvatar+AvatarFallback+AvatarImageEmojiAvatarmoved fromprimitives/Avatartocomposites/EmojiAvatarshadow-lgandborder-[0.5px]removed from generated avatars — now opt-in viaclassNameSpecial notes for your reviewer
packages/ui/src/components/icons/packages/ui/src/components/primitives/avatar.tsx— new shadcn Avatar primitivepackages/ui/scripts/codegen.ts— avatar generation using AvatarFallbacksrc/renderer/src/components/Icons/LogoAvatar.tsx— reusable logo rendererChecklist
Release note
🤖 Generated with Claude Code