Skip to content
This repository was archived by the owner on Mar 4, 2020. It is now read-only.
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

### BREAKING CHANGES
- Fix `firstFocusableSelector` in `FocusTrapZone` and `AutoFocusZone` @sophieH29 ([#1732](https://github.com/stardust-ui/react/pull/1732))
- Rename Popup `shouldTriggerBeTabbable` prop to `tabbableTrigger` @jurokapsiar ([#1696](https://github.com/stardust-ui/react/pull/1696))
- `StackableEventListener` is removed @layershifter ([#1755](https://github.com/stardust-ui/react/pull/1755))
- Rename `Tree` to `HierarchicalTree` @silviuavram ([#1752](https://github.com/stardust-ui/react/pull/1752))

Expand All @@ -36,6 +37,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- Export `call-blocked` icon to Teams theme @francescopalmiotto ([#1736](https://github.com/stardust-ui/react/pull/1736))
- Add support for component styles debugging @kuzhelov ([#1726](https://github.com/stardust-ui/react/pull/1726))
- Use FocusZone in selectable list @jurokapsiar ([#1757](https://github.com/stardust-ui/react/pull/1757))
- Add `MenuButton` component @jurokapsiar ([#1696](https://github.com/stardust-ui/react/pull/1696))
- Add `useEventListener` hook @layershifter ([#1755](https://github.com/stardust-ui/react/pull/1755))

### Documentation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const unsupportedComponents = [
'ItemLayout',
'Layout',
'List',
'MenuButton',
'Portal',
'Provider',
'RadioGroup',
Expand Down
5 changes: 3 additions & 2 deletions docs/src/components/DocsBehaviorRoot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,15 @@ class DocsBehaviorRoot extends React.Component<any, any> {
}

const { match } = this.props
const pageTitle = `${_.capitalize(match.params.name)} accessibility behaviors`
const componentName = _.upperFirst(_.camelCase(match.params.name))
const pageTitle = `${componentName} accessibility behaviors`
return (
<DocumentTitle title={pageTitle}>
<Segment styles={{ backgroundColor: 'transparent' }}>
<Header as="h1" aria-level={2} content={pageTitle} />

{behaviorMenuItems
.find(behavior => behavior.displayName === _.capitalize(match.params.name))
.find(behavior => behavior.displayName === componentName)
.variations.map((variation, keyValue) => (
<React.Fragment key={keyValue}>
<Segment
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Button } from '@stardust-ui/react'

const config: ScreenerTestsConfig = {
steps: [builder => builder.click(`.${Button.className}`).snapshot('RTL: Shows menuButton')],
}

export default config
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as React from 'react'
import { Button, MenuButton } from '@stardust-ui/react'

const MenuButtonExampleRtl = () => (
<MenuButton
trigger={<Button content="ا يجلبه إلينا الأس" />}
menu={['English text!', 'غالباً ونرفض الشعور']}
/>
)

export default MenuButtonExampleRtl
12 changes: 12 additions & 0 deletions docs/src/examples/components/MenuButton/Rtl/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import * as React from 'react'

import ComponentExample from 'docs/src/components/ComponentDoc/ComponentExample'
import NonPublicSection from 'docs/src/components/ComponentDoc/NonPublicSection'

const Rtl = () => (
<NonPublicSection title="Rtl">
<ComponentExample examplePath="components/MenuButton/Rtl/MenuButtonExample.rtl" />
</NonPublicSection>
)

export default Rtl
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { useBooleanKnob } from '@stardust-ui/docs-components'
import * as React from 'react'
import { Button, MenuButton } from '@stardust-ui/react'

const MenuButtonOpenExample = () => {
const [open, setOpen] = useBooleanKnob({ name: 'open', initialValue: true })

return (
<MenuButton
open={open}
onOpenChange={(e, { open }) => setOpen(open)}
trigger={<Button icon="expand" title="Open MenuButton" />}
menu={['1', '2', '3', { content: 'submenu', menu: ['4', '5'] }]}
/>
)
}

export default MenuButtonOpenExample
16 changes: 16 additions & 0 deletions docs/src/examples/components/MenuButton/State/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import * as React from 'react'

import ComponentExample from 'docs/src/components/ComponentDoc/ComponentExample'
import ExampleSection from 'docs/src/components/ComponentDoc/ExampleSection'

const State = () => (
<ExampleSection title="State">
<ComponentExample
title="Open"
description="Note that if MenuButton is controlled, then its 'open' prop value could be changed either by parent component, or by user actions (e.g. key press) - thus it is necessary to handle 'onOpenChange' event."
examplePath="components/MenuButton/State/MenuButtonExampleOpen"
/>
</ExampleSection>
)

export default State
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import * as React from 'react'
import { Alert, Button, MenuButton } from '@stardust-ui/react'

const items = ['1', '2', '3', { content: 'submenu', menu: { items: ['4', '5'] } }]

class MenuButtonOnElement extends React.Component {
state = { alert: false }

showAlert = () => {
this.setState({ alert: true })
setTimeout(() => this.setState({ alert: false }), 2000)
}

render() {
return (
<>
<MenuButton
contextMenu
trigger={
<div style={{ padding: '4rem', border: 'red dashed' }}>
<Button content="Random button" onClick={this.showAlert} />
</div>
}
menu={{ items }}
/>
{this.state.alert && <Alert warning content="Click!" />}
</>
)
}
}

export default MenuButtonOnElement
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import * as React from 'react'
import { Alert, Button, Flex, MenuButton } from '@stardust-ui/react'

class MenuButtonExampleOn extends React.Component {
state = { alert: false }

showAlert = () => {
this.setState({ alert: true })
setTimeout(() => this.setState({ alert: false }), 2000)
}

render() {
return (
<>
<Flex gap="gap.smaller">
<MenuButton
trigger={<Button icon="expand" content="Click" aria-label="Click button" />}
menu={['1', '2', '3', { content: 'submenu', menu: { items: ['4', '5'] } }]}
on="click"
/>
<MenuButton
trigger={<Button icon="expand" content="Hover" aria-label="Hover button" />}
menu={['1', '2', '3', { content: 'submenu', menu: { items: ['4', '5'] } }]}
on="hover"
/>
<MenuButton
trigger={<Button icon="expand" content="Focus" aria-label="Focus button" />}
menu={['1', '2', '3', { content: 'submenu', menu: { items: ['4', '5'] } }]}
on="focus"
/>
<MenuButton
trigger={
<Button
icon="expand"
content="Context"
aria-label="Context button"
onClick={this.showAlert}
/>
}
menu={['1', '2', '3', { content: 'submenu', menu: { items: ['4', '5'] } }]}
on="context"
/>
</Flex>
{this.state.alert && (
<Alert
warning
content="Right, you can still click the button! Right click opens the MenuButton."
/>
)}
</>
)
}
}

export default MenuButtonExampleOn
21 changes: 21 additions & 0 deletions docs/src/examples/components/MenuButton/Usage/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import * as React from 'react'

import ComponentExample from 'docs/src/components/ComponentDoc/ComponentExample'
import ExampleSection from 'docs/src/components/ComponentDoc/ExampleSection'

const Usage = () => (
<ExampleSection title="Usage">
<ComponentExample
title="Triggering menu on different actions"
description="A context menu can be triggered on click, hover, focus or context."
examplePath="components/MenuButton/Usage/MenuButtonExampleOn"
/>
<ComponentExample
title="Context menu"
description="A menu button can be attached to any element to create a context menu."
examplePath="components/MenuButton/Usage/MenuButtonExampleContextMenu"
/>
</ExampleSection>
)

export default Usage
15 changes: 15 additions & 0 deletions docs/src/examples/components/MenuButton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import * as React from 'react'

import Rtl from './Rtl'
import Usage from './Usage'
import State from './State'

const MenuButtonExamples = () => (
<>
<Usage />
<State />
<Rtl />
</>
)

export default MenuButtonExamples
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class PopupContextOnElement extends React.Component {
<Button content="Random button" onClick={this.showAlert} />
</div>
}
shouldTriggerBeTabbable={false}
tabbableTrigger={false}
content={contentWithButtons}
trapFocus
on="context"
Expand Down
18 changes: 17 additions & 1 deletion packages/react/src/components/Menu/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@ import { menuBehavior } from '../../lib/accessibility'
import { Accessibility } from '../../lib/accessibility/types'
import { ReactAccessibilityBehavior } from '../../lib/accessibility/reactTypes'
import { ComponentVariablesObject, ComponentSlotStylesPrepared } from '../../themes/types'
import { WithAsProp, ShorthandCollection, ShorthandValue, withSafeTypeForAs } from '../../types'
import {
WithAsProp,
ShorthandCollection,
ShorthandValue,
withSafeTypeForAs,
ComponentEventHandler,
} from '../../types'
import MenuDivider from './MenuDivider'
import { IconProps } from '../Icon/Icon'

Expand Down Expand Up @@ -53,6 +59,14 @@ export interface MenuProps extends UIComponentProps, ChildrenComponentProps {
/** Shorthand array of props for Menu. */
items?: ShorthandCollection<MenuItemProps, MenuShorthandKinds>

/**
* Called when a panel title is clicked.
*
* @param {SyntheticEvent} event - React's original SyntheticEvent.
* @param {object} data - All item props.
*/
onItemClick?: ComponentEventHandler<MenuItemProps>

/** A menu can adjust its appearance to de-emphasize its contents. */
pills?: boolean

Expand Down Expand Up @@ -106,6 +120,7 @@ class Menu extends AutoControlledComponent<WithAsProp<MenuProps>, MenuState> {
fluid: PropTypes.bool,
iconOnly: PropTypes.bool,
items: customPropTypes.collectionShorthandWithKindProp(['divider', 'item']),
onItemClick: PropTypes.func,
pills: PropTypes.bool,
pointing: PropTypes.oneOfType([PropTypes.bool, PropTypes.oneOf(['start', 'end'])]),
primary: customPropTypes.every([customPropTypes.disallow(['secondary']), PropTypes.bool]),
Expand All @@ -132,6 +147,7 @@ class Menu extends AutoControlledComponent<WithAsProp<MenuProps>, MenuState> {

this.trySetState({ activeIndex: index })

_.invoke(this.props, 'onItemClick', e, itemProps)
_.invoke(predefinedProps, 'onClick', e, itemProps)
},
onActiveChanged: (e, props) => {
Expand Down
Loading