Product Switcher Navigation
A free product switcher navigation for React with accessible disclosure links, an adjacent preview, and responsive in-flow behaviour.
Customise
Code
<NavProductSwitcher products={products} />Product Switcher Navigation is a free product switcher navigation react component for Next.js, built with Motion and Tailwind. A native disclosure button opens a stable, width-constrained panel of real product links. Keyboard focus and fine-pointer hover select the same adjacent preview, while a shared-layout indicator moves between entries without measuring the panel on every interaction.
The component follows a non-modal disclosure pattern, not a menu or dialog pattern. Tab keeps its normal document order, every destination remains a complete anchor with its own visible name and description, and the repeated visual preview is hidden from assistive technology. Escape closes and returns focus to the trigger, an outside pointer press closes without stealing focus, and moving focus beyond the navigation closes the panel. On narrow screens the disclosure stays in flow with links first and the preview beneath them. Reduced motion makes the panel and previews swap instantly and removes shared-layout travel.
Install
Add the @te registry to your components.json once:
{
"registries": {
"@te": "https://templateempire.io/r/{name}.json"
}
}Then install the component:
npx shadcn@latest add @te/nav-product-switcherUsage
import { NavProductSwitcher } from "@/components/nav-product-switcher";
const products = [
{
id: "components",
name: "Components",
description: "Motion-first sections ready to install.",
href: "/components",
eyebrow: "Build",
},
{
id: "templates",
name: "Templates",
description: "Complete Next.js marketing sites.",
href: "/templates",
eyebrow: "Launch",
},
{
id: "systems",
name: "Design systems",
description: "Shared tokens and motion standards.",
href: "/design-systems",
eyebrow: "Scale",
},
];
export default function Page() {
return <NavProductSwitcher products={products} initialId="templates" />;
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
| label | string | "Products" | Text shown by the native disclosure button. |
| products | ReadonlyArray<{ id: string; name: string; description: string; href: string; eyebrow?: string }> | required | Three to eight products with unique ids and real root-relative or HTTP(S) destinations. Invalid and duplicate entries are omitted safely. |
| initialId | string | undefined | Initial visual preview. An unknown id falls back to the first valid product. |
| defaultOpen | boolean | false | Open the disclosure on the first interactive render. The server paint stays closed; toggling, Escape, and outside press then behave as normal. |
| width | number | 720 | Panel maximum width in CSS pixels, clamped between 320 and 960. |
| columns | 1 | 2 | 2 | Link-list columns on wide screens. |
| panelDuration | number | 0.28 | Panel open, close, and preview crossfade duration in seconds, clamped between 0 and 0.7. |
| indicatorStiffness | number | 360 | Shared active-indicator spring stiffness, clamped between 140 and 560. |
| previewSide | "left" | "right" | "right" | Preview position on wide screens. Narrow screens keep links first and place the preview below. |
| radius | number | 24 | Panel corner radius in CSS pixels, clamped between 0 and 44. |
| className | string | undefined | Additional classes merged onto the navigation group with cn(). |
Customisation
Product Switcher Navigation exposes three Tier 3 CSS variables for its surface, accent, and dividers. Scalar props control the panel geometry and motion while product wording stays ordinary application data:
:root {
--product-switcher-panel: var(--popover);
--product-switcher-accent: var(--primary);
--product-switcher-divider: var(--border);
}
<NavProductSwitcher
products={products}
width={800}
panelDuration={0.22}
indicatorStiffness={420}
previewSide="left"
radius={20}
/>Frequently asked questions
- Is Product Switcher Navigation free for commercial use?
- Yes. Product Switcher Navigation is MIT licensed, so you can use it in personal and commercial projects without attribution.
- Is Product Switcher Navigation accessible for keyboard and screen reader users?
- Yes. It uses a native disclosure button with aria-expanded and aria-controls, a labelled panel, and real anchors in normal Tab order. It does not apply menu roles, arrow-key trapping, or a focus trap. Escape closes the panel and returns focus to the trigger, while focus leaving the navigation closes without stealing focus.
- How do preview motion and reduced motion work in Product Switcher Navigation?
- Keyboard focus and fine-pointer hover select the same preview. Preview layers overlap in one stable grid cell and crossfade with opacity, while a shared-layout indicator moves on a spring. With reduced motion enabled the panel and preview update instantly, and the indicator is rendered without shared-layout travel.