Skip to content

Commit a0812c3

Browse files
committed
NavLink automatically toggles active based on current location
1 parent 10c2c68 commit a0812c3

File tree

3 files changed

+45
-5
lines changed

3 files changed

+45
-5
lines changed

package-lock.json

Lines changed: 6 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
"webpack-dev-server": "^3.11.0"
6161
},
6262
"dependencies": {
63+
"@plotly/dash-component-plugins": "^1.2.0",
6364
"classnames": "^2.2.6",
6465
"fast-isnumeric": "^1.1.3",
6566
"is-absolute-url": "^2.1.0",

src/components/nav/NavLink.js

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
import React from 'react';
1+
import React, {useEffect, useState} from 'react';
22
import PropTypes from 'prop-types';
33
import {omit} from 'ramda';
44
import classNames from 'classnames';
5+
import {History} from '@plotly/dash-component-plugins';
56
import Link from '../../private/Link';
67

78
/**
89
* Add a link to a `Nav`. Can be used as a child of `NavItem` or of `Nav`
910
* directly.
1011
*/
1112
const NavLink = props => {
13+
const [linkActive, setLinkActive] = useState(false);
1214
const {
1315
children,
1416
disabled,
@@ -17,9 +19,18 @@ const NavLink = props => {
1719
loading_state,
1820
setProps,
1921
n_clicks,
22+
href,
2023
...otherProps
2124
} = props;
2225

26+
const pathnameToActive = pathname => {
27+
setLinkActive(
28+
active === true ||
29+
(active === 'exact' && pathname === href) ||
30+
(active === 'partial' && pathname.startsWith(href))
31+
);
32+
};
33+
2334
const incrementClicks = () => {
2435
if (!disabled && setProps) {
2536
setProps({
@@ -29,12 +40,24 @@ const NavLink = props => {
2940
}
3041
};
3142

32-
const classes = classNames(className, 'nav-link', {active, disabled});
43+
useEffect(() => {
44+
// get initial pathname
45+
pathnameToActive(window.location.pathname);
46+
47+
// add event listener to update on change
48+
History.onChange(() => pathnameToActive(window.location.pathname));
49+
}, []);
50+
51+
const classes = classNames(className, 'nav-link', {
52+
active: linkActive,
53+
disabled
54+
});
3355
return (
3456
<Link
3557
className={classes}
3658
disabled={disabled}
3759
preOnClick={incrementClicks}
60+
href={href}
3861
{...omit(['n_clicks_timestamp'], otherProps)}
3962
data-dash-is-loading={
4063
(loading_state && loading_state.is_loading) || undefined
@@ -88,9 +111,20 @@ NavLink.propTypes = {
88111
href: PropTypes.string,
89112

90113
/**
91-
* Apply 'active' style to this component
114+
* Apply 'active' style to this component. Set to "exact" to automatically
115+
* toggle active status when pathname matches href, or to "partial" to
116+
* automatically toggle on a partial match.
117+
*
118+
* For example
119+
* - dbc.NavLink(..., href="/my-page", active="exact") will be active on
120+
* "/my-page" but not "/my-page/other" or "/random"
121+
* - dbc.NavLink(..., href="/my-page", active="partial") will be active on
122+
* "/my-page" and "/my-page/other" but not "/random"
92123
*/
93-
active: PropTypes.bool,
124+
active: PropTypes.oneOfType([
125+
PropTypes.bool,
126+
PropTypes.oneOf(['partial', 'exact'])
127+
]),
94128

95129
/**
96130
* Disable the link

0 commit comments

Comments
 (0)