Navigation patterns
Production-grade SaaS UI skills for AI coding agents (React + Tailwind + shadcn/ui) — Codex, Claude Code, Cursor, OpenCode. One npx command to install.
npx -y skills add param087/saas-ui-skills --skill navigation-patternsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Use when building app navigation — sidebar nav with active states, a command palette (cmdk), tabs, and breadcrumbs. Covers accessible markup, active-route detection, and keyboard-first navigation.
SKILL.md
4.1 KB, as published. Nobody here has run it
Navigation Patterns
Overview
Navigation is how users build a mental map of your SaaS app. The core set: a sidebar for primary sections, tabs for views within a page, breadcrumbs for depth, and a command palette for power users. Mark up each with semantic landmarks and correct active state so both mouse and keyboard users stay oriented.
When to use
- Building the primary sidebar or in-page tabs.
- Adding ⌘K quick navigation/search.
- Users get lost or can't tell where they are.
Sidebar with active state
"use client";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { cn } from "@/lib/utils";
const items = [
{ href: "/dashboard", label: "Dashboard", icon: Home },
{ href: "/invoices", label: "Invoices", icon: FileText },
{ href: "/settings", label: "Settings", icon: Settings },
];
export function Sidebar() {
const pathname = usePathname();
return (
<nav aria-label="Primary" className="flex flex-col gap-1 p-3">
{items.map(({ href, label, icon: Icon }) => {
const active = pathname === href || pathname.startsWith(href + "/");
return (
<Link
key={href}
href={href}
aria-current={active ? "page" : undefined}
className={cn(
"flex items-center gap-3 rounded-md px-3 py-2 text-sm font-medium transition-colors",
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
active ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted/50 hover:text-foreground",
)}
>
<Icon className="h-4 w-4" aria-hidden />
{label}
</Link>
);
})}
</nav>
);
}
aria-current="page" tells screen readers which item is active — color alone isn't enough. Match the active route with startsWith so nested pages keep their parent highlighted.
Command palette (⌘K)
import { CommandDialog, CommandInput, CommandList, CommandItem, CommandGroup } from "@/components/ui/command";
export function CommandMenu() {
const [open, setOpen] = React.useState(false);
React.useEffect(() => {
const down = (e: KeyboardEvent) => {
if (e.key === "k" && (e.metaKey || e.ctrlKey)) { e.preventDefault(); setOpen((o) => !o); }
};
document.addEventListener("keydown", down);
return () => document.removeEventListener("keydown", down);
}, []);
return (
<CommandDialog open={open} onOpenChange={setOpen}>
<CommandInput placeholder="Search or jump to…" />
<CommandList>
<CommandGroup heading="Navigation">
<CommandItem onSelect={() => go("/invoices")}>Invoices</CommandItem>
<CommandItem onSelect={() => go("/settings")}>Settings</CommandItem>
</CommandGroup>
</CommandList>
</CommandDialog>
);
}
cmdk (under shadcn Command) gives fuzzy search, arrow-key nav, and focus management for free.
Tabs & breadcrumbs
- Tabs for switching views of the same resource (Overview / Activity / Settings). Use shadcn
Tabs; sync the active tab to?tab=for deep links. - Breadcrumbs for hierarchy (
Workspace › Project › Settings); wrap in<nav aria-label="Breadcrumb">and mark the last crumbaria-current="page".
Pitfalls
- Active state by color only — add
aria-currentand ideally weight/indicator. - Exact-match active route breaks on nested pages — use
startsWith. - Command palette without focus trap/Esc — use the
Commanddialog primitive. - Tabs that lose state on refresh — persist to the URL.
- No
aria-labelon multiple<nav>s — screen readers can't distinguish them.
Hand-off
Wayfinding that sits inside the responsive-layout shell; deep flows route into settings-pages, billing-and-pricing, and dashboard-layout.