Skip to content

Link(props, ...children) renders an <a> that dispatches router.navigate(href) on plain left-clicks, preserving modified clicks (⌘-click, middle-click, etc.) for native browser behaviour — “open in new tab” works without special handling.

import { Link } from "@whisq/router";
function Link(
props: {
href: string;
router: Router;
class?: string | (() => string);
},
...children: (string | number | WhisqNode)[]
): WhisqNode;
PropTypeDescription
hrefstringDestination path — pushed via router.navigate(href) on plain left-click.
routerRouterThe router instance to dispatch against. Pass the same createRouter() return value used by the enclosing RouterView.
classstring | (() => string) (optional)Same reactive-class shape as every other element prop — pass a function to recompute on route change (e.g. for active styling).
Link({ href: "/about", router }, "About Us")

There’s no dedicated active / activeClass prop — the reactive class getter is the pattern. Read router.current.value.path inside a getter:

Link({
href: "/about",
router,
class: () => router.current.value.path === "/about" ? "active" : "",
}, "About")

For a navigation bar where many links share the same rule, factor the active-class function:

const isActive = (href: string) =>
router.current.value.path === href ? "active" : "";
nav(
Link({ href: "/", router, class: () => isActive("/") }, "Home"),
Link({ href: "/about", router, class: () => isActive("/about") }, "About"),
Link({ href: "/blog", router, class: () => isActive("/blog") }, "Blog"),
)

For prefix-matching active styling (e.g. /blog stays active on /blog/my-post), compare with startsWith:

class: () => router.current.value.path.startsWith("/blog") ? "active" : ""

Link checks the click event and skips its own navigation if any of the following are true — the browser handles the click as a plain anchor:

  • event.button !== 0 (middle or right-click)
  • event.metaKey, event.ctrlKey, event.shiftKey, event.altKey

So ⌘-click (or Ctrl-click on Windows) opens in a new tab, Shift-click opens in a new window, etc. — all native browser behaviours are preserved.

  • Plain <a> under the hood. Renders via a(...) and accepts the same reactive class getter pattern.
  • No prefetch, no active class prop. Both are deliberately absent in the current router — if you need them, compose on top: wrap Link in your own component that adds a prefetch hook, or extract an isActive helper as shown above.
  • href is a plain string. It’s not reactive — if you need a dynamic destination, recompose: render a different Link or compute the href at call time.

Docs current to v0.1.0-alpha.9 . All releases →