Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/bright-routers-smile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tanstack/router-devtools-core': patch
---

Apply and update React toggle button props in the router devtools.
21 changes: 19 additions & 2 deletions e2e/react-router/basic/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import ReactDOM from 'react-dom/client'
import { useState } from 'react'
import {
ErrorComponent,
Link,
Expand All @@ -9,7 +10,7 @@ import {
createRouter,
redirect,
} from '@tanstack/react-router'
import { TanStackRouterDevtools } from '@tanstack/react-router-devtools'
import { TanStackRouterDevtoolsInProd as TanStackRouterDevtools } from '@tanstack/react-router-devtools'
import { NotFoundError, fetchPost, fetchPosts } from './posts'
import './styles.css'
import type { ErrorComponentProps } from '@tanstack/react-router'
Expand All @@ -27,6 +28,9 @@ const rootRoute = createRootRoute({
})

function RootComponent() {
const [usesUpdatedDevtoolsProps, setUsesUpdatedDevtoolsProps] =
useState(false)

return (
<>
<div className="p-2 flex gap-2 text-lg border-b">
Expand Down Expand Up @@ -88,7 +92,20 @@ function RootComponent() {
</div>
</div>
<Outlet />
<TanStackRouterDevtools position="bottom-right" />
<button type="button" onClick={() => setUsesUpdatedDevtoolsProps(true)}>
Update devtools props
</button>
<TanStackRouterDevtools
position="bottom-right"
toggleButtonProps={{
className: usesUpdatedDevtoolsProps
? 'updated-devtools-toggle'
: 'initial-devtools-toggle',
'aria-label': usesUpdatedDevtoolsProps
? 'Updated Router Devtools'
: 'Custom Router Devtools',
}}
/>
</>
)
}
Expand Down
17 changes: 17 additions & 0 deletions e2e/react-router/basic/tests/app.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,20 @@ test('Link in SVG does not trigger a full page reload', async ({ page }) => {

expect(fullPageLoad).toBeFalsy()
})

test('Applies and updates React props on the devtools toggle button', async ({
page,
}) => {
const initialToggleButton = page.getByRole('button', {
name: 'Custom Router Devtools',
})

await expect(initialToggleButton).toHaveClass(/initial-devtools-toggle/)

await page.getByRole('button', { name: 'Update devtools props' }).click()

const updatedToggleButton = page.getByRole('button', {
name: 'Updated Router Devtools',
})
await expect(updatedToggleButton).toHaveClass(/updated-devtools-toggle/)
})
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { clsx as cx } from 'clsx'

import { createEffect, createMemo, createSignal } from 'solid-js'
import { Show, createEffect, createMemo, createSignal } from 'solid-js'
import { Dynamic } from 'solid-js/web'

import { DevtoolsOnCloseContext } from './context'
Expand Down Expand Up @@ -32,9 +32,7 @@ export interface FloatingDevtoolsOptions {
/**
* Use this to add props to the toggle button. For example, you can add class, style (merge and override default style), onClick (extend default handler), etc.
*/
toggleButtonProps?: any & {
ref?: any
}
toggleButtonProps?: Accessor<any>
/**
* The position of the TanStack Router logo to open and close the devtools panel.
* Defaults to 'bottom-left'.
Expand All @@ -61,7 +59,7 @@ export function FloatingTanStackRouterDevtools({
initialIsOpen,
panelProps = {},
closeButtonProps = {},
toggleButtonProps = {},
toggleButtonProps = () => undefined,
position = 'bottom-left',
containerElement: Container = 'footer',
router,
Expand Down Expand Up @@ -193,12 +191,6 @@ export function FloatingTanStackRouterDevtools({
...otherCloseButtonProps
} = closeButtonProps

const {
onClick: onToggleClick,
class: toggleButtonClassName,
...otherToggleButtonProps
} = toggleButtonProps

// Do not render on the server
if (!isMounted()) return null

Expand All @@ -224,15 +216,6 @@ export function FloatingTanStackRouterDevtools({
}
})

const buttonStyle = createMemo(() => {
return cx(
styles().mainCloseBtn,
styles().mainCloseBtnPosition(position),
styles().mainCloseBtnAnimation(!!isOpen()),
toggleButtonClassName,
)
})

return (
<Dynamic
component={Container}
Expand Down Expand Up @@ -262,27 +245,47 @@ export function FloatingTanStackRouterDevtools({
)} */}
</DevtoolsOnCloseContext.Provider>

<button
type="button"
{...otherToggleButtonProps}
aria-label="Open TanStack Router Devtools"
onClick={(e) => {
setIsOpen(true)
onToggleClick && onToggleClick(e)
<Show keyed when={toggleButtonProps() ?? {}}>
{(resolvedToggleButtonProps) => {
const {
onClick: onToggleClick,
class: solidToggleButtonClassName,
// React uses className while Solid uses class for the same DOM attribute.
className: reactToggleButtonClassName,
...otherToggleButtonProps
} = resolvedToggleButtonProps

return (
<button
type="button"
aria-label="Open TanStack Router Devtools"
{...otherToggleButtonProps}
onClick={(e) => {
setIsOpen(true)
onToggleClick && onToggleClick(e)
}}
class={cx(
styles().mainCloseBtn,
styles().mainCloseBtnPosition(position),
styles().mainCloseBtnAnimation(!!isOpen()),
solidToggleButtonClassName,
reactToggleButtonClassName,
)}
>
<div class={styles().mainCloseBtnIconContainer}>
<div class={styles().mainCloseBtnIconOuter}>
<TanStackLogo />
</div>
<div class={styles().mainCloseBtnIconInner}>
<TanStackLogo />
</div>
</div>
<div class={styles().mainCloseBtnDivider}>-</div>
<div class={styles().routerLogoCloseButton}>TanStack Router</div>
</button>
)
}}
class={buttonStyle()}
>
<div class={styles().mainCloseBtnIconContainer}>
<div class={styles().mainCloseBtnIconOuter}>
<TanStackLogo />
</div>
<div class={styles().mainCloseBtnIconInner}>
<TanStackLogo />
</div>
</div>
<div class={styles().mainCloseBtnDivider}>-</div>
<div class={styles().routerLogoCloseButton}>TanStack Router</div>
</button>
</Show>
</Dynamic>
)
}
Expand Down
10 changes: 7 additions & 3 deletions packages/router-devtools-core/src/TanStackRouterDevtoolsCore.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export class TanStackRouterDevtoolsCore {

#panelProps: any
#closeButtonProps: any
#toggleButtonProps: any
#toggleButtonProps: Signal<any>
#containerElement?: string | any

#isMounted = false
Expand All @@ -74,7 +74,7 @@ export class TanStackRouterDevtoolsCore {

this.#panelProps = config.panelProps
this.#closeButtonProps = config.closeButtonProps
this.#toggleButtonProps = config.toggleButtonProps
this.#toggleButtonProps = createSignal(config.toggleButtonProps)
this.#containerElement = config.containerElement
}

Expand All @@ -92,7 +92,7 @@ export class TanStackRouterDevtoolsCore {

const panelProps = this.#panelProps
const closeButtonProps = this.#closeButtonProps
const toggleButtonProps = this.#toggleButtonProps
const [toggleButtonProps] = this.#toggleButtonProps
const containerElement = this.#containerElement

let Devtools
Expand Down Expand Up @@ -157,5 +157,9 @@ export class TanStackRouterDevtoolsCore {
if (options.containerElement !== undefined) {
this.#containerElement = options.containerElement
}

if ('toggleButtonProps' in options) {
this.#toggleButtonProps[1](options.toggleButtonProps)
}
}
}