npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

storybook-found-router

v1.1.0

Published

Storybook decorator for React components using Found routing

Readme

storybook-found-router

Storybook decorator for React components using Found routing

This storybook decorator will allow you to render the React components of your application that use any of the Found router instances by adding a memory router wrapper to your stories. You can customise the decorator using the two arguments routeConfig and initialLocation to navigate within the storybook, taking advantage of the built in Story Links Addon functionality, and set the initial location; in addition to this your routing actions will also be logged by default using the Storybook Addon Action

Guide

Installation

npm install --save-dev storybook-found-router

Basic usage

If you just want to be able to render your routing aware components you can add the decorator to your stories like this

import React from 'react'
import Link from 'found/lib/Link'
import { storiesOf } from '@storybook/react'
import storyRouter from 'storybook-found-router'

const Navigation = () => (
  <div>
    <ul>
      <li><Link to='/blog'>Blog</Link></li>
    </ul>
  </div>
)

storiesOf('Navigation', module)
  .addDecorator(storyRouter())
  .add('default', () => <Navigation />)

This is useful when your hypothetical Navigation component is using some Found instances like the Link from found/lib/Link. This basic implementation allows you to render the component and storybook-found-router will log the router action when you click on a link (e.g. PUSH: ["/blog"]) to let you know what the router would perform when running your application; however no real action will be performed unless you stat using the first argument: routeConfig.

Custom usage

If you want your links to actually perform some navigation you can do so by using the first routeConfig argument. Imagine that you have a story like this

import React from 'react'
import Link from 'found/lib/Link'
import { storiesOf } from '@storybook/react'

const Blog = ({ user = 'Guest' }) => <div>Hey {user}, welcome to my blog</div>

storiesOf('Blog', module)
  .add('default', () => <Blog />)
  .add('user', () => <Blog user='Luke Skywalker' />)

If we take the example given above in the "Basic usage" and want to perform navigation when clicking on the /blog link we can do so by setting the first argument like this

storiesOf('Navigation', module)
  .addDecorator(storyRouter([{ path: 'blog', story: 'Blog' }]))
  .add('default', () => <Navigation />)

With the above configuration when our Navigation sotry is rendered and we click the link to /blog we will be redirected to the default story of the Blog "kind", as defined with this line storiesOf('Blog', module).add('default', () => <Blog />).

You might have noticed that our Blog "kind" has two stories defined, default and user; if we wanted our link to navigate to the user story we could do this by passing an array to the story property of our routeConfig argument like this

storiesOf('Navigation', module)
  .addDecorator(storyRouter([{ path: 'blog', story: ['Blog', 'user'] }]))
  .add('default', () => <Navigation />)

Advanced usage

The "Custom usage" seen above is handy when you want to render isolated components using router instances and with a few links that you want to direct to stories, but what about if you want to support multiple nested routes within your application? Perhaps you might want to consider mimicking your Found route configuration and add the decorator globally to all stories

import { configure, addDecorator } from '@storybook/react'

function loadStories() {
  // Import your stories here
}
const routeConfig = [
  {
    path: '/',
    story: 'HomePage',
    children: [
      {
        path: 'blog',
        story: 'BlogPage',
        children: [
          {
            path: ':post',
            story: 'PostPage',
            children: [
              {
                path: 'author',
                story: 'AuthorPage'
              }
            ]
          }
        ]
      }
    ]
  }
]

addDecorator(storyRouter(routeConfig))
configure(loadStories, module)

With this global configuration you will only have to define your routeConfig in one place and all your stories will automatically be decorated with the router instances; this configuration will also allow you to handle navigation on multiple links within one component matching nested routes like this

const Navigation = () => (
  <div>
    <ul>
      <li><Link to='/blog'>Blog</Link></li>
      <li><Link to='/blog/123'>Blog Post</Link></li>
      <li><Link to='/blog/123/author'>Post Author</Link></li>
    </ul>
  </div>
)

Arguments

The storybook-found-router function takes two optional arguments

routeConfig

The first argument you can pass is routeConfig which is an array of objects containing the following three properties

  • path a string containing the location path you want to match
  • story a string containing the name of the "kind" ('HomePage') or an array containing both the "kind" and the story name (['HomePage', 'default'])
  • children an array of objects containing additional nested routes

If you omit the story property the decorator will still provide the router instances to your story components but clicking on the matched link won't trigger any navigation action. When passing a string to the story property the decorator will match the 'default' story of the specified "kind" so you need to use an array just when you want to match a specific story within a "kind" which is not the 'default'.

initialLocation

A string that will be passed to the MemoryRouter as initial location; useful when your component need to be aware of the active route.

Notes

Matching is performed using the default Found matching algorithm as this decorator is not meant to reinvent any matching logic. Under the hood the Found matching algorithm is performed using Path-to-RegExp which allows you to use some patterns like the following

  • /path/subpath => Matches /path/subpath
  • /path/:param => Matches /path/foo
  • /path/:regexParam(\\d+) => Matches /path/123 - Does not match /path/foo
  • /path/:optionalParam? => Matches /path/foo and /path
  • /path/* => Matches /path/foo/bar