JSFiddle - React, Tailwind, and code Playground

by Renan Gomes

HTML

<nav id='context-menu' class='context-menu'>
  <a href='#'>Novo</a>
  <a href='#'>Salvar</a>
  <span class='separator'></span>
  <a href='#'>Copiar</a>
  <a href='#'>Colar</a>
  <span class='separator'></span>
  <a href='#'>Fechar</a>
</nav>

<p id='log'></p>

CSS

* { box-sizing: border-box }

.context-menu.active {
  display: flex;
  position: absolute;
}

.context-menu {
  border: 1px solid #ccc;
  box-shadow: 0 4px 2px rgba(0, 0, 0, .2);
  display: none;
  flex-flow: column wrap;
  padding: 6px 4px;
  width: 200px;
  height: 190px;
}

.context-menu .separator,
.context-menu a {
  display: inline-block
}

.context-menu .separator {
  border: 1px solid #ccc;
  margin: 4px 0;
  width: 100%
}

.context-menu a {
  color: #333;
  margin-left: 15px;
  padding: 5px;
  text-decoration: none
}

JavaScript

document.addEventListener('contextmenu', handleContextMenu, false);

var menu = document.querySelector('.context-menu'),
		menuItems = menu.querySelectorAll('a');
    
var size = {width: 0, height: 0};

/**
 * Função para exibir o menu de contexto no ponto x/y
 * que o usuário clicar com o mouse.
 */
function handleContextMenu(event){
	event.preventDefault();
  
  menu.classList.add('active');
  
  updateWindowSize();
  var needsWrapWidth = event.clientX > size.width - 200,
  		needsWrapHeight = event.clientY > size.height - 200;
      
 	if(!needsWrapWidth)
  	menu.style.left  = event.clientX + 'px';
  else
  	menu.style.right = '0px';

	if(!needsWrapHeight)
  	menu.style.top = event.clientY + 'px';
  else
  	menu.style.bottom = '0'
}

for(var i = 0; i < menuItems.length; i++){
	menuItems[i].addEventListener('click', handleContextMenuClick, false);
}

function handleContextMenuClick(event){
	var selection = event.target.innerHTML;
	
  document.getElementById('log').innerHTML = 'Você clicou na opção "' + selection + '".';
  
  menu.classList.remove('active');
}

function updateWindowSize(){
	size.width = window.innerWidth || document.documentElement.clientWidth ||
           document.body.clientWidth || document.body.offsetWidth;
  size.height = window.innerHeight || document.documentElement.clientHeight ||
           document.body.clientHeight || document.body.offsetHeight;
}