Skip to content

Commit

Permalink
feat(react-query-devtools): Add move devtools select menu (#4100)
Browse files Browse the repository at this point in the history
* feat: Add move devtools select menu

Added the option to move devtools to one of these sides `left`,  `right`, `top`, and `bottom` and refactored the code to accommodate the new capability

* fix: import types with ts type import

* fix: fix a docs typo
  • Loading branch information
salamaashoush authored Oct 9, 2022
1 parent f5fb92c commit e6eaca6
Show file tree
Hide file tree
Showing 4 changed files with 476 additions and 153 deletions.
57 changes: 33 additions & 24 deletions docs/devtools.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ function App() {
- `position?: "top-left" | "top-right" | "bottom-left" | "bottom-right"`
- Defaults to `bottom-left`
- The position of the React Query logo to open and close the devtools panel
- `panelPosition?: "top" | "bottom" | "left" | "right"`
- Defaults to `bottom`
- The position of the React Query devtools panel
- `context?: React.Context<QueryClient | undefined>`
- Use this to use a custom React Query context. Otherwise, `defaultContext` will be used.

Expand Down Expand Up @@ -89,6 +92,10 @@ Use these options to style the dev tools.
- The standard React style object used to style a component with inline styles
- `className: string`
- The standard React className property used to style a component with classes
- `showCloseButton?: boolean`
- Show a close button inside the devtools panel
- `closeButtonProps: PropsObject`
- Use this to add props to the close button. For example, you can add `className`, `style` (merge and override default style), `onClick` (extend default handler), etc.

## Devtools in production

Expand All @@ -103,30 +110,32 @@ import { Example } from './Example'
const queryClient = new QueryClient()

const ReactQueryDevtoolsProduction = React.lazy(() =>
import('@tanstack/react-query-devtools/build/lib/index.prod.js').then(d => ({
default: d.ReactQueryDevtools
}))
import('@tanstack/react-query-devtools/build/lib/index.prod.js').then(
(d) => ({
default: d.ReactQueryDevtools,
}),
),
)

function App() {
const [showDevtools, setShowDevtools] = React.useState(false)

React.useEffect(() => {
// @ts-ignore
window.toggleDevtools = () => setShowDevtools(old => !old)
}, [])

return (
<QueryClientProvider client={queryClient}>
<Example />
<ReactQueryDevtools initialIsOpen />
{ showDevtools && (
<React.Suspense fallback={null}>
<ReactQueryDevtoolsProduction />
</React.Suspense>
)}
</QueryClientProvider>
);
const [showDevtools, setShowDevtools] = React.useState(false)

React.useEffect(() => {
// @ts-ignore
window.toggleDevtools = () => setShowDevtools((old) => !old)
}, [])

return (
<QueryClientProvider client={queryClient}>
<Example />
<ReactQueryDevtools initialIsOpen />
{showDevtools && (
<React.Suspense fallback={null}>
<ReactQueryDevtoolsProduction />
</React.Suspense>
)}
</QueryClientProvider>
)
}

export default App
Expand All @@ -140,9 +149,9 @@ If your bundler supports package exports, you can use the following import path:

```tsx
const ReactQueryDevtoolsProduction = React.lazy(() =>
import('@tanstack/react-query-devtools/production').then(d => ({
default: d.ReactQueryDevtools
}))
import('@tanstack/react-query-devtools/production').then((d) => ({
default: d.ReactQueryDevtools,
})),
)
```

Expand Down
99 changes: 99 additions & 0 deletions packages/react-query-devtools/src/__tests__/devtools.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -764,4 +764,103 @@ describe('ReactQueryDevtools', () => {
consoleErrorMock.mockRestore()
})
})

it('should render a menu to select panel position', async () => {
const { queryClient } = createQueryClient()

function Page() {
const { data = 'default' } = useQuery(['check'], async () => 'test')

return (
<div>
<h1>{data}</h1>
</div>
)
}

renderWithClient(queryClient, <Page />, {
initialIsOpen: true,
})

const positionSelect = (await screen.findByLabelText(
'Panel position',
)) as HTMLSelectElement

expect(positionSelect.value).toBe('bottom')
})

it(`should render the panel to the left if panelPosition is set to 'left'`, async () => {
const { queryClient } = createQueryClient()

function Page() {
const { data = 'default' } = useQuery(['check'], async () => 'test')

return (
<div>
<h1>{data}</h1>
</div>
)
}

renderWithClient(queryClient, <Page />, {
initialIsOpen: true,
panelPosition: 'left',
})

const positionSelect = (await screen.findByLabelText(
'Panel position',
)) as HTMLSelectElement

expect(positionSelect.value).toBe('left')

const panel = (await screen.getByLabelText(
'React Query Devtools Panel',
)) as HTMLDivElement

expect(panel.style.left).toBe('0px')
expect(panel.style.width).toBe('500px')
expect(panel.style.height).toBe('100vh')
})

it('should change the panel position if user select different option from the menu', async () => {
const { queryClient } = createQueryClient()

function Page() {
const { data = 'default' } = useQuery(['check'], async () => 'test')

return (
<div>
<h1>{data}</h1>
</div>
)
}

renderWithClient(queryClient, <Page />, {
initialIsOpen: true,
})

const positionSelect = (await screen.findByLabelText(
'Panel position',
)) as HTMLSelectElement

expect(positionSelect.value).toBe('bottom')

const panel = (await screen.getByLabelText(
'React Query Devtools Panel',
)) as HTMLDivElement

expect(panel.style.bottom).toBe('0px')
expect(panel.style.height).toBe('500px')
expect(panel.style.width).toBe('100%')

await act(async () => {
fireEvent.change(positionSelect, { target: { value: 'right' } })
})

expect(positionSelect.value).toBe('right')

expect(panel.style.right).toBe('0px')
expect(panel.style.width).toBe('500px')
expect(panel.style.height).toBe('100vh')
})
})
Loading

0 comments on commit e6eaca6

Please sign in to comment.