fix(c8): fill-style icons — visual unity with native tabs
CI / ci (push) Canceled after 0s
CI / ci-windows (push) Canceled after 0s
CI / plugin-mount (push) Canceled after 0s

Root cause: DSH's @deepseek-ai/dsh-client-ui-primitives only ships
outline variants (mask+stroke) for agent/gauge/user icons, while native
tabs use fill:currentColor paths (solid, heavy visual weight). This made
the apes tabs look 'lighter' than the official ones in the + menu.

Fix: custom fill-style SVG icons in src/client/apes/icons.tsx
(IconAgentFill16, IconGaugeFill16, IconUserFill16) — matching the
fill:currentColor path style of DSH native tabs (IconCodeOutline16,
IconFolderOpen16, etc.).

Also: order 40/45/50 → 60/65/70 (avoid clash with terminal=40,
browser=50 in the native tab order).
This commit is contained in:
figmar
2026-10-03 19:31:00 +08:00
parent fbd183e93f
commit 2f3944a8bd
4 changed files with 445 additions and 4 deletions
+51
View File
@@ -0,0 +1,51 @@
/**
* Custom fill-style icons for apes tabs — matching the visual weight of
* DSH native tabs (which use `fill: currentColor` paths, not outline/mask).
*
* DSH's `@deepseek-ai/dsh-client-ui-primitives` only ships outline variants
* for agent/gauge/user, so we define our own fill variants here to ensure
* the apes tabs look "official" in the + menu.
*/
import type { ReactNode } from 'react'
/** Agent icon: a simple robot/agent face (fill style). */
export function IconAgentFill16({ size = 16, className }: { size?: number; className?: string }): ReactNode {
return (
<svg width={size} height={size} viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" className={className}>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M8 1.5C4.686 1.5 2 4.186 2 7.5V12.5C2 13.328 2.672 14 3.5 14H12.5C13.328 14 14 13.328 14 12.5V7.5C14 4.186 11.314 1.5 8 1.5ZM8 3C10.485 3 12.5 5.015 12.5 7.5V12.5H3.5V7.5C3.5 5.015 5.515 3 8 3ZM6 6.5C6.828 6.5 7.5 7.172 7.5 8C7.5 8.828 6.828 9.5 6 9.5C5.172 9.5 4.5 8.828 4.5 8C4.5 7.172 5.172 6.5 6 6.5ZM10 6.5C10.828 6.5 11.5 7.172 11.5 8C11.5 8.828 10.828 9.5 10 9.5C9.172 9.5 8.5 8.828 8.5 8C8.5 7.172 9.172 6.5 10 6.5Z"
fill="currentColor"
/>
</svg>
)
}
/** Gauge/app icon: a simple app grid (fill style). */
export function IconGaugeFill16({ size = 16, className }: { size?: number; className?: string }): ReactNode {
return (
<svg width={size} height={size} viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" className={className}>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M3 3H7V7H3V3ZM9 3H13V7H9V3ZM3 9H7V13H3V9ZM9 9H13V13H9V9Z"
fill="currentColor"
/>
</svg>
)
}
/** User/profile icon: a simple user silhouette (fill style). */
export function IconUserFill16({ size = 16, className }: { size?: number; className?: string }): ReactNode {
return (
<svg width={size} height={size} viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" className={className}>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M8 2.5C5.519 2.5 3.5 4.519 3.5 7C3.5 9.481 5.519 11.5 8 11.5C10.481 11.5 12.5 9.481 12.5 7C12.5 4.519 10.481 2.5 8 2.5ZM8 4C9.657 4 11 5.343 11 7C11 8.657 9.657 10 8 10C6.343 10 5 8.657 5 7C5 5.343 6.343 4 8 4ZM2 13.5C2 12.672 2.672 12 3.5 12H12.5C13.328 12 14 12.672 14 13.5C14 14.328 13.328 15 12.5 15H3.5C2.672 15 2 14.328 2 13.5Z"
fill="currentColor"
/>
</svg>
)
}
+4 -4
View File
@@ -26,7 +26,7 @@
*/
import { useCallback, useMemo, useState, type CSSProperties } from 'react'
import { useSyncExternalStore } from 'react'
import { IconAgentPresetOutline16, IconGaugeOutline16, IconUserOutline16 } from '@deepseek-ai/dsh-client-ui-primitives'
import { IconAgentFill16, IconGaugeFill16, IconUserFill16 } from './icons.tsx'
import type { TabComponentProps, TabDescriptor } from '../service.ts'
import type {
SidebarSessionList,
@@ -231,7 +231,7 @@ function ApesAppsView(props: TabComponentProps) {
* to `service.registerTab`. Information-layer tabs are single-instance.
*/
export const apesTabs: TabDescriptor[] = [
{ id: 'apes:agents', title: () => t('apesAgentsTitle'), icon: (size: number) => <IconAgentPresetOutline16 size={size} />, order: 60, single: true, component: ApesAgentsView },
{ id: 'apes:apps', title: () => t('apesAppsTitle'), icon: (size: number) => <IconGaugeOutline16 size={size} />, order: 65, single: true, component: ApesAppsView },
{ id: 'apes:profile', title: () => t('apesProfileTitle'), icon: (size: number) => <IconUserOutline16 size={size} />, order: 70, single: true, component: ApesProfileView },
{ id: 'apes:agents', title: () => t('apesAgentsTitle'), icon: (size: number) => <IconAgentFill16 size={size} />, order: 60, single: true, component: ApesAgentsView },
{ id: 'apes:apps', title: () => t('apesAppsTitle'), icon: (size: number) => <IconGaugeFill16 size={size} />, order: 65, single: true, component: ApesAppsView },
{ id: 'apes:profile', title: () => t('apesProfileTitle'), icon: (size: number) => <IconUserFill16 size={size} />, order: 70, single: true, component: ApesProfileView },
]