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 (
+
+ )
+ }
+}
+
+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)
+})