diff --git a/docs/src/examples/components/ContextMenu/Types/ContextMenuExample.shorthand.tsx b/docs/src/examples/components/ContextMenu/Types/ContextMenuExample.shorthand.tsx new file mode 100644 index 0000000000..1452c253c4 --- /dev/null +++ b/docs/src/examples/components/ContextMenu/Types/ContextMenuExample.shorthand.tsx @@ -0,0 +1,34 @@ +import React from 'react' +import { ContextMenu } from '@stardust-ui/react' + +const items = [ + { + key: 'show', + content: 'Show in channel', + icon: 'search', + divider: true, + menu: { + items: [ + { key: '1', content: 'item1' }, + { + key: '2', + content: 'item2', + menu: { items: [{ key: '1', content: 'item1' }, { key: '2', content: 'item2' }] }, + }, + ], + }, + }, + { key: 'move', content: 'Move to collection', icon: 'arrow right' }, + { key: 'copy', content: 'Copy to collection', icon: 'copy' }, + { key: 'remove', content: 'Remove', icon: 'delete', divider: true }, + { key: 'edit', content: 'Edit', icon: 'edit' }, + { key: 'getlink', content: 'Get link', icon: 'file' }, +] + +const callback = () => { + alert('ContextMenu callback invoked...') +} + +const ContextMenuExample = () => + +export default ContextMenuExample diff --git a/docs/src/examples/components/ContextMenu/Types/index.tsx b/docs/src/examples/components/ContextMenu/Types/index.tsx new file mode 100644 index 0000000000..3338b386a1 --- /dev/null +++ b/docs/src/examples/components/ContextMenu/Types/index.tsx @@ -0,0 +1,15 @@ +import React from 'react' +import ComponentExample from 'docs/src/components/ComponentDoc/ComponentExample' +import ExampleSection from 'docs/src/components/ComponentDoc/ExampleSection' + +const Types = () => ( + + + +) + +export default Types diff --git a/docs/src/examples/components/ContextMenu/index.tsx b/docs/src/examples/components/ContextMenu/index.tsx new file mode 100644 index 0000000000..15cfb6ef1a --- /dev/null +++ b/docs/src/examples/components/ContextMenu/index.tsx @@ -0,0 +1,10 @@ +import React from 'react' +import Types from './Types' + +const ContextMenuExamples = () => ( +
+ +
+) + +export default ContextMenuExamples diff --git a/src/components/ContextMenu/ContextMenu.tsx b/src/components/ContextMenu/ContextMenu.tsx new file mode 100644 index 0000000000..79081e678d --- /dev/null +++ b/src/components/ContextMenu/ContextMenu.tsx @@ -0,0 +1,83 @@ +import * as _ from 'lodash' +import * as PropTypes from 'prop-types' +import * as React from 'react' +import ReactNode = React.ReactNode +import { UIComponent, customPropTypes, IRenderResultConfig } from '../../lib' +import { ComponentVariablesInput, ComponentPartStyle } from '../../../types/theme' +import { Extendable } from '../../../types/utils' +import Menu, { MenuItem } from '../Menu' +// import List, { ListItem } from '../List' +// import Popup from '../Popup' +export interface IContextMenuProps { + as?: any + className?: string + styles?: ComponentPartStyle + variables?: ComponentVariablesInput +} + +/** + * A contextMenu. + * @accessibility This is example usage of the accessibility tag. + * This should be replaced with the actual description after the PR is merged + */ +class ContextMenu extends UIComponent, any> { + static displayName = 'ContextMenu' + + static className = 'ui-contextmenu' + + static propTypes = { + /** An element type to render as (string or function). */ + as: customPropTypes.as, + + /** Additional classes. */ + className: PropTypes.string, + + /** The tree of menu containing submenus and it's submenus and so on. */ + items: PropTypes.arrayOf(PropTypes.object), + + /** Function passed which needs to be invoked when the menuitem has no submenu. */ + onItemClick: PropTypes.func, + + /** Custom styles to be applied for component. */ + styles: PropTypes.oneOfType([PropTypes.object, PropTypes.func]), + + /** Custom variables to be applied for component. */ + variables: PropTypes.oneOfType([PropTypes.object, PropTypes.func]), + } + + static defaultProps = { + as: 'div', + } + + renderComponent({ ElementType, classes, rest }: IRenderResultConfig): ReactNode { + return ( + + {this.renderItems()} + + ) + } + + renderItems = () => { + const { items } = this.props + return ( + + {_.map(items, (item, index) => + MenuItem.create(item, { + defaultProps: { + index, + styles: { + color: 'rgba(37,36,36,0.75)', + fontFamily: 'Segoe UI', + ...(item.divider && { + borderBottom: '2px solid #F3F2F1', + }), + }, + }, + }), + )} + + ) + } +} + +export default ContextMenu diff --git a/src/components/ContextMenu/index.tsx b/src/components/ContextMenu/index.tsx new file mode 100644 index 0000000000..98774c125c --- /dev/null +++ b/src/components/ContextMenu/index.tsx @@ -0,0 +1 @@ +export { default } from './ContextMenu' diff --git a/src/index.ts b/src/index.ts index 28c50034b1..e081d7257f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -10,6 +10,7 @@ export { ButtonGroup } from './components/Button' export { default as Chat } from './components/Chat' export { ChatItem } from './components/Chat' export { ChatMessage } from './components/Chat' +export { default as ContextMenu } from './components/ContextMenu' export { default as Divider } from './components/Divider' export { default as Grid } from './components/Grid' export { default as Header } from './components/Header' diff --git a/src/themes/teams/componentStyles.ts b/src/themes/teams/componentStyles.ts index b136c379f4..0611659675 100644 --- a/src/themes/teams/componentStyles.ts +++ b/src/themes/teams/componentStyles.ts @@ -13,6 +13,8 @@ export { default as Chat } from './components/Chat/chatStyles' export { default as ChatItem } from './components/Chat/chatItemStyles' export { default as ChatMessage } from './components/Chat/chatMessageStyles' +export { default as ContextMenu } from './components/ContextMenu/contextMenuStyles' + export { default as Divider } from './components/Divider/dividerStyles' export { default as Header } from './components/Header/headerStyles' diff --git a/src/themes/teams/componentVariables.ts b/src/themes/teams/componentVariables.ts index df10e0a02a..205f616813 100644 --- a/src/themes/teams/componentVariables.ts +++ b/src/themes/teams/componentVariables.ts @@ -13,6 +13,8 @@ export { default as ChatItem } from './components/Chat/chatItemVariables' export { default as ChatMessage } from './components/Chat/chatMessageVariables' +export { default as ContextMenu } from './components/ContextMenu/contextMenuVariables' + export { default as Divider } from './components/Divider/dividerVariables' export { default as Grid } from './components/Grid/gridVariables' diff --git a/src/themes/teams/components/ContextMenu/contextMenuStyles.tsx b/src/themes/teams/components/ContextMenu/contextMenuStyles.tsx new file mode 100644 index 0000000000..6d771952cd --- /dev/null +++ b/src/themes/teams/components/ContextMenu/contextMenuStyles.tsx @@ -0,0 +1,19 @@ +import { IContextMenuVariables } from './contextMenuVariables' +import { IComponentPartStylesInput, ICSSInJSStyle } from '../../../../../types/theme' +import { IContextMenuProps } from '../../../../components/ContextMenu/ContextMenu' + +const contextMenuStyles: IComponentPartStylesInput = { + root: ({ variables }): ICSSInJSStyle => { + const { height, width, padding, border } = variables + const styles = { + height, + width, + padding, + border, + } + + return styles + }, +} + +export default contextMenuStyles diff --git a/src/themes/teams/components/ContextMenu/contextMenuVariables.tsx b/src/themes/teams/components/ContextMenu/contextMenuVariables.tsx new file mode 100644 index 0000000000..d35cbe2a10 --- /dev/null +++ b/src/themes/teams/components/ContextMenu/contextMenuVariables.tsx @@ -0,0 +1,13 @@ +export interface IContextMenuVariables { + height?: string + width?: string + padding?: string + border?: string +} + +export default (): IContextMenuVariables => ({ + height: '100%', + width: '100%', + padding: '0', + // border: '1px solid #eeeeee', +}) diff --git a/test/specs/components/ContextMenu/ContextMenu-test.tsx b/test/specs/components/ContextMenu/ContextMenu-test.tsx new file mode 100644 index 0000000000..22d873add9 --- /dev/null +++ b/test/specs/components/ContextMenu/ContextMenu-test.tsx @@ -0,0 +1,7 @@ +import { isConformant } from 'test/specs/commonTests' + +import ContextMenu from 'src/components/ContextMenu' + +describe('ContextualMenu', () => { + isConformant(ContextMenu) +})