react-router-nested-history
A library to help build React apps with nested tabs and other containers that have their own history, complete with automatic altering of the browser's back and forward history to make it behave as you would expect a mobile app like Facebook or Twitter to behave.
Live demo
react-router-nested-history.herokuapp.com
Installation
npm install --save kenfehling/react-router-nested-history
react-router
This library is built to support react-router 4.
This library is very new and not battle-tested, although it does have unit tests, end-to-end tests, examples, and is used on my personal webpage. I would very much appreciate any feedback as I continue to solidify it. It's still under very active development.
Right now this library only works with browserHistory (HTML5 History API, not with hash history)
Roadmap
- Nested container groups
- End to end tests using Nightwatch.js
- Support for title libraries like react-helmet
- Transition animations (slide-in, slide-out)
- Support for SSR (server-side rendering)
- Support for components that lazy render (many existing React tab libraries)
API
HistoryRouter
Use this in place of react-router's BrowserRouter
component to enable this library.
BrowserRouter
props)
props (in addition to the existing name | type | default | description |
---|---|---|---|
zeroPage | string | / | The page at the beginning of the history stack |
HistoryRoute
Use this in place of react-router's Route
component to prevent a match's previous content from disappearing.
HistoryLink
Use this in place of react-router's Link
component to enable history tracking for a link.
HeaderLink
Use this for a container's header link (typically a tab-like thing)
props
name | type | required | description |
---|---|---|---|
toContainer | string | ✓ | The name of the container this links to |
className | string | The CSS class for styling this element | |
activeClassName | string | An alternate CSS class for styling the active item | |
children | ReactNode or Function | The children of this HeaderLink |
children
function params
name | type | description |
---|---|---|
isActive | boolean | Is this HeaderLink's associated Container active? |
BackLink
Use this to place a back link (which only shows if there is back history)
props
name | type | required | description |
---|---|---|---|
children | ReactNode or ({params}) => ReactNode | Defines what appears in the back link (default: 'Back') |
Container
Use this component to wrap one or more HistoryRoute
components to enable history for a container (a nested tab or window).
props
name | type | default | required | description |
---|---|---|---|---|
name | string | ✓ | The name of this container (must be unique) | |
initialUrl | string | ✓ | The path that the container starts on | |
patterns | string[] | ✓ | A list of path patterns that will load in this container from a URL in the address bar | |
isDefault | boolean | false | Consider this the default tab | |
animate | boolean | true | Should this container use slide transition animations? | |
className | string | The CSS class for styling this element |
ContainerGroup
Wraps one or more Container
components that act as a group (a group of tabs, etc.)
props
name | type | default | required | description |
---|---|---|---|---|
name | string | ✓ | The name of this group (must be unique) | |
isDefault | boolean | false | Consider this the default tab (only for a nested group) | |
allowInterContainerHistory | boolean | false | Allow history that would cause containers to switch | |
gotoTopOnSelectActive | boolean | false | Go to the top of a tab if it's selected while already active | |
hideInactiveContainers | boolean | true | Don't show the content of inactive containers | |
resetOnLeave | boolean | false | Reset container's history when switching to another container | |
children | ReactNode or Function | The children of this ContainerGroup |
children
function params
name | type | description |
---|---|---|
currentContainerIndex | number | The index of the current container |
currentContainerName | string | The name of the current container |
stackOrder | Container[] | The containers ordered by how recently they were activated |
setCurrentContainerIndex | (number)=>void | Switch the current container by index |
setCurrentContainerName | (string)=>void | Switch the current container by name |
WindowGroup
A convenience component that wraps a ContainerGroup
and is meant for
creating a group of HistoryWindow
components that overlap and are layered in
the order that they were last accessed.
props
Same as ContainerGroup
but with changes in defaults.
name | type | default | required | description |
---|---|---|---|---|
hideInactiveContainers | boolean | false | Don't render the content of inactive containers |
children
function params
Same as ContainerGroup
except with these additions:
name | type | description |
---|---|---|
openWindow | ({name:string}|{index:number}) => void | Open a window in this group |
resetWindowPositions | () => void | Restore the positions of the windows in this group to their original values |
HistoryWindow
A single window inside a WindowGroup
props
name | type | default | required | description |
---|---|---|---|---|
forName | string | ✓ | The name of the container or group this window wraps | |
visible | boolean | true | Is this window visible? | |
draggable | boolean | false | Uses [react-draggable](https://github.com/mzabriskie/react-draggable) to make window draggable | |
draggableProps | Object | {} | Props passed to the Draggable component | |
rememberPosition | boolean | true if draggable | Remember the position this window was dragged to? | |
left/center/right | number (in pixels) | Position horizontally based on (only) one of these anchor points | ||
top/middle/bottom | number (in pixels) | Position vertically based on (only) one of these anchor points | ||
className | string | The CSS class used to style this window | ||
topClassName | string | The CSS class used when this window is on top | ||
children | ReactNode or Function | ✓ | The children of this HistoryWindow |
children
function params
name | type | description |
---|---|---|
open | () => void | Make this window visible |
close | () => void | Make this window invisible |
switchTo | () => void | Switch to this window |
ScrollArea
Keeps track of scrolling inside a container
props
name | type | default | required | description |
---|---|---|---|---|
resetOnLeave | boolean | false | Reset the scroll position when the container is left | |
horizontal | boolean | false | Use horizontal scrolling | |
vertical | boolean | false | Use vertical scrolling |
WhenActive
Use inside a container to only render something when the container is
active. An example use case is with a library
like react-helmet.
With several windows open Helmet can get confused over which
title, etc. to use. Wrapping Helmet in WhenActive
makes it only
pay attention to the active container.