Skip to content

Commit e0db681

Browse files
arcanisDSchau
authored andcommittedMar 12, 2019
feat(gatsby-link): adds support for partiallyActive=true to Link (#12495)
* Adds support for partiallyActive=true to Link * Update index.js * Updates the documentation * chore: add typescript declaration(s)
1 parent 2bc1bca commit e0db681

File tree

6 files changed

+38
-16
lines changed

6 files changed

+38
-16
lines changed
 

‎docs/docs/gatsby-link.md

+12-13
Original file line numberDiff line numberDiff line change
@@ -80,28 +80,27 @@ const SiteNavigation = () => (
8080
8181
### Show active styles for partially matched and parent links
8282
83-
<iframe title="Screencast on egghead of how to style partially matched links in Gatsby." class="egghead-video" width=600 height=348 src="https://egghead.io/lessons/egghead-customize-styles-for-partially-matched-urls-with-gatsby-s-link-component/embed" />
84-
85-
Video hosted on [egghead.io][egghead].
86-
87-
The `activeStyle` or `activeClassName` prop are only set on a `<Link>` component if the current URL matches its `to` prop _exactly_. Sometimes, we may want to style a `<Link>` as active even if it partially matches the current URL. For example:
83+
By default the `activeStyle` and `activeClassName` props will only be set on a `<Link>` component if the current URL matches its `to` prop _exactly_. Sometimes, we may want to style a `<Link>` as active even if it partially matches the current URL. For example:
8884
8985
- We may want `/blog/hello-world` to match `<Link to="/blog">`
9086
- Or `/gatsby-link/#passing-state-through-link-and-navigate` to match `<Link to="/gatsby-link">`
9187
92-
In instances like these, we can use [@reach/router's](https://reach.tech/router/api/Link) `getProps` API to set active styles as follows:
88+
In instances like these, just add the `partiallyActive` prop to your `<Link>` component and the style will also be applied even if the `to` prop only is a partial match:
9389
9490
```jsx
9591
import React from "react"
9692
import { Link } from "gatsby"
9793
98-
const partiallyActive = className => ({ isPartiallyCurrent }) => ({
99-
className: className + (isPartiallyCurrent ? ` active` : ``),
100-
})
101-
102-
const PartiallyActiveLink = ({ className, ...rest }) => (
103-
<Link getProps={partiallyActive(className)} {...rest} />
104-
)
94+
const Header = <>
95+
<Link
96+
to="/articles/"
97+
activeStyle={{ color: "red" }}
98+
{/* highlight-next-line */}
99+
partiallyActive={true}
100+
>
101+
Articles
102+
</Link>
103+
</>;
105104
```
106105
107106
### Pass state as props to the linked page

‎packages/gatsby-link/index.d.ts

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ export interface GatsbyLinkProps<TState> extends LinkProps<TState> {
66
activeStyle?: object
77
innerRef?: Function
88
onClick?: (event: React.MouseEvent<HTMLAnchorElement>) => void
9+
partiallyActive?: boolean
10+
replace?: boolean
911
to: string
1012
}
1113

‎packages/gatsby-link/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
},
99
"dependencies": {
1010
"@babel/runtime": "^7.0.0",
11-
"@reach/router": "^1.1.1",
1211
"@types/reach__router": "^1.0.0",
1312
"prop-types": "^15.6.1"
1413
},
@@ -26,6 +25,7 @@
2625
"license": "MIT",
2726
"main": "index.js",
2827
"peerDependencies": {
28+
"@reach/router": "^1.1.1",
2929
"gatsby": "^2.0.0",
3030
"react": "^16.4.2",
3131
"react-dom": "^16.4.2"

‎packages/gatsby-link/src/__tests__/__snapshots__/index.js.snap

+12
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,15 @@ exports[`<Link /> matches basic snapshot 1`] = `
2424
</a>
2525
</div>
2626
`;
27+
28+
exports[`<Link /> matches partially active snapshot 1`] = `
29+
<div>
30+
<a
31+
class="link"
32+
href="/active/nested"
33+
style="color: black;"
34+
>
35+
link
36+
</a>
37+
</div>
38+
`;

‎packages/gatsby-link/src/__tests__/index.js

+7
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,13 @@ describe(`<Link />`, () => {
7474
expect(container).toMatchSnapshot()
7575
})
7676

77+
it(`matches partially active snapshot`, () => {
78+
const { container } = setup({
79+
linkProps: { to: `/active/nested`, partiallyActive: true },
80+
})
81+
expect(container).toMatchSnapshot()
82+
})
83+
7784
it(`does not fail to initialize without --prefix-paths`, () => {
7885
expect(() => {
7986
getInstance({})

‎packages/gatsby-link/src/index.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ function normalizePath(path) {
1818
const NavLinkPropTypes = {
1919
activeClassName: PropTypes.string,
2020
activeStyle: PropTypes.object,
21+
partiallyActive: PropTypes.bool,
2122
}
2223

2324
// Set up IntersectionObserver
@@ -83,8 +84,8 @@ class GatsbyLink extends React.Component {
8384
}
8485
}
8586

86-
defaultGetProps = ({ isCurrent }) => {
87-
if (isCurrent) {
87+
defaultGetProps = ({ isPartiallyCurrent, isCurrent }) => {
88+
if (this.props.partiallyActive ? isPartiallyCurrent : isCurrent) {
8889
return {
8990
className: [this.props.className, this.props.activeClassName]
9091
.filter(Boolean)
@@ -105,6 +106,7 @@ class GatsbyLink extends React.Component {
105106
activeClassName: $activeClassName,
106107
activeStyle: $activeStyle,
107108
innerRef: $innerRef,
109+
partiallyActive,
108110
state,
109111
replace,
110112
/* eslint-enable no-unused-vars */

0 commit comments

Comments
 (0)
Please sign in to comment.