Skip to content

Commit ec4214a

Browse files
feat(vue-query-devtools): Embedded panel mode (#9790)
1 parent ecdf962 commit ec4214a

File tree

5 files changed

+143
-1
lines changed

5 files changed

+143
-1
lines changed

.changeset/mighty-actors-lose.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@tanstack/vue-query-devtools': minor
3+
---
4+
5+
feat(vue-query-devtools): Add embedded panel mode

docs/framework/vue/devtools.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ bun add @tanstack/vue-query-devtools
4444

4545
By default, Vue Query Devtools are only included in bundles when `process.env.NODE_ENV === 'development'`, so you don't need to worry about excluding them during a production build.
4646

47+
## Floating Mode
48+
4749
Devtools will be mounted as a fixed, floating element in your app and provide a toggle in the corner of the screen to show and hide the devtools. This toggle state will be stored and remembered in localStorage across reloads.
4850

4951
Place the following code as high in your Vue app as you can. The closer it is to the root of the page, the better it will work!
@@ -79,6 +81,47 @@ import { VueQueryDevtools } from '@tanstack/vue-query-devtools'
7981
- Default behavior will apply the devtool's styles to the head tag within the DOM.
8082
- Use this to pass a shadow DOM target to the devtools so that the styles will be applied within the shadow DOM instead of within the head tag in the light DOM.
8183

84+
## Embedded Mode
85+
86+
Embedded mode will show the development tools as a fixed element in your application, so you can use our panel in your own development tools.
87+
88+
Place the following code as high in your React app as you can. The closer it is to the root of the page, the better it will work!
89+
90+
```vue
91+
<script setup>
92+
import { VueQueryDevtoolsPanel } from '@tanstack/vue-query-devtools'
93+
const isDevtoolsOpen = ref(false)
94+
function toggleDevtools() {
95+
isDevtoolsOpen.value = !isDevtoolsOpen.value
96+
}
97+
</script>
98+
99+
<template>
100+
<h1>The app!</h1>
101+
<button @click="toggleDevtools">Open Devtools</button>
102+
<VueQueryDevtoolsPanel v-if="isDevtoolsOpen" :onClose="toggleDevtools" />
103+
</template>
104+
```
105+
106+
### Options
107+
108+
- `style?: React.CSSProperties`
109+
- Custom styles for the devtools panel
110+
- Default: `{ height: '500px' }`
111+
- Example: `{ height: '100%' }`
112+
- Example: `{ height: '100%', width: '100%' }`
113+
- `onClose?: () => unknown`
114+
- Callback function that is called when the devtools panel is closed
115+
- `client?: QueryClient`,
116+
- Use this to use a custom QueryClient. Otherwise, the one from the nearest context will be used.
117+
- `errorTypes?: { name: string; initializer: (query: Query) => TError}[]`
118+
- Use this to predefine some errors that can be triggered on your queries. Initializer will be called (with the specific query) when that error is toggled on from the UI. It must return an Error.
119+
- `styleNonce?: string`
120+
- Use this to pass a nonce to the style tag that is added to the document head. This is useful if you are using a Content Security Policy (CSP) nonce to allow inline styles.
121+
- `shadowDOMTarget?: ShadowRoot`
122+
- Default behavior will apply the devtool's styles to the head tag within the DOM.
123+
- Use this to pass a shadow DOM target to the devtools so that the styles will be applied within the shadow DOM instead of within the head tag in the light DOM.
124+
82125
## Traditional Devtools
83126

84127
Vue Query will seamlessly integrate with the [Official Vue devtools](https://github.com/vuejs/devtools-next), adding custom inspector and timeline events.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<script setup lang="ts">
2+
import { computed, onMounted, onScopeDispose, ref, watchEffect } from 'vue'
3+
import { onlineManager, useQueryClient } from '@tanstack/vue-query'
4+
import { TanstackQueryDevtoolsPanel } from '@tanstack/query-devtools'
5+
import type { StyleValue } from 'vue'
6+
import type { DevtoolsPanelOptions } from './types'
7+
8+
const props = defineProps<DevtoolsPanelOptions>()
9+
const style = computed<StyleValue>(() => {
10+
return {
11+
height: '500px',
12+
...props.style,
13+
}
14+
})
15+
16+
const div = ref<HTMLElement>()
17+
const client = props.client || useQueryClient()
18+
const devtools = new TanstackQueryDevtoolsPanel({
19+
client,
20+
queryFlavor: 'Vue Query',
21+
version: '5',
22+
onlineManager,
23+
buttonPosition: 'bottom-left',
24+
position: 'bottom',
25+
initialIsOpen: true,
26+
errorTypes: props.errorTypes,
27+
styleNonce: props.styleNonce,
28+
shadowDOMTarget: props.shadowDOMTarget,
29+
hideDisabledQueries: props.hideDisabledQueries,
30+
onClose: props.onClose,
31+
})
32+
33+
watchEffect(() => {
34+
devtools.setOnClose(props.onClose ?? (() => {}))
35+
devtools.setErrorTypes(props.errorTypes || [])
36+
})
37+
38+
onMounted(() => {
39+
devtools.mount(div.value as HTMLElement)
40+
})
41+
42+
onScopeDispose(() => {
43+
devtools.unmount()
44+
})
45+
</script>
46+
47+
<template>
48+
<div :style="style" className="tsqd-parent-container" ref="div"></div>
49+
</template>
Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import devtools from './devtools.vue'
2+
import devtoolsPanel from './devtoolsPanel.vue'
23
import type { DefineComponent } from 'vue'
3-
import type { DevtoolsOptions } from './types'
4+
import type { DevtoolsOptions, DevtoolsPanelOptions } from './types'
45

56
export const VueQueryDevtools = (
67
process.env.NODE_ENV !== 'development'
@@ -9,3 +10,11 @@ export const VueQueryDevtools = (
910
}
1011
: devtools
1112
) as DefineComponent<DevtoolsOptions, {}, unknown>
13+
14+
export const VueQueryDevtoolsPanel = (
15+
process.env.NODE_ENV !== 'development'
16+
? function () {
17+
return null
18+
}
19+
: devtoolsPanel
20+
) as DefineComponent<DevtoolsPanelOptions, {}, unknown>

packages/vue-query-devtools/src/types.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,39 @@ export interface DevtoolsOptions {
4343
*/
4444
hideDisabledQueries?: boolean
4545
}
46+
47+
export interface DevtoolsPanelOptions {
48+
/**
49+
* Custom instance of QueryClient
50+
*/
51+
client?: QueryClient
52+
/**
53+
* Use this so you can define custom errors that can be shown in the devtools.
54+
*/
55+
errorTypes?: Array<DevtoolsErrorType>
56+
/**
57+
* Use this to pass a nonce to the style tag that is added to the document head. This is useful if you are using a Content Security Policy (CSP) nonce to allow inline styles.
58+
*/
59+
styleNonce?: string
60+
/**
61+
* Use this so you can attach the devtool's styles to specific element in the DOM.
62+
*/
63+
shadowDOMTarget?: ShadowRoot
64+
65+
/**
66+
* Custom styles for the devtools panel
67+
* @default { height: '500px' }
68+
* @example { height: '100%' }
69+
* @example { height: '100%', width: '100%' }
70+
*/
71+
style?: React.CSSProperties
72+
73+
/**
74+
* Callback function that is called when the devtools panel is closed
75+
*/
76+
onClose?: () => unknown
77+
/**
78+
* Set this to true to hide disabled queries from the devtools panel.
79+
*/
80+
hideDisabledQueries?: boolean
81+
}

0 commit comments

Comments
 (0)