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.
react-router-nested-history.herokuapp.com
npm install --save kenfehling/react-router-nested-history
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)
- 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)
Use this in place of react-router's BrowserRouter
component to enable this library.
name | type | default | description |
---|---|---|---|
zeroPage | string | / | The page at the beginning of the history stack |
Use this in place of react-router's Route
component to prevent a match's previous content from disappearing.
Use this in place of react-router's Link
component to enable history tracking for a link.
Use this for a container's header link (typically a tab-like thing)
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 |
name | type | description |
---|---|---|
isActive | boolean | Is this HeaderLink's associated Container active? |
Use this to place a back link (which only shows if there is back history)
name | type | required | description |
---|---|---|---|
children | ReactNode or ({params}) => ReactNode | Defines what appears in the back link (default: 'Back') |
Use this component to wrap one or more HistoryRoute
components to enable history for a container (a nested tab or window).
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 |
Wraps one or more Container
components that act as a group (a group of tabs, etc.)
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 |
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 |
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.
Same as ContainerGroup
but with changes in defaults.
name | type | default | required | description |
---|---|---|---|---|
hideInactiveContainers | boolean | false | Don't render the content of inactive containers |
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 |
A single window inside a WindowGroup
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 |
name | type | description |
---|---|---|
open | () => void | Make this window visible |
close | () => void | Make this window invisible |
switchTo | () => void | Switch to this window |
Keeps track of scrolling inside a container
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 |
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.