Skip to content

Commit 3e5c5e7

Browse files
committed
feat: hide Devframe Inspector by default and auto-hide empty terminals/messages docks
1 parent 0dae402 commit 3e5c5e7

8 files changed

Lines changed: 147 additions & 6 deletions

File tree

packages/core/src/client/webcomponents/components/views-builtin/SettingsAdvanced.vue

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ import type { SharedState } from 'devframe/utils/shared-state'
44
import type { DevToolsDocksUserSettings } from '../../state/dock-settings'
55
import { DEFAULT_STATE_USER_SETTINGS } from '@vitejs/devtools-kit/constants'
66
import { useConfirm } from '../../state/confirm'
7+
import { sharedStateToRef } from '../../state/docks'
78
89
const props = defineProps<{
910
context: DocksContext
1011
settingsStore: SharedState<DevToolsDocksUserSettings>
1112
}>()
1213
14+
const settings = sharedStateToRef(props.settingsStore)
1315
const confirm = useConfirm()
1416
1517
async function resetAllSettings() {
@@ -64,6 +66,26 @@ async function deauthorize() {
6466

6567
<template>
6668
<div class="flex flex-col gap-6">
69+
<!-- Show Devframe Inspector toggle -->
70+
<label class="flex items-center gap-3 cursor-pointer group">
71+
<button
72+
class="w-10 h-6 rounded-full transition-colors relative shrink-0"
73+
:class="settings.showDevframeInspector ? 'bg-lime' : 'bg-gray/30'"
74+
@click="settingsStore.mutate((s) => { s.showDevframeInspector = !s.showDevframeInspector })"
75+
>
76+
<div
77+
class="absolute top-1 w-4 h-4 rounded-full bg-white shadow transition-transform"
78+
:class="settings.showDevframeInspector ? 'translate-x-5' : 'translate-x-1'"
79+
/>
80+
</button>
81+
<div class="flex flex-col">
82+
<span class="text-sm">Show Devframe Inspector</span>
83+
<span class="text-xs op50">Reveal the experimental Devframe Inspector dock — the DevTools for the DevTools</span>
84+
</div>
85+
</label>
86+
87+
<div class="border-t border-base" />
88+
6789
<!-- Reset Shortcuts -->
6890
<div class="flex items-start gap-4">
6991
<div class="flex-1">

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

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { DevToolsDockEntry } from '@vitejs/devtools-kit'
2-
import { DEFAULT_STATE_USER_SETTINGS } from '@vitejs/devtools-kit/constants'
2+
import { DEFAULT_STATE_USER_SETTINGS, DEVTOOLS_INSPECTOR_DOCK_ID } from '@vitejs/devtools-kit/constants'
33
import { describe, expect, it } from 'vitest'
44
import {
55
docksGroupByCategories,
@@ -92,6 +92,33 @@ describe('dock groups', () => {
9292
})
9393
})
9494

95+
describe('devframe inspector visibility (settings: showDevframeInspector)', () => {
96+
const entries: DevToolsDockEntry[] = [
97+
iframe('a'),
98+
iframe(DEVTOOLS_INSPECTOR_DOCK_ID),
99+
]
100+
101+
it('hides the inspector from the dock bar by default', () => {
102+
const grouped = docksGroupByCategories(entries, settings)
103+
const ids = grouped.flatMap(([, items]) => items.map(i => i.id))
104+
expect(ids).toContain('a')
105+
expect(ids).not.toContain(DEVTOOLS_INSPECTOR_DOCK_ID)
106+
})
107+
108+
it('reveals the inspector when showDevframeInspector is enabled', () => {
109+
const enabled = { ...settings, showDevframeInspector: true }
110+
const grouped = docksGroupByCategories(entries, enabled)
111+
const ids = grouped.flatMap(([, items]) => items.map(i => i.id))
112+
expect(ids).toContain(DEVTOOLS_INSPECTOR_DOCK_ID)
113+
})
114+
115+
it('still lists the inspector in the settings management view (includeHidden)', () => {
116+
const grouped = docksGroupByCategories(entries, settings, { includeHidden: true })
117+
const ids = grouped.flatMap(([, items]) => items.map(i => i.id))
118+
expect(ids).toContain(DEVTOOLS_INSPECTOR_DOCK_ID)
119+
})
120+
})
121+
95122
describe('resolveCommandIcon (dock icon → command icon projection)', () => {
96123
it('passes string icons through unchanged', () => {
97124
expect(resolveCommandIcon('logos:nuxt-icon')).toBe('logos:nuxt-icon')

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { DevToolsDockEntriesGrouped, DevToolsDockEntry, DevToolsDocksUserSettings, DevToolsViewGroup } from '@vitejs/devtools-kit'
22
import type { Immutable } from 'devframe/utils/shared-state'
33
import type { WhenContext } from 'devframe/utils/when'
4+
import { DEVTOOLS_INSPECTOR_DOCK_ID } from '@vitejs/devtools-kit/constants'
45
import { evaluateWhen } from 'devframe/utils/when'
56
import { DEFAULT_CATEGORIES_ORDER } from '../constants'
67

@@ -104,6 +105,11 @@ export function docksGroupByCategories(
104105
continue
105106
if (entry.when && !whenContext && entry.when === 'false' && !includeHidden)
106107
continue
108+
// The Devframe Inspector is hidden by default; it only joins the dock bar
109+
// once opted into via Settings → Advanced. The settings management view
110+
// (`includeHidden`) still lists it so users can discover the toggle.
111+
if (!includeHidden && entry.id === DEVTOOLS_INSPECTOR_DOCK_ID && !settings.showDevframeInspector)
112+
continue
107113
if (!includeHidden && docksHidden.includes(entry.id))
108114
continue
109115

packages/core/src/node/plugins/index.ts

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
import type { KitNodeContext } from '@vitejs/devtools-kit/node'
12
import type { Plugin } from 'vite'
23
import { createInspectDevframe } from '@devframes/plugin-inspect'
34
import { createMessagesDevframe } from '@devframes/plugin-messages'
45
import { createTerminalsDevframe } from '@devframes/plugin-terminals'
6+
import { DEVTOOLS_INSPECTOR_DOCK_ID } from '@vitejs/devtools-kit/constants'
57
import { createPluginFromDevframe } from '@vitejs/devtools-kit/node'
68
import { DevToolsBuild } from './build'
79
import { DevToolsInjection } from './injection'
@@ -58,24 +60,81 @@ export async function DevTools(options: DevToolsOptions = {}): Promise<Plugin[]>
5860
// dock — rather than the `~viteplus` group (which collects integrations
5961
// like Rolldown). The hub's own `~terminals` / `~messages` docks are
6062
// suppressed via `builtinDocks` in `createDevToolsContext`.
61-
plugins.push(createPluginFromDevframe(createTerminalsDevframe(), {
63+
//
64+
// The hub's built-in `~terminals` / `~messages` docks auto-hid themselves
65+
// when empty; the plugin-mounted iframe docks that replaced them carry no
66+
// such rule, so we restore it here — the dock is filtered out of the bar
67+
// (`when: 'false'`) whenever there are no sessions / messages.
68+
const terminalsDevframe = createTerminalsDevframe()
69+
plugins.push(createPluginFromDevframe(terminalsDevframe, {
6270
dock: { category: '~builtin' },
71+
setup(ctx) {
72+
hideDockWhenEmpty(
73+
ctx,
74+
terminalsDevframe.id,
75+
() => ctx.terminals.sessions.size === 0,
76+
refresh => ctx.terminals.events.on('terminal:session:updated', refresh),
77+
)
78+
},
6379
}))
64-
plugins.push(createPluginFromDevframe(createMessagesDevframe(), {
80+
const messagesDevframe = createMessagesDevframe()
81+
plugins.push(createPluginFromDevframe(messagesDevframe, {
6582
dock: { category: '~builtin' },
83+
setup(ctx) {
84+
hideDockWhenEmpty(
85+
ctx,
86+
messagesDevframe.id,
87+
() => ctx.messages.entries.size === 0,
88+
(refresh) => {
89+
ctx.messages.events.on('message:added', refresh)
90+
ctx.messages.events.on('message:updated', refresh)
91+
ctx.messages.events.on('message:removed', refresh)
92+
ctx.messages.events.on('message:cleared', refresh)
93+
},
94+
)
95+
},
6696
}))
6797

6898
// Meta-introspection ("DevTools for the DevTools"), provided by the
6999
// official devframe inspector plugin (replaces the former
70-
// `@vitejs/devtools-self-inspect` package).
71-
plugins.push(createPluginFromDevframe(createInspectDevframe(), {
100+
// `@vitejs/devtools-self-inspect` package). Pinned to a stable id so the
101+
// client can gate it behind the `showDevframeInspector` user setting;
102+
// hidden by default (opt in via Settings → Advanced).
103+
plugins.push(createPluginFromDevframe(createInspectDevframe({ id: DEVTOOLS_INSPECTOR_DOCK_ID }), {
72104
dock: { category: '~builtin', icon: 'ph:stethoscope-duotone' },
73105
}))
74106
}
75107

76108
return plugins
77109
}
78110

111+
/**
112+
* Keep a dock entry out of the dock bar while its backing collection is empty.
113+
*
114+
* Mirrors the hub's built-in `~terminals` / `~messages` auto-hide: sets the
115+
* dock's `when` clause to `'false'` (unconditionally hidden) when `isEmpty()`
116+
* and clears it otherwise, re-evaluating whenever the passed `subscribe`
117+
* callback fires. Each `docks.update` re-broadcasts the dock shared state.
118+
*/
119+
function hideDockWhenEmpty(
120+
ctx: KitNodeContext,
121+
dockId: string,
122+
isEmpty: () => boolean,
123+
subscribe: (refresh: () => void) => void,
124+
): void {
125+
const sync = (): void => {
126+
const view = ctx.docks.views.get(dockId)
127+
if (!view)
128+
return
129+
const when = isEmpty() ? 'false' : undefined
130+
if (view.when === when)
131+
return
132+
ctx.docks.update({ ...view, when })
133+
}
134+
subscribe(sync)
135+
sync()
136+
}
137+
79138
export {
80139
DevToolsBuild,
81140
DevToolsInjection,

packages/kit/src/constants.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@ export const DEVTOOLS_DOCK_IMPORTS_VIRTUAL_ID = '/__devtools-client-imports.js'
4040
*/
4141
export const DEVTOOLS_VITEPLUS_GROUP_ID = '~viteplus'
4242

43+
/**
44+
* Dock id of the built-in Devframe Inspector (mounted from
45+
* `@devframes/plugin-inspect`). Shared between the node side (which pins the
46+
* mounted devframe to this id) and the client (which gates the dock behind the
47+
* `showDevframeInspector` user setting).
48+
*/
49+
export const DEVTOOLS_INSPECTOR_DOCK_ID = 'devframes-plugin-inspect'
50+
4351
export const DEFAULT_CATEGORIES_ORDER: Record<string, number> = {
4452
'default': 0,
4553
'app': 100,

packages/kit/src/types/settings.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,18 @@
1-
export type { DevframeDocksUserSettings as DevToolsDocksUserSettings } from '@devframes/hub/types'
1+
import type { DevframeDocksUserSettings } from '@devframes/hub/types'
2+
3+
/**
4+
* Vite DevTools user settings — the hub's {@link DevframeDocksUserSettings}
5+
* widened with Vite-flavored toggles that only Vite DevTools ships.
6+
*
7+
* The extra fields are optional so the hub's `DEFAULT_STATE_USER_SETTINGS()`
8+
* (which knows nothing about them) stays assignable; an absent value reads as
9+
* its documented default.
10+
*/
11+
export interface DevToolsDocksUserSettings extends DevframeDocksUserSettings {
12+
/**
13+
* Reveal the Devframe Inspector dock (the "DevTools for the DevTools"
14+
* meta-introspection panel). Hidden by default — an absent value keeps the
15+
* dock out of the dock bar until the user opts in from Settings → Advanced.
16+
*/
17+
showDevframeInspector?: boolean
18+
}

test/__snapshots__/tsnapi/@vitejs/devtools-kit/constants.snapshot.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
export declare const DEFAULT_CATEGORIES_ORDER: Record<string, number>;
66
export declare const DEVTOOLS_DIRNAME: string;
77
export declare const DEVTOOLS_DOCK_IMPORTS_VIRTUAL_ID: string;
8+
export declare const DEVTOOLS_INSPECTOR_DOCK_ID: string;
89
export declare const DEVTOOLS_MOUNT_PATH: string;
910
export declare const DEVTOOLS_MOUNT_PATH_NO_TRAILING_SLASH: string;
1011
export declare const DEVTOOLS_VITEPLUS_GROUP_ID: string;

test/__snapshots__/tsnapi/@vitejs/devtools-kit/constants.snapshot.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
export var DEFAULT_CATEGORIES_ORDER /* const */
66
export var DEVTOOLS_DIRNAME /* const */
77
export var DEVTOOLS_DOCK_IMPORTS_VIRTUAL_ID /* const */
8+
export var DEVTOOLS_INSPECTOR_DOCK_ID /* const */
89
export var DEVTOOLS_MOUNT_PATH /* const */
910
export var DEVTOOLS_MOUNT_PATH_NO_TRAILING_SLASH /* const */
1011
export var DEVTOOLS_VITEPLUS_GROUP_ID /* const */

0 commit comments

Comments
 (0)