diff --git a/docs/src/examples/components/Menu/Types/MenuExampleVerticalWithSubmenu.shorthand.tsx b/docs/src/examples/components/Menu/Types/MenuExampleVerticalWithSubmenu.shorthand.tsx
new file mode 100644
index 0000000000..1e8dae4410
--- /dev/null
+++ b/docs/src/examples/components/Menu/Types/MenuExampleVerticalWithSubmenu.shorthand.tsx
@@ -0,0 +1,39 @@
+import React from 'react'
+import { Menu, Provider } from '@stardust-ui/react'
+
+const items = [
+ {
+ key: 'editorials',
+ content: 'Editorials',
+ menu: {
+ items: [
+ { key: '1', content: 'item1' },
+ {
+ key: '2',
+ content: 'item2',
+ menu: { items: [{ key: '1', content: 'item1' }, { key: '2', content: 'item2' }] },
+ },
+ ],
+ },
+ },
+ { key: 'review', content: 'Reviews' },
+ { key: 'events', content: 'Upcoming Events' },
+]
+
+const MenuExampleVerticalWithSubmenu = () => (
+
+
+
+)
+
+export default MenuExampleVerticalWithSubmenu
diff --git a/docs/src/examples/components/Menu/Types/MenuExampleWithSubmenu.shorthand.tsx b/docs/src/examples/components/Menu/Types/MenuExampleWithSubmenu.shorthand.tsx
new file mode 100644
index 0000000000..187296aa78
--- /dev/null
+++ b/docs/src/examples/components/Menu/Types/MenuExampleWithSubmenu.shorthand.tsx
@@ -0,0 +1,57 @@
+import React from 'react'
+import { Menu, Provider } from '@stardust-ui/react'
+
+const items = [
+ {
+ key: 'editorials',
+ content: 'Editorials',
+ menu: {
+ items: [
+ { key: '1', content: 'item1' },
+ {
+ key: '2',
+ content: 'item2',
+ menu: { items: [{ key: '1', content: 'item1' }, { key: '2', content: 'item2' }] },
+ },
+ {
+ key: '3',
+ content: 'item3',
+ menu: { items: [{ key: '1', content: 'item1' }, { key: '2', content: 'item2' }] },
+ },
+ ],
+ },
+ },
+ {
+ key: 'review',
+ content: 'Reviews',
+ menu: {
+ items: [
+ { key: '1', content: 'item1' },
+ {
+ key: '2',
+ content: 'item2',
+ menu: { items: [{ key: '1', content: 'item1' }, { key: '2', content: 'item2' }] },
+ },
+ ],
+ },
+ },
+ { key: 'events', content: 'Upcoming Events' },
+]
+
+const MenuExampleWithSubMenu = () => (
+
+
+
+)
+
+export default MenuExampleWithSubMenu
diff --git a/docs/src/examples/components/Menu/Types/index.tsx b/docs/src/examples/components/Menu/Types/index.tsx
index 8ce62a8f8d..a589b627a9 100644
--- a/docs/src/examples/components/Menu/Types/index.tsx
+++ b/docs/src/examples/components/Menu/Types/index.tsx
@@ -19,6 +19,16 @@ const Types = () => (
description="A vertical menu displays elements vertically."
examplePath="components/Menu/Types/MenuExampleVertical"
/>
+
+
)
diff --git a/src/components/Menu/Menu.tsx b/src/components/Menu/Menu.tsx
index b92919d8fa..0aea78c915 100644
--- a/src/components/Menu/Menu.tsx
+++ b/src/components/Menu/Menu.tsx
@@ -121,10 +121,22 @@ class Menu extends AutoControlledComponent, any> {
static Item = MenuItem
+ state = {
+ submenuOpen: false,
+ activeIndex: '',
+ }
+
handleItemOverrides = predefinedProps => ({
onClick: (e, itemProps) => {
const { index } = itemProps
+ this.setState(prev => {
+ if (prev.activeIndex === index) {
+ return { submenuOpen: !prev.submenuOpen }
+ }
+ return { submenuOpen: true }
+ })
+
this.trySetState({ activeIndex: index })
_.invoke(predefinedProps, 'onClick', e, itemProps)
@@ -133,7 +145,7 @@ class Menu extends AutoControlledComponent, any> {
renderItems = (variables: ComponentVariablesObject) => {
const { iconOnly, items, pills, pointing, renderItem, type, underlined, vertical } = this.props
- const { activeIndex } = this.state
+ const { activeIndex, submenuOpen } = this.state
return _.map(items, (item, index) =>
MenuItem.create(item, {
@@ -147,6 +159,10 @@ class Menu extends AutoControlledComponent, any> {
vertical,
index,
active: parseInt(activeIndex, 10) === index,
+ ...(activeIndex === index && { submenuOpen }),
+ ...(item.menu && {
+ styles: { position: 'relative' },
+ }),
},
overrideProps: this.handleItemOverrides,
render: renderItem,
diff --git a/src/components/Menu/MenuItem.tsx b/src/components/Menu/MenuItem.tsx
index 5691f45a8e..bdce6028e2 100644
--- a/src/components/Menu/MenuItem.tsx
+++ b/src/components/Menu/MenuItem.tsx
@@ -5,6 +5,8 @@ import * as React from 'react'
import { childrenExist, createShorthandFactory, customPropTypes, UIComponent } from '../../lib'
import Icon from '../Icon'
+import Menu from '../Menu'
+// import Provider from '../Provider'
import { menuItemBehavior } from '../../lib/accessibility'
import { Accessibility, AccessibilityActionHandlers } from '../../lib/accessibility/interfaces'
import IsFromKeyboard from '../../lib/isFromKeyboard'
@@ -29,10 +31,12 @@ export interface IMenuItemProps {
icon?: ShorthandValue
iconOnly?: boolean
index?: number
+ menu?: any
onClick?: ComponentEventHandler
pills?: boolean
pointing?: boolean | 'start' | 'end'
renderIcon?: ShorthandRenderFunction
+ submenuOpen?: boolean
type?: 'primary' | 'secondary'
underlined?: boolean
vertical?: boolean
@@ -82,6 +86,9 @@ class MenuItem extends UIComponent, IMenuItemState> {
/** MenuItem index inside Menu. */
index: PropTypes.number,
+ /** MenuItem's submenu */
+ menu: PropTypes.any,
+
/**
* Called on click. When passed, the component will render as an `a`
* tag by default instead of a `div`.
@@ -100,6 +107,9 @@ class MenuItem extends UIComponent, IMenuItemState> {
*/
pointing: PropTypes.oneOfType([PropTypes.bool, PropTypes.oneOf(['start', 'end'])]),
+ /** */
+ submenuOpen: PropTypes.bool,
+
/** The menu can have primary or secondary type */
type: PropTypes.oneOf(['primary', 'secondary']),
@@ -136,7 +146,7 @@ class MenuItem extends UIComponent, IMenuItemState> {
state = IsFromKeyboard.initial
renderComponent({ ElementType, classes, accessibility, rest }) {
- const { children, content, icon, renderIcon } = this.props
+ const { children } = this.props
return (
, IMenuItemState> {
{...accessibility.keyHandlers.root}
{...rest}
>
- {childrenExist(children) ? (
- children
- ) : (
-
- {icon &&
- Icon.create(this.props.icon, {
- defaultProps: { xSpacing: !!content ? 'after' : 'none' },
- render: renderIcon,
- })}
- {content}
-
- )}
+ {childrenExist(children) ? children : this.renderMenuItem(accessibility, classes)}
)
}
-
+ private renderMenuItem = (accessibility, classes) => {
+ const { content, icon, renderIcon, menu, type, vertical, submenuOpen } = this.props
+ return (
+ <>
+
+ {icon &&
+ Icon.create(this.props.icon, {
+ defaultProps: { xSpacing: !!content ? 'after' : 'none' },
+ render: renderIcon,
+ })}
+ {content}
+
+ {menu && submenuOpen ? (
+
+ ) : null}
+ >
+ )
+ }
protected actionHandlers: AccessibilityActionHandlers = {
performClick: event => this.handleClick(event),
}
diff --git a/src/themes/teams/components/Menu/menuVariables.ts b/src/themes/teams/components/Menu/menuVariables.ts
index d299a5356e..95bfc59ee4 100644
--- a/src/themes/teams/components/Menu/menuVariables.ts
+++ b/src/themes/teams/components/Menu/menuVariables.ts
@@ -24,7 +24,7 @@ export interface IMenuVariables {
export default (siteVars: any): IMenuVariables => {
return {
defaultColor: siteVars.gray02,
- defaultBackgroundColor: 'transparent',
+ defaultBackgroundColor: '#FFF',
defaultActiveColor: siteVars.black,
defaultActiveBackgroundColor: siteVars.gray10,