React-contexify-ext
Add a context menu to your react application with ease !
- Demo
- Installation
- Features
- How it works ?
- Add a context menu to a table
- Api
- Migration from v1 to v2
- Release Notes
Demo
Live demo here
Installation
$ yarn add react-contexify-ext
or
$ npm install --save react-contexify-ext
You also need to include the css file provided. Otherwise it wont work as expected.
Style Loader :
1998 Script tag :
<link rel="stylesheet" href="/dist/ReactContexify.min.css"/>
Features
- The context menu never leave the visible screen. You can reduce the window to check the behavior
- The callback provide an access to the wrapped component
- One menu can be use for multiple targets
- Create as many contextual menu as you want, as long as the id is unique
- Easily customizable. Theme are split into different sass file. Fifteen line of code can be enough to create a theme
- Don't rely on
findDOMNode
How it works ?
Create your menu
; { // targetNode refer to the html node on which the menu is triggered console; //ref will be the mounted instance of the wrapped component //If you wrap more than one component, ref will be an array of ref console; // Additionnal data props passed down to the `Item` console;} // create your menu firstconst MyAwesomeMenu = <ContextMenu id='menu_id'> <Item leftIcon=<IconFont className="fa fa-plus" /> onClick=onClick> Add </Item> <Item leftIcon=<IconFont className="material-icons">remove_circle</IconFont> onClick=onClick> Remove </Item> <Item><IconFont className="fa fa-scissors" />cut</Item> <Separator/> <Item disabled> Paste </Item> </ContextMenu>;
Define which component can display the menu
; //wrap your component with the `ContextMenuProvider` const Foo = <ContextMenuProvider id="menu_id">bar</ContextMenuProvider>;const Bar = <ContextMenuProvider id="menu_id">baz</ContextMenuProvider>; // or you can use the curried function to add the same menu for many components, it's up to you const addContextMenu = ; const Foo = ;const Bar = ;
All together
; ;;; const App = <div> <Foo /> <Bar /> <MyAwesomeMenu/> </div> ReactDOM;
Add a context menu to a table
; //You need to use a tr as a render tag otherwise your browser console will bleed !const Tr = <ContextMenuProvider id="menu_id" renderTag="tr"> <td>propscel1</td> <td>propscel2</td> </ContextMenuProvider>; { return <table> <thead> <tr> <th>Cel 1</th> <th>Cel 2</th> </tr> </thead> <tbody> <Tr cel1="lorem" cel2="ipsum" /> <Tr cel1="foo" cel2="bar" /> </tbody> </table> }
Api
ContextMenu (Type : React Component)
Props | Type | Default | Required | Possible Value | Description |
---|---|---|---|---|---|
id | string|int | - | ✓ | - | Used to identify the corresponding menu |
children | Item |null |
- | ✓ | - | Menu item |
theme | string | ✘ | light | dark | Theme is appended to react-contexify__theme--${given theme} |
|
animation | string | ✘ | fade | flip | pop | zoom | Animation is appended to .react-contexify__will-enter--${given animation} |
You can set built-in theme and animation using ContextMenu constant as follow :
<ContextMenu id="foo" theme={ContextMenu.THEME.dark} animation={ContextMenu.ANIMATION.pop}> ... </ContextMenu>
Item (Type : React Component)
Props | Type | Default | Required | Description |
---|---|---|---|---|
children | node | - | ✓ | Any valid node to render(string, react component...) |
leftIcon | node | ✘ | Any valid node to render(string, react component...) | |
rightIcon | node | ✘ | Any valid node to render(string, react component...) | |
disabled | bool | false | ✘ | Disable the item |
onClick | function | ✘ | Callback when the item is clicked | |
data | any | ✘ | Additional data that will be passed to the callback |
onClick
When an you select an Item your callback will receive 3 parameters: targetNode
, refs
, data
.
- if you wrap a single react component refs will be the mounted instance of the wrapped component
- If you wrap more than one component refs will be an array of ref
ref will be an instance of the react component only if the component is declared as a class
If you use any flux store like redux or mobx stick with it.
For more details about ref please read this
Separator (Type : React Component)
Don't expect any props. It's just a separator xD.
<Separator />
IconFont (Type : React Component)
Props | Type | Default | Required | Description |
---|---|---|---|---|
children | node | - | ✘ | Menu item |
className | string | ✘ | Additional className | |
style | string | ✘ | Additional style |
The icon font render a i tag.
//example with Font Awesome <IconFont className="fa fa-trash" />//example with material icons<IconFont className="material-icons">remove_circle</IconFont>
ContextMenuProvider (Type : React Component)
Props | Type | Default | Required | Possible Value | Description |
---|---|---|---|---|---|
id | string or int | - | ✓ | - | Id used to map your component to a context menu |
renderTag | node | div | ✘ | - | The render tag of the wrapper |
event | string | onContextMenu | ✘ | Same as React Event (onClick, onContextMenu ...) | Event to trigger the context menu |
className | string | ✘ | Additional className | ||
style | object | ✘ | Additional style |
const Foo = <ContextMenuProvider id="menu_id"><MyComponent /></ContextMenuProvider>;
menuProvider (Type : function)
Args | Type | Default | Required | Possible Value | Description |
---|---|---|---|---|---|
id | string | - | ✓ | - | Id used to map your component to a context menu |
- Function returned by menuProvider expect :
Args | Type | Default | Required | Possible Value | Description |
---|---|---|---|---|---|
targetComponent | React Component | - | ✓ | - | The component on which you want to add a context menu |
renderTag | node | div | ✘ | - | The render tag of the wrapper |
event | string | onContextMenu | ✘ | Same as React Event (onClick, onContextMenu ...) | Event to trigger the context menu |
className | string | ✘ | Additional className | ||
style | object | ✘ | Additional style |
Migration from v1 to v2
Breaking changes are a pain for developers but sometimes we have too.
Item Component: You can render whatever you want now, which gives you more control.
//before<Item label="foo" />// now<Item>foo</Item>
onClick callback: Having access to the instance of the react component can be sometimes really useful.
//before// now
Release Notes
2.0.7
- Simplified implementation Pull Request #22
2.0.6
- Typo fix in documentation
- Pass props down to
menuProvider
function
2.0.5
- Will now hide menu on mousedown.Relate to issue 19
- Added flag noIdents to cssnano to avoid animation name collision with other libs
Bug Fix
- Fixed zoom animation
2.0.4
- Minor code cleanup
2.0.3
Bug Fix
- Firefox trigger a click event also on context menu which was making the menu disappear. Relate to issue 16
2.0.2
Bug Fixes
- Fix issue #14
2.0.1
Bug Fixes
- conditional rendering was badly tested, shame on me !
2.0.0
- This version introduce breaking changes for the item component
- Upgrade to
prop-types
- Tested with jest and enzyme
- Reviewed build system
Features
- The
onClick
callback provide a ref to the wrapped component - Can now use condtionnal rendering for dynamic menu. Relate to issue 12
- Added
IconFont
component
Bug Fixes
- Fixed right click behavior. Relate to issue 11
1.1.0
Features
- Added possibility to set the render tag for the wrapper
- Added a ContextMenuProvider component
- Added possibility to set className and style to ContextMenuProvider
- Removed ContextMenuProvider style.Was too unpredictable
Bug Fixes
- fixed incorrect PropTypes used
- dead code elimination
Contribute
Any idea and suggestions are welcome.
Thanks
Big thanks to Tobias Reich. This project is based on basicContext. A vanilla js context menu.
License
React Contexify is licensed under MIT.