JSFiddle - React, Tailwind, and code Playground

by Sam Wray

HTML

<div class=context></div>

CSS

html, body {
	margin: 0;
	background-color: white;
	height: 100%;
}

.context {
	width: 100px;
	height: 150px;
	background-color: red;
	position: fixed;
	opacity: 0;
	transition: opacity 300ms;
}

.context.menu-show {
	opacity: 1;
	transition: opacity 30ms;
}

JavaScript

let contextDiv = document.querySelector('.context');

document.addEventListener('click', (e) => {
	if(e.target !== contextDiv) contextDiv.classList.remove('menu-show');
});

document.addEventListener('contextmenu', (e) => {
	e.preventDefault();
	
	contextDiv.classList.remove('menu-show');
	contextDiv.classList.add('menu-show');
	
	let x = e.clientX;
	let y = e.clientY;
	let width = contextDiv.clientWidth;
	let height = contextDiv.clientHeight;
	
	if((x + width) > window.innerWidth) {
		x = window.innerWidth - width;
	}
	
	if((y + height) > window.innerHeight) {
		y = window.innerHeight - height;
	}
	
	contextDiv.style.left = x + 'px';
	contextDiv.style.top = y + 'px';
});

class Menu {
  constructor(settings = {}) {
  	const typeEnum = ['contextmenu', 'menubar'];
  	let items = [];
    let type = isValidType(settings.type) ? settings.type : 'contextmenu';
    
    Object.defineProperty(this, 'items', {
    	get: () => {
      	return items;
      }
    });
    
   Object.defineProperty(this, 'type', {
    	get: () => {
      	return type;
      },
      set: (typeIn) => {
      	type = isValidType(typeIn) ? typeIn : type;
      }
    });
    
    this.append = item => {
    	if(!(item instanceof MenuItem)) {
      	console.error('appended item must be an instance of MenuItem');
	      return false;
      }
      
      return items.push(item);
    };
    
    this.insert = (item, index) => {
	    if(!(item instanceof MenuItem)) {
      	console.error('inserted item must be an instance of MenuItem');
	      return false;
      }
      
  		items.splice(index, 0, item);
      return true;
  	};
    
    this.remove = item => {
    	if(!(item instanceof MenuItem)) {
      	console.error('item to be removed is not an instance of MenuItem');
	      return false;
      }
      
      let index = items.indexOf(item);
      if(index < 0) {
      	console.error('item to be removed was not found in this.items');
	      return false;
      } else {
     ...