Usage
Everything you need to drop pokenav into a React app. Prefer picking sprites visually? Use the playground and copy the config it generates.
Install
npm install pokenavreact and react-dom(>=18) are peer dependencies. Import the stylesheet once, anywhere in your app — in the Next.js App Router, your root layout:
import 'pokenav/styles.css';Minimal example
The smallest config that renders: a position, an orientation, and some items. Every other field has a default.
import { Pallet } from 'pokenav';
import 'pokenav/styles.css';
<Pallet
position="left"
orientation="vertical"
items={[
{ label: 'Home', href: '/', pokemonId: 133 },
{ label: 'Work', href: '/work', pokemonId: 81 },
{ label: 'Contact', href: '/contact', pokemonId: 185 },
]}
activeHref={pathname}
/>activeHrefis a plain string you supply — the component compares it to each item's href and imports no router. Use usePathname() in the App Router, useRouter().pathname in Pages, useLocation().pathname in React Router, or your own scroll-spy.
NavConfig reference
| Prop | Type | Default | Description |
|---|---|---|---|
position | 'left' | 'center' | 'right' | — | Which edge the trail anchors to. Also sets which side labels and the pokéball button sit on; center follows left there. |
orientation | 'vertical' | 'horizontal' | — | Which axis the trail runs along. Independent of position. |
items | NavItem[] | — | One node per item, in trail order. |
theme | NavTheme | {} | Optional styling. See below. |
NavItem
| Field | Type | Description |
|---|---|---|
label | string | Visible label, and the section half of the sprite's alt text. |
href | string | Link destination, and what activeHref is compared against. |
pokemonId | number? | National Dex id, 1–898. Resolved from the bundled catalogue, loaded lazily. |
spriteUrl | string? | Any custom image. Wins over pokemonId and skips the catalogue entirely. |
NavTheme
| Field | Type | Default | Description |
|---|---|---|---|
accentColor | string | #64748b | Single source of truth for the active ring, hover ring, inactive ring, trail and focus ring. No color is hardcoded. |
ringStyle | 'solid' | 'pokeball' | solid | pokeball draws a red/white split ring with a button on the seam. |
trailPath | 'straight' | 'wavy' | straight | wavy draws the trail as a curve through the node centers instead of a straight line. |
dotStyle | 'dotted' | 'dashed' | 'solid' | dotted | How the connecting trail is stroked. |
font | string | inherit | CSS font-family applied to labels. |
Component props beyond NavConfig
| Prop | Type | Description |
|---|---|---|
activeHref | string? | Current route. Omit and no node is active. |
scrollProgress | number? | 0–1. Fills the trail and moves the highlight. useScrollProgress() is exported for the page-scroll case. |
ariaLabel | string? | Landmark name. Defaults to 'Site navigation'. |
className | string? | Merged onto the root <nav>. |
Centered horizontal nav
position and orientation are independent, so center works as a top nav. In horizontal, labels always sit below the node so the trail never runs through them.
<Pallet
position="center"
orientation="horizontal"
items={[
{ label: 'Home', href: '/', pokemonId: 25 },
{ label: 'Work', href: '/work', pokemonId: 133 },
{ label: 'Writing', href: '/writing', pokemonId: 143 },
{ label: 'Contact', href: '/contact', pokemonId: 448 },
]}
theme={{ accentColor: '#16a34a', trailPath: 'wavy' }}
activeHref={pathname}
/>Custom sprites — no Pokémon required
Set spriteUrl on an item and the bundled catalogue is never touched. Use it on every item and you get the route-map navigation with entirely your own art, and none of the licensing question below applies to your build.
<Pallet
position="left"
orientation="vertical"
items={[
{ label: 'Home', href: '/', spriteUrl: '/icons/star.svg' },
{ label: 'Work', href: '/work', spriteUrl: '/icons/leaf.svg' },
{ label: 'Contact', href: '/contact', spriteUrl: '/icons/bolt.svg' },
]}
theme={{ accentColor: '#8b5cf6' }}
activeHref={pathname}
/>Pick sprites visually
Writing Dex numbers by hand is no fun. The playground lets you search all 898 sprites, filter by generation, assign them to nav items, and copy out the finished config.
Accessibility
Sprites carry alt text in the form "{Pokémon name} — {section name}", and the visible label is hidden from assistive technology when a sprite is present so the section is not announced twice. Nodes are ordinary links, so keyboard navigation works by default, with a deliberate focus ring drawn in your accent color. All motion — hover bounce, ring transitions, trail fill — is suppressed under prefers-reduced-motion, while state that carries meaning, like the active node's scale and the scroll fill position, is kept.
Sprite licensing
The code is MIT. The bundled Pokémon sprites are fan-derived artwork, not covered by that license, and rely on the same fan-tolerance precedent as PokéAPI — a precedent, not a guarantee. Read SPRITES-NOTICE.md before shipping anything commercial, and remember that spriteUrl lets you avoid the question entirely.