Skip to content
Twilight React Playground
ثيم رائدaren

LinkProvider

providerAdvancedlive demo

Tells the engine's Link which real anchor component to render; TwilightProvider supplies TanStack Router's, and tests can supply a plain one.

import { LinkProvider } from '@salla.sa/twilight-theme-engine/providers';

In plain words

The engine's Link does not know which router your theme uses. LinkProvider hands it an adapter: the component that renders the actual anchor. Under TwilightProvider the adapter is TanStack Router's Link, set up for you.

You mount your own LinkProvider only for tests, a component preview tool such as Storybook, or a different router.

Signature

function LinkProvider(props: { adapter: LinkAdapter; children: ReactNode }): JSX.Element

type LinkAdapter = React.ComponentType<LinkProps>;   // LinkProps from '/components/common'

Try it live

The engine’s Link inside a nested LinkProvider: the adapter decides which anchor is rendered, so the same Link works with any router.Try this: click the link: the plain adapter received to as-is, with no locale added, and the Link added data-spa-link.
Storefront canvas · en · LTR
Engine Link to /brands
Attributes on the rendered anchor (click the link):
click the link
Controls
What a theme writes
import type { ReactNode } from 'react';
import { Link, type LinkProps } from '@salla.sa/twilight-theme-engine/components/common';
import { LinkProvider } from '@salla.sa/twilight-theme-engine/providers';

// A test or a Storybook story: plain anchors, no router needed.
function PlainAnchor({ to, href, preload: _preload, replace: _replace, ...rest }: LinkProps) {
  return <a href={to ?? href} {...rest} />;
}

export function WithPlainLinks({ children }: { children: ReactNode }) {
  return <LinkProvider adapter={PlainAnchor}>{children}</LinkProvider>;
}

// <WithPlainLinks><Link to="/brands" preload="intent">Brands</Link></WithPlainLinks>

Example

tests/utils/with-plain-links.tsx
import type { ReactNode } from 'react';
import type { LinkProps } from '@salla.sa/twilight-theme-engine/components/common';
import { LinkProvider } from '@salla.sa/twilight-theme-engine/providers';

function PlainAnchor({ to, href, preload: _preload, replace: _replace, ...rest }: LinkProps) {
  return <a href={to ?? href} {...rest} />;
}

export function WithPlainLinks({ children }: { children: ReactNode }) {
  return <LinkProvider adapter={PlainAnchor}>{children}</LinkProvider>;
}

How it behaves

  • With client.framework: 'tanstack' (the default) the navigation setup mounts LinkProvider with TanStackLinkAdapter once isReady. That adapter adds the current locale to internal paths and turns preload: 'intent' into TanStack's intent preloading.

  • The engine Link passes to (falling back to href, then /), every other prop and data-spa-link="" to the adapter, and forwards its ref.

  • The nearest LinkProvider wins, as with any React context.

Gotchas

  • LinkAdapter is not exported under that name. Type an adapter with LinkProps from @salla.sa/twilight-theme-engine/components/common.

  • An adapter receives preload and replace. Spreading replace={true} onto a DOM anchor makes React warn about a non-boolean attribute; take both out first, as the example does.

Related

Source and docs