Skip to content

Commit fcbd1e1

Browse files
authored
Merge pull request #482 from facultyai/active-navlinks
Active NavLinks
2 parents 10c2c68 + cecefd9 commit fcbd1e1

File tree

4 files changed

+48
-6
lines changed

4 files changed

+48
-6
lines changed

docs/components_page/components/nav.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ Use the `vertical` argument to stack navigation items. You can pass either a Boo
3333

3434
## Pills
3535

36-
Use the `pills` argument to indicate active state with pill styled nav items.
36+
Use the `pills` argument to indicate active state with pill styled nav items. The `active` property can be set to `True` or `False` to manually control whether the link is active, or to `"exact"` to automatically set the `active` property when the current pathname matches the `href`, or to `"partial"` to automatically set the `active` property when the current pathname starts with `href`.
3737

3838
{{example:components/nav/pill.py:nav}}
3939

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: 40 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,22 @@ 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 the current pathname matches href, or to
116+
* "partial" to automatically toggle on a partial match. Assumes that href is
117+
* a relative url such as /link rather than an absolute such as
118+
* https://example.com/link
119+
*
120+
* For example
121+
* - dbc.NavLink(..., href="/my-page", active="exact") will be active on
122+
* "/my-page" but not "/my-page/other" or "/random"
123+
* - dbc.NavLink(..., href="/my-page", active="partial") will be active on
124+
* "/my-page" and "/my-page/other" but not "/random"
92125
*/
93-
active: PropTypes.bool,
126+
active: PropTypes.oneOfType([
127+
PropTypes.bool,
128+
PropTypes.oneOf(['partial', 'exact'])
129+
]),
94130

95131
/**
96132
* Disable the link

0 commit comments

Comments
 (0)