# Nav Link

A navigation link that marks the current page with aria-current and data-active. Supports asChild for router links.

Docs: https://corsairui.vercel.app/docs/nav-link

## Install

```bash
pnpm dlx shadcn@latest add @corsair-ui/nav-link
```

Also adds: `utils`.
npm: `@radix-ui/react-slot`, `clsx`, `tailwind-merge`.

## API

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `active` | `boolean` | `false` | Sets aria-current="page" and data-active. |
| `asChild` | `boolean` | `false` | Renders your router's link (next/link, react-router) instead of <a>. |

## Styling

Restyle it in the project that installs it: `className` on each part, the theme variables, and these attributes with arbitrary variants (`[&_[data-slot=…]]:…`, `data-[state=…]:…`).

data-slot: `nav-link`

State attributes:

- `data-active` (computed)

## Accessibility

- The current page is announced through aria-current, not only by colour.

## Examples

On the docs page: Current page. The usage examples in the source comments below are the reference.

## Source

What `shadcn add` writes into the project:

### nav-link.tsx

```tsx
import { Slot } from "@radix-ui/react-slot";
import type { ComponentProps } from "react";
import { cn } from "@/registry/default/lib/utils";

interface NavLinkProps extends ComponentProps<"a"> {
  /** Marks the link as the current page: sets `aria-current="page"` and `data-active`. */
  active?: boolean;
  /** Render the single child (next/link, a router Link, a plain `<a>`) with the link styles instead. */
  asChild?: boolean;
}

/**
 * A navigation link that knows whether it points at the current page. The
 * active link gets `aria-current="page"`, which screen readers announce as
 * "current page", and `data-active="true"` for styling. It stays a real link,
 * so it is reached with Tab and followed with Enter, and shows a focus ring.
 * Pass `asChild` to use your framework's link component.
 *
 * @example
 * <NavLink asChild active={pathname === "/docs"}>
 *   <Link href="/docs">Docs</Link>
 * </NavLink>
 */
function NavLink({ active = false, asChild = false, className, ...props }: NavLinkProps) {
  const Comp = asChild ? Slot : "a";

  return (
    <Comp
      data-slot="nav-link"
      data-active={active}
      aria-current={active ? "page" : undefined}
      className={cn(
        "text-muted-foreground hover:text-foreground data-[active=true]:text-foreground inline-flex items-center gap-1.5 rounded-md px-2 py-1.5 text-sm data-[active=true]:font-medium",
        "transition-colors outline-none motion-reduce:transition-none",
        "focus-visible:ring-ring/50 focus-visible:ring-[3px]",
        "[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
        className
      )}
      {...props}
    />
  );
}

export { NavLink, type NavLinkProps };
```
