Giter Site home page Giter Site logo

use-context-menu's Introduction

react-use-context-menu

A React hook for easily creating custom Context Menus! The hooks take care of the logic and creating the a11y attributes, you take care of the UI!


Table of Contents

Installation

This module is distributed via npm which is bundled with node and should be installed as one of your project's dependencies:

npm install --save react-use-context-menu

or

yarn add react-use-context-menu

Features

  • Supports Keyboard navigation
  • Fully customizable
  • Fully accessible
  • No dependencies
  • Only 1kb gzipped
  • RTL support
  • supports touch screen with hold to display!
  • Detects the size of the menu and always places it inside the viewport when clicking near the borders.
  • ESM and CommonJS dist

Usage

Basic usage:

import React from 'react'
import ReactDOM from 'react-dom'
import useContextMenu from 'react-use-context-menu'

function App() {
  const [
    bindMenu,
    bindMenuItems,
    useContextTrigger
  ] = useContextMenu();
  const [bindTrigger] = useContextTrigger({});
  return (
    <div className="App">
      <h1>useContextMenu</h1>
      <h2 {...bindTrigger}>Right click me to see some magic happen!</h2>
      <nav {...bindMenu}>
        <div {...bindMenuItems}>First action</div>
        <div {...bindMenuItems}>Second action</div>
        <hr/>
        <div {...bindMenuItems}>Last action</div>
      </nav>
    </div>
  );
}

API

const [
    bindMenu,
    bindMenuItems,
    useContextTrigger,
    {
        data, // the data collected by the collect function of useContextTrigger
        coords, // a 2d Array [x, y] returning the coords of the point where the right click was triggered
        setCoords, // manually set the coords of the menu
        isVisible, // Boolean indicating if the menu is visible or not
        setVisible, // manually set the context menu visible with setVisible(true) or hidden with setVisible(false)
    }
  ] = useContextMenu({
      rtl: false, // Optional, set to true to enable RightToLeft menu,
      handleElementSelect: el => el.focus() // Handles the element being selected with keyboard. Optional, focus is the default behaviour
  });

bindMenu

The first element of the result array is an Object used to bind the context menu element. It has 4 properties:

{
    style, // Mandatory
    ref, // Mandatory
    role: "menu", // Optional, if you don't care about a11y ๐Ÿ˜ 
    tabIndex: -1 // same as above, also this is needed for keyboard navigation
}

Keep in mind that you need to spread this over an actual element (like a div or a nav), if you spread it to a Component, then the Component should take care of passing the props to the underlying wrapper element. If you as well need to access the ref of the element you can simply do:

<div {...bindMenu} ref={(el) => {
    bindMenu.ref(el);
    // put your code here
}}

bindMenuItems

The second element is an Object with 3 props:

{
    ref, // Mandatory
    role: "menuitem", // Optional, if you don't care about a11y ๐Ÿ˜ 
    tabIndex: -1 // same as above, also this is needed for kayboard navigation
}

used to bind the menu items. You can spread it or assign the props one by one. Same as above applies.

useContextTrigger

The third element of the result array is another hook which you should use to bind the trigger component(s), which is the component which will trigger the context menu when right clicked. It accepts an optional config object for fine tuning and advanced usage

const [bindTrigger] = useContextTrigger({
// those are the default values 
  disable: false, // disable the trigger
  holdToDisplay: 1000, // time in ms after which the context menu will appear when holding the touch
  posX: 0, // distance in pixel from which the context menu will appear related to the right click X coord
  posY: 0, // distance in pixel from which the context menu will appear related to the right click y coord
  mouseButton: MOUSE_BUTTON.RIGHT, // set to 0 for triggering the context menu with the left click
  disableIfShiftIsPressed: false, // Self explanatory ๐Ÿ˜บ
  collect: () => 'useContextMenu is cool!' // collect data to be passed to the context menu, see the example to see this in action
});

Examples:

You can check the example folder or this codesandbox for more advanced examples.

Comparison with other similar packages

This is the first package implemented using hooks so far for what I've seen! Other packages are using components which requires lot of configuration and are way bigger in size. Also this is the smallest and most configurable ๐Ÿ’ƒ

Gratitude

This package have been deeply inspired by https://github.com/vkbansal/react-contextmenu, thanks a lot to @vkbansal! ๐Ÿ™

LICENSE

MIT

use-context-menu's People

Contributors

cluk3 avatar dependabot-preview[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

use-context-menu's Issues

event in collect function

Hi, will be cool to have an opportunity to pass event in colect func.
In my case i have more than 1k elements in list and every element i need to wrap and bind triger to be able to recognize on which element right click was made. It causes some problems with performance.
If i could wrap whole list and bind trigger to list and by event check with data art on which rlrmrnt click was made. That will be cool.

Focus does not reset on menu close.

  • react-use-context-menu: ^0.1.3"
  • npm (or yarn) version: 1.19.1

Reproduction codesandbox: https://codesandbox.io/s/laughing-river-4msn6

Problem description: When you use keyboard to select item, and you click away from context menu. The focus remains on that item. So let's say you open menu, press arrow down twice, then click away. Focus will go to third item.

Suggested solution: Focus should reset to first item when menu closes.

Plans to maintain

Is there plans to maintain this package? It looks the most promising, but being as it's a young package I don't want to commit to something that might die out in a few months.

Default menu shows up when ctrl + clicking

  • react-use-context-menu: 0.1.4
  • node: 12.16.2
  • yarn: 1.22.4

What you did:

Press ctrl + click to emulate right click

What happened:

Browser defualt menu shows up on top of custom context menu. Not sure if this is the desired behavior but some users prefer to ctrl+click rather than right click.

Reproduction codesandbox:
https://codesandbox.io/s/hopeful-hopper-v4zzv?fontsize=14

Suggested solution:

Window events have access to a ctrlKey property so we could check if ctrl key is being pressed on a left click event and adjust the event handlers to recognize this click. Probably want to add a config option to enable/disable this as well. I can take a crack at this if I find some free time this week.

Left clicking on trigger element doesn't hide context menu

First off: Thanks for this library! ๐Ÿ™‚

I think I've found a bug.

  • react-use-context-menu version: 0.1.4
  • node version: 14.6.1
  • npm (or yarn) version: 2.4.1

Expected behaviour
When the user left clicks on the div that triggered the context menu, the context menu should be hidden.

Actual behavior
If the user left clicks the div that triggered the context menu, the context menu is not hidden.
If the user left clicks somewhere else on the page, the context men is hidden.

Example: https://codesandbox.io/s/sad-shaw-yfrqk

In the example, right click the word "context", then left click the word "me". I would expect the context menu to disappear, but it doesn't. If you click anywhere else on the page, the context menu disappears.

Thanks! ๐Ÿ™‚

holdToDisplay should be 1s by default only for touch events.

I find the holdToDisplay feature useful only for touch, in desktop it's not very useful.

I would change the default option to be 1s for touch and 0 for mouse events.
The holdToDisplay option will have the following interface:

type HoldToDisplayConfig = {
 ({ touch: number  } | { mouse: number  })
}

interface ContextTriggerConfig{
  holdToDisplay: number | HoldToDisplayConfig,
  ...otherOptions
}

With the default value being:

const defaultHoldToDisplay = {
  mouse: 0,
  touch: 1000
}

If a number is given it will apply to both touch and mouse.
Also, this will require a major version bump as it will be a breaking change.

I'll implement this myself during the next days, meanwhile if somebody shows up and wants to take care of this, I'll be more than happy.

context-menu appear on the left of the window when i'm closing it

  • react-use-context-menu version: 0.1.4
  • node version: 12.18.2
  • yarn version: 1.22

What you did:
i have a project which render a document list and i use context-menu on its elements.

What happened:
when i close the context menu with a left click, the context-menu closes and reappear during 1 frame on the left side of the viewport.

unfortunately, i can't reproduce it on codesandbox

Problem description:
on /useContextMenu.js, the setStyles(baseStyles) doesn't keep the top and left position of the context-menu before disappearing

Suggested solution:
replace it with

setStyles({ ...style, position: 'fixed', opacity: 0, pointerEvents: 'none' });

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.