Skip to content

Commit db10e17

Browse files
authored
fix(core): preserve object-form dock icons in command projection (#378)
1 parent d62b90c commit db10e17

3 files changed

Lines changed: 36 additions & 2 deletions

File tree

‎packages/core/src/client/webcomponents/state/__tests__/dock-groups.test.ts‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
getEntryGroup,
77
getGroupMembers,
88
getRegisteredGroupIds,
9+
resolveCommandIcon,
910
} from '../dock-settings'
1011

1112
function iframe(id: string, extra: Partial<DevToolsDockEntry> = {}): DevToolsDockEntry {
@@ -90,3 +91,21 @@ describe('dock groups', () => {
9091
expect(ids).not.toContain('nuxt:pages')
9192
})
9293
})
94+
95+
describe('resolveCommandIcon (dock icon → command icon projection)', () => {
96+
it('passes string icons through unchanged', () => {
97+
expect(resolveCommandIcon('logos:nuxt-icon')).toBe('logos:nuxt-icon')
98+
})
99+
100+
it('collapses an object icon to its light variant (e.g. the Vite+ group)', () => {
101+
// Regression: object-form icons were dropped to `undefined`, so the Vite+
102+
// entry lost its icon in the command palette and Shortcuts settings.
103+
expect(resolveCommandIcon({ light: 'builtin:vite-plus-core', dark: 'builtin:vite-plus-core' }))
104+
.toBe('builtin:vite-plus-core')
105+
expect(resolveCommandIcon({ light: 'i-light', dark: 'i-dark' })).toBe('i-light')
106+
})
107+
108+
it('falls back to dark when light is absent', () => {
109+
expect(resolveCommandIcon({ dark: 'i-dark' } as any)).toBe('i-dark')
110+
})
111+
})

‎packages/core/src/client/webcomponents/state/context.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { DEFAULT_STATE_USER_SETTINGS } from '@vitejs/devtools-kit/constants'
88
import { computed, markRaw, reactive, ref, toRefs, watchEffect } from 'vue'
99
import { BUILTIN_ENTRIES } from '../constants'
1010
import { createCommandsContext } from './commands'
11-
import { docksGroupByCategories, getGroupMembers, getRegisteredGroupIds } from './dock-settings'
11+
import { docksGroupByCategories, getGroupMembers, getRegisteredGroupIds, resolveCommandIcon } from './dock-settings'
1212
import { createDockEntryState, DEFAULT_DOCK_PANEL_STORE, sharedStateToRef, useDocksEntries } from './docks'
1313
import { createClientMessagesClient } from './messages-client'
1414
import { registerMainFrameDockActionHandler, triggerMainFrameDockAction } from './popup'
@@ -217,7 +217,7 @@ export async function createDocksContext(
217217
id: `devtools:docks:${entry.id}`,
218218
source: 'client' as const,
219219
title: entry.title,
220-
icon: typeof entry.icon === 'string' ? entry.icon : undefined,
220+
icon: resolveCommandIcon(entry.icon),
221221
action: () => {
222222
toggleEntry(entry.id)
223223
},

‎packages/core/src/client/webcomponents/state/dock-settings.ts‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,21 @@ export interface SplitGroupsResult {
1212
overflow: DevToolsDockEntriesGrouped
1313
}
1414

15+
/**
16+
* Resolve a dock entry's icon down to a single icon string.
17+
*
18+
* A dock icon may be a string or a `{ light, dark }` pair, but a command's icon
19+
* is string-only. When projecting dock entries into commands (palette + Shortcuts
20+
* settings) we collapse the object form to a single string rather than dropping
21+
* it — otherwise object-icon docks (e.g. the built-in Vite+ group) lose their
22+
* icon entirely. Returns `undefined` only when no icon is available.
23+
*/
24+
export function resolveCommandIcon(icon: DevToolsDockEntry['icon']): string | undefined {
25+
if (typeof icon === 'string')
26+
return icon
27+
return icon?.light ?? icon?.dark
28+
}
29+
1530
/**
1631
* Collect the ids of every registered dock group (`type: 'group'`).
1732
*

0 commit comments

Comments
 (0)