-
Notifications
You must be signed in to change notification settings - Fork 360
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(vertical-navigation): Add the Vertical Navigation pattern #88
feat(vertical-navigation): Add the Vertical Navigation pattern #88
Conversation
@ohadlevy, Serena told me that I should ping you when I had this pushed up. It's not quite done yet, i'm still in the process of refactoring things. I pushed my partial code so I can head home, but I plan to wrap up most of this tonight. |
@mturley It looks like it's still a bit early, but I think this is the right idea. I.m.o. the only component state we’ll need is the state which indicates whether the secondary/tertiary nav drawers are open, everything else can be indicated by props from the application/redux store (including what nav items are active). I like the approach w/ rendering the nav items as lists. Look forward to reviewing it further once you are ready here... |
/cc @amirfefer |
f41321b
to
07a0358
Compare
Sorry for the delay on this, I've had a few distractions. I just pushed a few more commits that complete the basic structure of this and include some refactoring I did to make the primary/secondary/tertiary levels all driven by one VerticalNavigationItem (the markup was similar enough at each level that the differences are logically laid out in the render function without foo much fuss). I think it's pretty clean. Now I just need to finish getting any react-specific CSS tuned up, and address my last few TODO comments. Should be good to go on Monday. My next PR will be at a faster pace-- I've had some new-hire tasks and other one-time distractions these first few weeks. |
bee7f02
to
45a5dec
Compare
activeSecondary, | ||
children, | ||
topBannerContents, | ||
notificationDrawer /* TODO notification drawer components? */, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would leave this out and allow the application to add it separately. The drawer trigger should be added to the topBannerContents and notification drawer would be part of the app content.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, that is sort of what I'm doing here already. The notification drawer is a child of the top banner, so it has to be rendered by this component (React doesn't allow external DOM modifications). So we just accept a prop notificationDrawer
that is just the entire node tree to be rendered in that container. The application can pass a whole other component as that prop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll remove my TODO though, I was wondering whether we wanted to drive it any more directly here. Sounds like we don't.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't believe notificationDrawer needs to be a child of the top banner.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it is part of the vertical navigation, it does buy you the correct top positioning and height otherwise it is not necessary, the application would then need to specify those values. We could handle that in the notification drawer component.
Just seems better to keep them separated to me. I'm OK either way though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. Okay. It was a child of the top banner in the pf-ng code and the PF core example markup. If we don't do that, I feel like we should make that change upstream maybe?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there is no upstream change necessary though. You can have it either way. There is just the preset position and height setting gained by having the drawer-pf a child of navbar-pf-vertical
const { hideTopBanner } = this.state; | ||
this.setState({ | ||
hideTopBanner: !hideTopBanner, | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will need to notify the application as well. The main body content needs to respond to the collapse as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. I'll add a handler that can be passed in for that.
// This class is confusingly named, but the logic is more readable. | ||
'mobile-secondary-item-pf': | ||
mobileItem && depth === 'primary' && showMobileTertiary, | ||
// I don't know, that's just how this stuff was in patternfly-ng... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, could have been named better but basically it is used to handle mobile navigation where only one of the menus (primary, secondary, or tertiary) are shown at a time (the navigation is drill down in mobile mode).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. I'll change this comment to be a little less confused, haha.
/> | ||
<span>{title}</span> | ||
</div> | ||
<ListGroup> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@priley86 , here is the cause of the <li>
-inside-<li>
warnings we are getting. This ListGroup sits inside a ListGroupItem, and renders ListGroupItem children.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you need to add componentClass="ul"
here.
@mturley do you mind rebasing w/ current master? I think something in index.js is misaligned. Getting the following:
|
@mturley Looks like we need index.js in components/VerticalNavigation |
'show-mobile-nav': showMobileNav, | ||
})} | ||
> | ||
<ListGroup> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you need to add componentClass="ul"
here.
/> | ||
<span>{title}</span> | ||
</div> | ||
<ListGroup> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you need to add componentClass="ul"
here.
|
||
VerticalNavigationItem.defaultProps = { | ||
trackActiveState: true, | ||
trackHoverState: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why are the defaults true here? Aren't these indicating the item is active or hovered on? Only one item at most should ever be active, same as hover.
[`${nextDepth}-nav-item-pf`]: | ||
depth !== 'tertiary' && children && children.length > 0, | ||
active: trackActiveState, // This is the only class we have at the tertiary depth. | ||
'visible-xs-block': trackActiveState, // TODO is trackActiveState the right thing here, and is it named right? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure why 'visible-xs-block' set on active items (or ever).
handleTertiaryBlur, | ||
handlePrimaryClick, | ||
handleSecondaryClick, | ||
handleTertiaryClick, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why would an item have 3 levels of click handlers? Any one item would only ever be at one level right? Shouldn't it just have a handleClick, handleHover, handleBlur?
Not really sure why any item needs the handleHover or handleBlur callbacks. Shouldn't the hover state be maintained here? Also, you will find the need to have delays for the hover/blur handling when showing/hiding submenus.
d435940
to
2d2467e
Compare
I'm almost done with this, I squashed all the commits so far and I'll squash again after I push the rest. |
@mturley Would it make sense to create this component w/o secondary or tertiary navigation support to begin with? This gets us partially there (and enough of the way for those w/o secondary menus) and able to try this out before adding the hover/pinned features. Thoughts? |
collapsedSecondaryNav: false, | ||
collapsedTertiaryNav: false, | ||
}; | ||
this.handleNavBarToggleClick = this.handleNavBarToggleClick.bind(this); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can use the bind helpers in helpers.js here now:
https://github.com/patternfly/patternfly-react/blob/master/src/common/helpers.js
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(see Wizard examples)
() => { | ||
return ( | ||
<VerticalNavigation secondaryCollapsed={false} tertiaryCollapsed> | ||
<VerticalNavigationItem title="Item 1" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a nit but can we expose the API as VerticalNavigation.Item
... see Wizard examples...it's just a consistency thing with the other complex components (both in PF React and React Bootstrap) where we have a lots of sub components.
@mturley apologies - ignore my last comment about |
@mturley once you get closer on this, you may want to test w/ React Router. I don't know that we should necessarily assume that VerticalNavigationItem will be a direct child of VerticalNavigation (depending on how we set up the React Router Dom). Reason being is - typically you will see I started some examples of this here prior, but this is missing all of the other vert. nav features you've started in the implementation here. I would say just test this sooner than later ;-> The React Router Dom is of course optional too... you can simply inject the current route state in a parent level wrapper (this might be easier). This would enable you to still use VerticalNavigationItems as direct children... If the downstream product is not using React Router - then this is likely not an issue though... |
|
||
const handleHover = { | ||
primary: handlePrimaryHover, | ||
secondary: handleSecondaryHover, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re-reading this bit... I almost wonder if splitting out Secondary and Tertiary into their own components makes more sense (as it seems it would split the components a bit better as far as props/handlers/etc, i.e.:
<VerticalNavigation >
<VerticalNavigation.Item title="Item 1" secondaryCollapsed={false}>
<VerticalNavigation.SecondaryItem title="Item 1-A" tertiaryCollapsed>
<VerticalNavigation.TertiaryItem title="Item 1-A-i">
</VerticalNavigation.SecondaryItem>
<VerticalNavigation.Item>
</VerticalNavigation>
It seems like this may split the logic a bit better and make it a bit easier to compose...
@jeff-phillips-18 @mturley thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I may be over simplifying a bit though... not sure.
666aa86
to
d0bc6c9
Compare
@jeff-phillips-18 , sorry I didn't notice your comment earlier about doing primary-only. I think I will have everything working shortly, but if there are any further issues with secondary/tertiary stuff I will disable them for now and get this merged. |
Thanks @priley86. I pushed a few more minor tweaks from discussions with @jeff-phillips-18 (fixed corner cases around hover/blur timers). I guess that invalidated your approval. If you could re-approve when you get a chance that'd be great! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Thanks for all the hard work that went into this @mturley !
@mturley nice job on the fixes. Again I am OK to merge here. Another thing I noted with the https://egghead.io/lessons/javascript-redux-persisting-the-state-to-the-local-storage |
Thanks for the reviews guys. @priley86 I like the idea of using redux patterns for local storage, I do think though that even if we add that support, it should still be able to fall back on window.sessionStorage to support users who aren't using redux. |
@mturley sure - i think redux is an optional replacement for the consumer. valid point 👍 |
@jeff-phillips-18 @mturley just want to confirm that the strategy for this component was to match the core implementation, which can be found here: https://rawgit.com/patternfly/patternfly/master-dist/dist/tests/vertical-navigation-with-tertiary-pins.html There is a difference between the Pinning implementation between core & angular. This PR matches the core implementation. Just noting here :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mturley this looks great! Nice to see the different examples as well. I tried a number of different combinations and all looks good 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seeing some issues in mobile
0ce6339
to
ae513f9
Compare
ae513f9
to
279a64b
Compare
Fixed the mobile issues @jeff-phillips-18 was seeing. |
Aww every time I rebase on upstream master it dismisses all my shiny green approvals... @priley86 @serenamarie125 :) |
🎉 |
* feat(deps): apply v4 updates * [cleanup] add back missed storybook type pkgs * [cleanup] make storybook work again
What:
Creating the new Vertical Navigation component.
Why:
To bring patternfly-react one step closer to feature parity with patternfly-ng
How:
New components, factoring things to be as reusable as possible
Storybook: https://mturley.github.io/patternfly-react/?selectedKind=Vertical%20Navigation&selectedStory=Items%20as%20JSX&full=0&addons=1&stories=1&panelRight=0&addonPanel=storybooks%2Fstorybook-addon-knobs