diff --git a/.changeset/solid-link-role.md b/.changeset/solid-link-role.md new file mode 100644 index 0000000000..b66e1c1dc6 --- /dev/null +++ b/.changeset/solid-link-role.md @@ -0,0 +1,5 @@ +--- +'@tanstack/solid-router': patch +--- + +Preserve caller-provided roles on enabled links. diff --git a/packages/solid-router/src/link.tsx b/packages/solid-router/src/link.tsx index c5d3691672..ccc1773736 100644 --- a/packages/solid-router/src/link.tsx +++ b/packages/solid-router/src/link.tsx @@ -534,7 +534,7 @@ export function useLinkProps< href: () => hrefOption()?.href, disabled: () => !!local.disabled, target: () => local.target, - role: () => (local.disabled ? 'link' : undefined), + role: () => (local.disabled ? 'link' : propsSafeToSpread.role), 'aria-disabled': () => (local.disabled ? 'true' : undefined), 'data-status': () => (isActive() ? 'active' : undefined), 'aria-current': () => (isActive() ? 'page' : undefined), diff --git a/packages/solid-router/tests/link.test.tsx b/packages/solid-router/tests/link.test.tsx index f4de9b831c..3a5fe05fab 100644 --- a/packages/solid-router/tests/link.test.tsx +++ b/packages/solid-router/tests/link.test.tsx @@ -180,6 +180,51 @@ describe('Link', () => { ).rejects.toThrow() }) + test('preserves a caller-provided role while enabled', async () => { + const [disabled, setDisabled] = Solid.createSignal(false) + const rootRoute = createRootRoute() + const indexRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '/', + component: () => ( + <> + + + Posts + + + ), + }) + const postsRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '/posts', + }) + const router = createRouter({ + routeTree: rootRoute.addChildren([indexRoute, postsRoute]), + history, + }) + + render(() => ) + + const link = await screen.findByTestId('role-link') + const toggle = screen.getByRole('button', { name: 'Toggle disabled' }) + + expect(link).toHaveAttribute('role', 'button') + + fireEvent.click(toggle) + await waitFor(() => expect(link).toHaveAttribute('role', 'link')) + + fireEvent.click(toggle) + await waitFor(() => expect(link).toHaveAttribute('role', 'button')) + }) + test('does not forward internal Link props to the DOM', async () => { const internalPropNames = [ 'activeProps',