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

Commit 5324ba9

Browse files
jurokapsiarmnajdova
authored andcommitted
feat(menu): Submenu (#539)
* feat(menuItem: add menu prop) * Only one submenu open at a time * Fix bug: submenu noe closes on clicking a menuItem with no submenu * Code cleanup * Remove the activeIndex prop passed to the menuItem * Remove Popup and implement submenu without it * initial keyboard support * left/right arrow handling * simplify keyboard handlers * -fixed import in the MenuItem * -added submenuIndicator -small fixes in the styles and the way the submenu is generated * -clicking on leaf element should close the submenus (the same should be done for enter/space) -applied consistent (left-right) navigation for horizontal menu and (up-down) navigation for vertical menu * -implemented outside click to close all menus -implemented enter key on leaf menu item to close the menu * -fixed import * -refactored MenuItem handlers - fixed issues -removed onClick handler for the Menu (not necessary for now) -added onKeyDown in the creation of the MenuItem in the Menu component for handling the action prop * -added setActiveIndex callback and removed onKeyDown in the creation of MenuItems in the Menu component * -right arrow key is closing the submenus and goes to the next element if the menu is horizontal, or is focusing the first MenuItem if it is vertical * -handled left arrow key * -changed ref -focus trap wip * -added Ref component instead of using the itemRef on the ElementType -removed subscription for focus * -fixes * -moved ref //TODO: figure out tests failing * -close menu on outside focus * -improved comments * -fixed escape key not focusing the active element -changed parentRef to inSubmenu boolean * -fixing key problems -added dependency for generating id * -refactored submenuRef element * fix broken tests * -added comments in the tests -changed the submenuDomElement so submenuRef * -renamed inSubmenu to submenu prop in the Menu * -fixed with the auto-controlled prop in the Menu * -added state interface in the Menu -improved menu variables' names * -fixed variables in examples * -remove state initialization in the MenuItem component * -added new handler for escape -changed submenu examples titles * -refactored conditions using doesNodeContainClick * -renamed submenu* props to menu in the MenuItem component -changed setActiveIndex with onActiveChanged -introduced different styles for the hovering vs active elements * -improved example -fixed issue with the condition for the active prop * -exported MenuState -added correct typings to the menuStyles * -fixed underlined active + hovered style * -fixed border corner clipped by adding custom styles for the first child menu items and the last child menu items in vertical menu * -addressed comments on PR * chore: prepare release 0.15.0 [ci skip] * 0.15.0 * fix(Prototype): Fix Popover prototype after breaking changes (#623) * chore: cache results of vulnerability scans (#621) * implement caching strategy * adjust file name of scan marker * add yarn lock hash to marker file name * add change to build config * fix dir name in build config * improve caching strategy * just restore cache * temporary remove lint and tests * try * fix caching strategy * try * try * try * try epoch * create file on scan * return lint and test steps * introduce comment for the caching approach taken * remove unnecessary function * simplify expression for marker file name * feat(text): color prop (#597) * feat(text): color prop * addressed comments * changelog * amended changelog * made text color override other props that change color * feat(header): header and header description color prop (#628) * feat(header): header and header description color prop * changelog * fixed examples * addressed PR comments * fix(Popup): allow to 'detach' from trigger and RTL adjustments (#612) * introduce offset prop * correct description of supported values * update changelog * introduce fix * ensure RTL is properly applied to complex offset expressions * rename method to make logic more expressive * add unit tests * remove unnecessary grid props from offset example * update changelog * fix(SelectableList): Items in list should be selectable (#566) * Reflect which item is selected in list * Make list derived from autocontrolled component * small fix * Update ListExampleSelection.tsx * Update ListExampleSelection.shorthand.tsx * Small improvement * Rename *ItemIndex -> *Index * Names refactoring * Minor improvements * update changelog * Add onSelectedIndexChange * Add some tests * Small improvements afer CR * Small improvements afer CR * Small improvements afer CR * create focus handler when List is constructed * fix changelog * changelog * docs(Examples): allow to use TS in examples (#617) * docs(Examples): allow to use TS in examples * add jsdoc * fix typo * rename file * add comment * `createExample` to `createExampleSourceCode` * rework with `path.relative()` * remove JSON files on remove tsx * create getRelativePathToSource function * -updated changelog * -updated changelog * -updated changelog with breaking changes -removed TODO comment * -fixed imports in examples
1 parent c9cfb51 commit 5324ba9

File tree

19 files changed

+500
-82
lines changed

19 files changed

+500
-82
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
1717

1818
## [Unreleased]
1919

20+
### BREAKING CHANGES
21+
- renamed Teams theme menu variables the contains props names as prefixes @mnajdova ([#539](https://github.com/stardust-ui/react/pull/539))
22+
2023
### Fixes
2124
- Ensure `Popup` properly flips values of `offset` prop in RTL @kuzhelov ([#612](https://github.com/stardust-ui/react/pull/612))
2225
- Fix `List` - items should be selectable @sophieH29 ([#566](https://github.com/stardust-ui/react/pull/566))
@@ -25,6 +28,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
2528
- Add `color` prop to `Text` component @Bugaa92 ([#597](https://github.com/stardust-ui/react/pull/597))
2629
- Add `color` prop to `Header` and `HeaderDescription` components @Bugaa92 ([#628](https://github.com/stardust-ui/react/pull/628))
2730
- Add and export compose icons in Teams theme @joheredi ([#639](https://github.com/stardust-ui/react/pull/639))
31+
- Add `menu` prop to `MenuItem` @mnajdova ([#539](https://github.com/stardust-ui/react/pull/539))
2832

2933
<!--------------------------------[ v0.15.0 ]------------------------------- -->
3034
## [v0.15.0](https://github.com/stardust-ui/react/tree/v0.15.0) (2018-12-17)

docs/src/components/CodeSnippet.tsx

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import * as _ from 'lodash'
21
import * as React from 'react'
32

43
import formatCode from '../utils/formatCode'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import * as React from 'react'
2+
import { Menu } from '@stardust-ui/react'
3+
4+
const items = [
5+
{
6+
key: 'editorials',
7+
content: 'Editorials',
8+
menu: {
9+
items: [
10+
{ key: '1', content: 'item1' },
11+
{
12+
key: '2',
13+
content: 'item2',
14+
menu: { items: [{ key: '1', content: 'item1' }, { key: '2', content: 'item2' }] },
15+
},
16+
],
17+
},
18+
},
19+
{ key: 'review', content: 'Reviews' },
20+
{ key: 'events', content: 'Upcoming Events' },
21+
]
22+
23+
const MenuExampleVerticalWithSubmenu = () => <Menu defaultActiveIndex={0} vertical items={items} />
24+
25+
export default MenuExampleVerticalWithSubmenu
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import * as React from 'react'
2+
import { Menu } from '@stardust-ui/react'
3+
4+
const items = [
5+
{
6+
key: 'editorials',
7+
content: 'Editorials',
8+
menu: {
9+
items: [
10+
{ key: '1', content: 'item1' },
11+
{
12+
key: '2',
13+
content: 'item2',
14+
menu: { items: [{ key: '1', content: 'item2.1' }, { key: '2', content: 'item2.2' }] },
15+
},
16+
{
17+
key: '3',
18+
content: 'item3',
19+
menu: { items: [{ key: '1', content: 'item3.1' }, { key: '2', content: 'item3.2' }] },
20+
},
21+
],
22+
},
23+
},
24+
{
25+
key: 'review',
26+
content: 'Reviews',
27+
menu: {
28+
items: [
29+
{ key: '1', content: 'item1' },
30+
{
31+
key: '2',
32+
content: 'item2',
33+
menu: { items: [{ key: '1', content: 'item2.1' }, { key: '2', content: 'item2.2' }] },
34+
},
35+
],
36+
},
37+
},
38+
{ key: 'events', content: 'Upcoming Events' },
39+
]
40+
41+
const MenuExampleWithSubMenu = () => <Menu defaultActiveIndex={0} items={items} />
42+
43+
export default MenuExampleWithSubMenu

docs/src/examples/components/Menu/Types/index.tsx

+6
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ const Types = () => (
1919
description="A vertical menu displays elements vertically."
2020
examplePath="components/Menu/Types/MenuExampleVertical"
2121
/>
22+
<ComponentExample
23+
title="Menu with submenus"
24+
description="A menu can have submenus."
25+
examplePath="components/Menu/Types/MenuExampleWithSubmenu"
26+
/>
27+
<ComponentExample examplePath="components/Menu/Types/MenuExampleVerticalWithSubmenu" />
2228
</ExampleSection>
2329
)
2430

docs/src/examples/components/Menu/Variations/MenuExampleIconOnlyPrimaryInverted.shorthand.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ const MenuExampleIconOnlyPrimaryInverted = () => (
1414
items={items}
1515
primary
1616
variables={siteVars => ({
17-
defaultColor: siteVars.gray06,
18-
defaultBackgroundColor: siteVars.brand,
19-
typePrimaryActiveBorderColor: siteVars.white,
17+
color: siteVars.gray06,
18+
backgroundColor: siteVars.brand,
19+
primaryActiveBorderColor: siteVars.white,
2020
})}
2121
/>
2222
)

src/components/Menu/Menu.tsx

+30-6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import * as React from 'react'
55
import {
66
AutoControlledComponent,
77
childrenExist,
8+
createShorthandFactory,
89
customPropTypes,
910
UIComponentProps,
1011
ChildrenComponentProps,
@@ -60,12 +61,19 @@ export interface MenuProps extends UIComponentProps, ChildrenComponentProps {
6061

6162
/** A vertical menu displays elements vertically. */
6263
vertical?: boolean
64+
65+
/** Indicates whether the menu is submenu. */
66+
submenu?: boolean
67+
}
68+
69+
export interface MenuState {
70+
activeIndex?: number | string
6371
}
6472

6573
/**
6674
* A menu displays grouped navigation actions.
6775
*/
68-
class Menu extends AutoControlledComponent<Extendable<MenuProps>, any> {
76+
class Menu extends AutoControlledComponent<Extendable<MenuProps>, MenuState> {
6977
static displayName = 'Menu'
7078

7179
static className = 'ui-menu'
@@ -88,6 +96,7 @@ class Menu extends AutoControlledComponent<Extendable<MenuProps>, any> {
8896
secondary: customPropTypes.every([customPropTypes.disallow(['primary']), PropTypes.bool]),
8997
underlined: PropTypes.bool,
9098
vertical: PropTypes.bool,
99+
submenu: PropTypes.bool,
91100
}
92101

93102
static defaultProps = {
@@ -107,6 +116,15 @@ class Menu extends AutoControlledComponent<Extendable<MenuProps>, any> {
107116

108117
_.invoke(predefinedProps, 'onClick', e, itemProps)
109118
},
119+
onActiveChanged: (e, props) => {
120+
const { index, active } = props
121+
if (active) {
122+
this.trySetState({ activeIndex: index })
123+
} else if (this.state.activeIndex === index) {
124+
this.trySetState({ activeIndex: null })
125+
}
126+
_.invoke(predefinedProps, 'onActiveChanged', e, props)
127+
},
110128
})
111129

112130
renderItems = (variables: ComponentVariablesObject) => {
@@ -119,11 +137,14 @@ class Menu extends AutoControlledComponent<Extendable<MenuProps>, any> {
119137
secondary,
120138
underlined,
121139
vertical,
140+
submenu,
122141
} = this.props
123142
const { activeIndex } = this.state
124143

125-
return _.map(items, (item, index) =>
126-
MenuItem.create(item, {
144+
return _.map(items, (item, index) => {
145+
const active =
146+
(typeof activeIndex === 'string' ? parseInt(activeIndex, 10) : activeIndex) === index
147+
return MenuItem.create(item, {
127148
defaultProps: {
128149
iconOnly,
129150
pills,
@@ -134,11 +155,12 @@ class Menu extends AutoControlledComponent<Extendable<MenuProps>, any> {
134155
variables,
135156
vertical,
136157
index,
137-
active: parseInt(activeIndex, 10) === index,
158+
active,
159+
inSubmenu: submenu,
138160
},
139161
overrideProps: this.handleItemOverrides,
140-
}),
141-
)
162+
})
163+
})
142164
}
143165

144166
renderComponent({ ElementType, classes, accessibility, variables, rest }) {
@@ -151,4 +173,6 @@ class Menu extends AutoControlledComponent<Extendable<MenuProps>, any> {
151173
}
152174
}
153175

176+
Menu.create = createShorthandFactory(Menu, 'items')
177+
154178
export default Menu

0 commit comments

Comments
 (0)