primer / blueprints

Reusable components for our documentation sites
MIT License
10 stars 6 forks source link

SideNav Componentization Tracking Issue #7

Closed emplums closed 5 years ago

emplums commented 5 years ago

This is a tracking/scoping issue for refactoring the SideNav component to be reusable.

Currently the SideNav component is hardcoded to work specifically for the blueprints project docs. I'd like to break it up into several different components to be added to the library. This will require a bit of refactoring to make all the components truly reusable.

Scope of Work

Separate SideNav into 7 components:

SideNav

Section

RouteMatch

NavList

NodeLink

SectionLink

NavLink

Notes

shawnbot commented 5 years ago

Yay, happy to see this happening! Please don't feel like you have to keep any of these component names... NodeLink might have made sense for me, but it may not for anyone else. πŸ˜‚ Maybe we call them PageLink, etc.?

Also, I think I may have discovered a better way to get the list of pages in Next.js, which should eliminate all of the pages hackiness that's happening.

emplums commented 5 years ago

Oooh I would be very interested in hearing more!

shawnbot commented 5 years ago

After hunting around GitHub and Spectrum, I found this thread which suggests that contexts can share data between server and client. If that's the case, then I think it looks something like this:

// pages/_document.js
import NextDocument from 'next/document'
import Pages from '../docs/pages'

export default Document extends NextDocument {
  render() {
    const {buildManifest} = this.props
    return (
      <Pages.Provider value={buildManifest.pages}>
        ...
      </Pages.Provider>
    )
}
// docs/components/SideNav.js
import Pages from '../docs/pages'

export default props => (
  <Pages.Consumer>
    {pages => (
      // do something with the pages object
    )}
  </Pages.Consumer> 
)

...and I guess only the components that need access to it would use <Pages.Consumer>?

If contexts don't work across the server/client boundary, then we might need to wire up a slightly hackier solution, but it's got to be better than what we have now. 😬

shawnbot commented 5 years ago

Maybe an HOC that wraps withRouter() would be nice:

export function withPages(Component) {
  return withRouter(props => (
    <Pages.Consumer>{value => <Component pages={value} {...props} />}</Pages.Consumer>
  ))
}
emplums commented 5 years ago

Oh that is super cool! Totally forgot we could use react context for this πŸ€” Since this would be a bit of a refactor, I'll make an issue for it for safe keeping!