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
18 changes: 17 additions & 1 deletion e2e/react-router/basic/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,23 @@ function RootComponent() {
}}
>
This Route Does Not Exist
</Link>
</Link>{' '}
<div className="flex items-center">
<svg width="20" height="20" viewBox="0 0 20 20" role="img">
<title id="rectTitle">Link in SVG</title>
<Link to="/posts" aria-label="Open posts from SVG">
<rect
x="0"
y="0"
width="20"
height="20"
rx="4"
fill="blue"
strokeWidth="2"
/>
</Link>
</svg>
</div>
</div>
<Outlet />
<TanStackRouterDevtools position="bottom-right" />
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
@@ -1,4 +1,8 @@
import { expect, test } from '@playwright/test'
import { getTestServerPort } from '@tanstack/router-e2e-utils'
import packageJson from '../package.json' with { type: 'json' }

const PORT = await getTestServerPort(packageJson.name)

test.beforeEach(async ({ page }) => {
await page.goto('/')
Expand Down Expand Up @@ -45,3 +49,16 @@ test('Navigating to a post page with viewTransition types', async ({
await page.getByRole('link', { name: 'sunt aut facere repe' }).click()
await expect(page.getByRole('heading')).toContainText('sunt aut facere')
})

test('Link in SVG does not trigger a full page reload', async ({ page }) => {
let fullPageLoad = false
page.on('domcontentloaded', () => {
fullPageLoad = true
})

await page.getByRole('link', { name: 'Open posts from SVG' }).click()
const url = `http://localhost:${PORT}/posts`
await page.waitForURL(url)

expect(fullPageLoad).toBeFalsy()
})
33 changes: 32 additions & 1 deletion e2e/solid-router/basic/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
Link,
Outlet,
RouterProvider,
createLink,
createRootRoute,
createRoute,
createRouter,
Expand All @@ -13,6 +14,7 @@ import { TanStackRouterDevtools } from '@tanstack/solid-router-devtools'
import { NotFoundError, fetchPost, fetchPosts } from './posts'
import './styles.css'
import type { ErrorComponentProps } from '@tanstack/solid-router'
import type * as Solid from 'solid-js'

const rootRoute = createRootRoute({
component: RootComponent,
Expand All @@ -26,6 +28,32 @@ const rootRoute = createRootRoute({
},
})

const SvgComponent = ({
// If included causes an error:
// Cannot set property className of #<SVGElement> which has only a getter
class: _className,
...props
}: Solid.JSX.IntrinsicElements['a']) => {
return (
<svg width="20" height="20" viewBox="0 0 20 20" role="img">
<title id="rectTitle">Link in SVG</title>
<a {...props} aria-label="Open posts from SVG">
<rect
x="0"
y="0"
width="20"
height="20"
rx="4"
fill="blue"
stroke-width="2"
/>
</a>
</svg>
)
}

const SvgLink = createLink(SvgComponent)

function RootComponent() {
return (
<>
Expand Down Expand Up @@ -70,7 +98,10 @@ function RootComponent() {
}}
>
This Route Does Not Exist
</Link>
</Link>{' '}
<div class="flex items-center">
<SvgLink to="/posts" />
</div>
</div>
<Outlet />
<TanStackRouterDevtools position="bottom-right" />
Expand Down
17 changes: 17 additions & 0 deletions e2e/solid-router/basic/tests/app.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { expect, test } from '@playwright/test'
import { getTestServerPort } from '@tanstack/router-e2e-utils'
import packageJson from '../package.json' with { type: 'json' }

const PORT = await getTestServerPort(packageJson.name)

test.beforeEach(async ({ page }) => {
await page.goto('/')
Expand Down Expand Up @@ -45,3 +49,16 @@ test('Navigating to a post page with viewTransition types', async ({
await page.getByRole('link', { name: 'sunt aut facere repe' }).click()
await expect(page.getByRole('heading')).toContainText('sunt aut facere')
})

test('Link in SVG does not trigger a full page reload', async ({ page }) => {
let fullPageLoad = false
page.on('domcontentloaded', () => {
fullPageLoad = true
})

await page.getByRole('link', { name: 'Open posts from SVG' }).click()
const url = `http://localhost:${PORT}/posts`
await page.waitForURL(url)

expect(fullPageLoad).toBeFalsy()
})
4 changes: 3 additions & 1 deletion packages/react-router/src/link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,9 @@ export function useLinkProps<
// The click handler
const handleClick = (e: React.MouseEvent) => {
// Check actual element's target attribute as fallback
const elementTarget = (e.currentTarget as HTMLAnchorElement).target
const elementTarget = (
e.currentTarget as HTMLAnchorElement | SVGAElement
).getAttribute('target')
const effectiveTarget = target !== undefined ? target : elementTarget

if (
Expand Down
4 changes: 3 additions & 1 deletion packages/solid-router/src/link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,9 @@ export function useLinkProps<
// The click handler
const handleClick = (e: MouseEvent) => {
// Check actual element's target attribute as fallback
const elementTarget = (e.currentTarget as HTMLAnchorElement).target
const elementTarget = (e.currentTarget as HTMLAnchorElement).getAttribute(
'target',
)
const effectiveTarget =
local.target !== undefined ? local.target : elementTarget

Expand Down