Skip to content
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

Navigation Component: Remove setActiveLevel child function arg #24704

Merged
merged 3 commits into from
Aug 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion packages/components/src/navigation/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { useEffect, useState } from '@wordpress/element';
* Internal dependencies
*/
import { Root } from './styles/navigation-styles';
import Button from '../button';

const Navigation = ( { activeItemId, children, data, rootTitle } ) => {
const [ activeLevel, setActiveLevel ] = useState( 'root' );
Expand All @@ -20,6 +21,7 @@ const Navigation = ( { activeItemId, children, data, rootTitle } ) => {
parent: item.parent || 'root',
isActive: item.id === activeItemId,
hasChildren: itemChildren.length > 0,
setActiveLevel,
};
} );
};
Expand All @@ -39,13 +41,28 @@ const Navigation = ( { activeItemId, children, data, rootTitle } ) => {
}
}, [] );

const NavigationBackButton = ( { children: backButtonChildren } ) => {
if ( ! parentLevel ) {
return null;
}

return (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we do keep this component instead of passing setActiveLevel maybe we should also include the logic for parentLevel here instead of in the story:

if ( ! parentLevel ) {
  return null;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thats a good addition (a897c42). And the implementation can also do logic like this, so I'll leave the check in the story.

{ parentLevel ? (
	<NavigationBackButton>
		<Icon icon={ arrowLeft } />
		{ parentLevel.title }
	</NavigationBackButton>
) : (
	<Button>Do something else</Button>
) }

<Button
isPrimary
onClick={ () => setActiveLevel( parentLevel.id ) }
>
{ backButtonChildren }
</Button>
);
};

return (
<Root className="components-navigation">
{ children( {
level,
levelItems,
parentLevel,
setActiveLevel,
NavigationBackButton,
} ) }
</Root>
);
Expand Down
31 changes: 21 additions & 10 deletions packages/components/src/navigation/stories/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/
import { Button } from '@wordpress/components';
import { useState } from '@wordpress/element';
import { Icon, arrowLeft } from '@wordpress/icons';

/**
* Internal dependencies
Expand Down Expand Up @@ -48,6 +49,21 @@ const data = [
id: 'child-2',
parent: 'item-3',
},
{
title: 'Nested Category',
id: 'child-3',
parent: 'item-3',
},
{
title: 'Sub Child 1',
id: 'sub-child-1',
parent: 'child-3',
},
{
title: 'Sub Child 2',
id: 'sub-child-2',
parent: 'child-3',
},
{
title: 'External link',
id: 'item-4',
Expand All @@ -68,18 +84,14 @@ function Example() {

return (
<Navigation activeItemId={ active } data={ data } rootTitle="Home">
{ ( { level, levelItems, parentLevel, setActiveLevel } ) => {
{ ( { level, levelItems, parentLevel, NavigationBackButton } ) => {
return (
<>
{ parentLevel && (
<Button
isPrimary
onClick={ () =>
setActiveLevel( parentLevel.id )
}
>
Back
</Button>
<NavigationBackButton>
<Icon icon={ arrowLeft } />
{ parentLevel.title }
</NavigationBackButton>
) }
<h1>{ level.title }</h1>
<NavigationMenu>
Expand All @@ -91,7 +103,6 @@ function Example() {
onClick={ ( selected ) =>
setActive( selected.id )
}
setActiveLevel={ setActiveLevel }
Copy link
Contributor

@joshuatf joshuatf Aug 21, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One concern I have with removing this is that we limit much of the control over the state of this menu externally.

For example, imagine a WooCommerce helper page that says "Navigate to the Settings section in the menu." We can allow the click handler of the Settings link to navigate the side menu. Tutorial based components may also want to make use of this function.

I think this could also be done through props if you prefer (if ( activeLevelId !== prevActiveLevelid ) { setActiveLevel( activeLevelId ) }), but I'd like to not restrict control here too much.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just so I understand what you're suggesting: the feature you'd like to keep is the ability to externally control the navigation component without actually navigating.

I can see why that might be useful in some circumstances. What if we exposed an optional top level prop called activeLevel? That would accomplish the same result without having to expose a function. That brings its own challenges we'd need to document, but I think it would be more straightforward than using setActiveLevel function.

What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure! That sounds like a good strategy to me. Do you want to do it here or should we tackle in a follow-up?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets follow up, issue here: #24775

/>
);
} ) }
Expand Down