Skip to content
This repository has been archived by the owner on Mar 4, 2020. It is now read-only.

feat(Toolbar): add menu prop #1518

Merged
merged 14 commits into from
Jun 26, 2019
Merged

feat(Toolbar): add menu prop #1518

merged 14 commits into from
Jun 26, 2019

Conversation

miroslavstastny
Copy link
Member

@miroslavstastny miroslavstastny commented Jun 18, 2019

Closes #1411.
A Toolbar item can now have a menu:

image

API

Following props were added to the ToolbarItem:

  • menu - depending on kind either shorthand for ToolbarMenuItem or ToolbarMenuDivider, each Toolbar Menu Item:
    • can have content and icon
    • can be active and disabled
    • has onClick, onFocus and onBlur callback
  • menuOpen - boolean, the menu is rendered if true.
  • onMenuOpenChange - callback to request menuOpen value change (the whole Toolbar is controlled component, parent must handle its state).

Known Limitations

  • accessibility to be handled separately

  • no styles for active (no redlines)

  • no submenu support (out of scope)

  • changelog

@codecov
Copy link

codecov bot commented Jun 19, 2019

Codecov Report

Merging #1518 into master will decrease coverage by 0.22%.
The diff coverage is 55.2%.

Impacted file tree graph

@@            Coverage Diff            @@
##           master   #1518      +/-   ##
=========================================
- Coverage   71.82%   71.6%   -0.23%     
=========================================
  Files         829     835       +6     
  Lines        6697    6789      +92     
  Branches     1917    1927      +10     
=========================================
+ Hits         4810    4861      +51     
- Misses       1882    1922      +40     
- Partials        5       6       +1
Impacted Files Coverage Δ
...es/react/src/components/Toolbar/ToolbarDivider.tsx 100% <ø> (ø) ⬆️
packages/react/src/index.ts 100% <ø> (ø) ⬆️
...gh-contrast/components/Toolbar/toolbarVariables.ts 0% <ø> (ø) ⬆️
...react/src/components/Toolbar/ToolbarRadioGroup.tsx 100% <ø> (ø) ⬆️
packages/react/src/components/Toolbar/Toolbar.tsx 89.47% <ø> (ø) ⬆️
...hemes/teams/components/Toolbar/toolbarVariables.ts 50% <ø> (ø) ⬆️
...eact/src/components/Toolbar/ToolbarMenuDivider.tsx 100% <100%> (ø)
...emes/teams/components/Toolbar/toolbarMenuStyles.ts 16.66% <16.66%> (ø)
...ams/components/Toolbar/toolbarMenuDividerStyles.ts 20% <20%> (ø)
...kages/react/src/components/Toolbar/ToolbarItem.tsx 59.09% <52%> (-14.83%) ⬇️
... and 10 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 21a5a50...aaf9f18. Read the comment docs.

* @param {SyntheticEvent} event - React's original SyntheticEvent.
* @param {object} data - All props and proposed value.
*/
onMenuOpenChange?: ComponentEventHandler<ToolbarItemProps>
Copy link
Member Author

Choose a reason for hiding this comment

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

Should we also hoist onOpenChange from Popup to here to have both on the same level?

Copy link
Member

Choose a reason for hiding this comment

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

Let's skip it for now, we still have an access to it via popup shorthand

<Ref innerRef={this.menuRef}>
<Popper align="start" position="above" targetRef={this.itemRef}>
{ToolbarMenu.create(menu, {
overrideProps: predefinedProps => ({
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
overrideProps: predefinedProps => ({
overrideProps: (predefinedProps: ToolbarItemProps) => ({

Copy link
Member

Choose a reason for hiding this comment

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

Are we going to move overrideProps to a class method?

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't think so. This is the only place where it is called, just once.

</ElementType>
)

if (!wrapper) {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if (!wrapper) {
if (_.isNil(wrapper)) {

Otherwise it will fail on empty string or 0

Copy link
Member Author

Choose a reason for hiding this comment

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

This is intentional. wrapper: false is valid.

Copy link
Member

Choose a reason for hiding this comment

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

_.isNil(wrapper) || wrapper === false?

@@ -135,6 +161,31 @@ class ToolbarItem extends UIComponent<WithAsProp<ToolbarItemProps>, ToolbarItemS
</ElementType>
)

const submenu = menuOpen ? (
Copy link
Contributor

Choose a reason for hiding this comment

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

what if the menu's items is an empty array?

Copy link
Member Author

Choose a reason for hiding this comment

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

Then in renders empty submenu, consistent with Menu. Do you think it is incorrect?

Copy link
Contributor

Choose a reason for hiding this comment

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

I would say if there are no menu items we don't need to render it. What the use case of rendering an empty menu?

Copy link
Member Author

Choose a reason for hiding this comment

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

Agree, but I think it is consumer's responsibility. menu can be array or object or element and we cannot check all. So I think it is better to be consistently dump than to try to be smart but inconsistent.

<>
<Ref innerRef={this.itemRef}>{renderedItem}</Ref>
{submenu}
</>
Copy link
Contributor

@sophieH29 sophieH29 Jun 25, 2019

Choose a reason for hiding this comment

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

based on our discussion and ARIA spec, toolbar button and menu should be wrapped in one div so then a screen reader will work correctly. @jurokapsiar correct me if I am wrong

Another aspect, when the focus is in menu and press ESC, the menu should get closed and focus should go on the button.
In theory, this type of keyboard event should be caught by a wrapper element, which wraps a toolbar button and menu and put a focus on the button. That seems for me the most logical way of doing it. Let me know what you think.

Copy link
Member Author

Choose a reason for hiding this comment

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

Makes sense. I added a wrapper slot, it is rendered only if there is a menu prop defined on the item, no matter whether the menu is open ( = rendered) or closed ( = not in dom).

@miroslavstastny miroslavstastny merged commit 23b34a9 into master Jun 26, 2019
@delete-merged-branch delete-merged-branch bot deleted the feat/toolbar-menu branch June 26, 2019 14:05
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Toolbar - menu
3 participants