This commit is contained in:
Michał Gdula 2023-02-07 14:34:26 +00:00
parent 96976856d7
commit 0982a91c03
5 changed files with 425 additions and 0 deletions

2
Menus/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
css/style.css.map
css/style.css

1
Menus/README.md Normal file
View file

@ -0,0 +1 @@
Menu system written in JS and Sass, uses json to markup the menus

182
Menus/css/style.sass Normal file
View file

@ -0,0 +1,182 @@
$primary: rgb(66, 130, 167)
$success: rgb(95, 175, 99)
$warning: rgb(236, 136, 77)
$critical: rgb(247, 111, 111)
$fg100: rgb(248,248,250)
$fg200: rgb(225,227,233)
$fg300: rgb(203,205,216)
$fg400: rgb(180,184,200)
$fg500: rgb(146,150,169)
$fg600: rgb(78,83,106)
$bg100: rgb(61,66,83)
$bg200: rgb(50,54,68)
$bg300: rgb(42,45,57)
$bg400: rgb(37,39,50)
$bg500: rgb(32,35,44)
$bg600: rgb(28,30,38)
*
box-sizing: border-box
html
font-size: 16px
font-family: 'Roboto', sans-serif
font-weight: 400
color: $fg100
background-color: $bg500
body
display: flex
flex-direction: row
justify-content: center
align-items: center
gap: 1rem
> button
margin: 0
padding: 0.5rem 1rem
width: auto
height: 3rem
display: flex
justify-content: center
align-items: center
color: $fg100
background-color: $bg300
border: 1px solid $bg200
border-radius: 3px
cursor: pointer
transition: all 0.2s ease-in-out
&:hover
background-color: $bg200
.contextMenuClose
width: 100vw
height: 100vh
position: fixed
top: 0
left: 0
background-color: transparent
z-index: 99998
.contextMenu
margin: 0
padding: 0.25rem
width: calc( 100vw - 10px )
height: auto
max-width: 300px
position: absolute
display: flex
flex-direction: column
justify-content: flex-start
align-items: flex-start
gap: 0.25rem
background-color: $bg300
border: 1px solid $bg200
border-radius: 6px
overflow: hidden
transition: all 0.2s ease-in-out
transform-origin: top left
opacity: 0
transform: scale(0, 0)
z-index: 99999
.contextMenuTitle
margin: 0
padding: 0.25rem 0.5rem
width: 100%
text-align: center
font-size: 1.2rem
font-weight: 400
color: $fg300
.contextMenuItem
margin: 0
padding: 0.25rem
width: 100%
height: auto
display: flex
flex-direction: row
justify-content: flex-start
align-items: center
gap: 0.5rem
background-color: $bg300
color: $fg300
border: none
border-radius: 3px
cursor: pointer
.contextMenuItem:hover
background-color: $bg200
.contextMenuItem__critical
color: $critical
//.contextMenuItem__critical:hover
// background-color: rgba($critical, 0.1)
.contextMenuItem__warning
color: $warning
//.contextMenuItem__warning:hover
// background-color: rgba($warning, 0.1)
.contextMenuItem__success
color: $success
//.contextMenuItem__success:hover
// background-color: rgba($success, 0.1)
.contextMenuItem__info
color: $primary
//.contextMenuItem__info:hover
// background-color: rgba($primary, 0.1)
.contextMenuText
margin: 0
padding: 0
font-size: 1rem
font-weight: 400
.contextMenuIcon
margin: 0
padding: 0
width: 1.25rem
height: 1.25rem
display: flex
justify-content: center
align-items: center
.contextMenuDivider
margin: 0 auto
padding: 0
width: 90%
height: 1px
border: none
background-color: $bg200
.contextMenu__show
opacity: 1
transform: scale(1, 1)
.contextMenu__hide
opacity: 0
transform: scale(0, 0)

110
Menus/index.html Normal file
View file

@ -0,0 +1,110 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JS menus</title>
<link rel="stylesheet" href="css/style.css">
<script src="js/main.js"></script>
</head>
<body>
<button onclick="showContextMenu(this, [{'value': 'gwagwa', 'function': dissmissContextMenu},{'value': 'gwagwa', 'function': dissmissContextMenu}])">Show menu</button>
<button onclick="imageActions(this)">Image actions</button>
</body>
</html>
<script>
function imageActions(obj) {
var link = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="-3 -3 24 24" fill="currentColor"><path d="M3.19 9.345a.97.97 0 0 1 1.37 0 .966.966 0 0 1 0 1.367l-2.055 2.052a1.932 1.932 0 0 0 0 2.735 1.94 1.94 0 0 0 2.74 0l4.794-4.787a.966.966 0 0 0 0-1.367.966.966 0 0 1 0-1.368.97.97 0 0 1 1.37 0 2.898 2.898 0 0 1 0 4.103l-4.795 4.787a3.879 3.879 0 0 1-5.48 0 3.864 3.864 0 0 1 0-5.47L3.19 9.344zm11.62-.69a.97.97 0 0 1-1.37 0 .966.966 0 0 1 0-1.367l2.055-2.052a1.932 1.932 0 0 0 0-2.735 1.94 1.94 0 0 0-2.74 0L7.962 7.288a.966.966 0 0 0 0 1.367.966.966 0 0 1 0 1.368.97.97 0 0 1-1.37 0 2.898 2.898 0 0 1 0-4.103l4.795-4.787a3.879 3.879 0 0 1 5.48 0 3.864 3.864 0 0 1 0 5.47L14.81 8.656z"></path></svg>'
var download = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -5 24 24" fill="currentColor"><path d="M8 6.641l1.121-1.12a1 1 0 0 1 1.415 1.413L7.707 9.763a.997.997 0 0 1-1.414 0L3.464 6.934A1 1 0 1 1 4.88 5.52L6 6.641V1a1 1 0 1 1 2 0v5.641zM1 12h12a1 1 0 0 1 0 2H1a1 1 0 0 1 0-2z"></path></svg>';
var edit = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="-2.5 -2.5 24 24" fill="currentColor"><path d="M12.238 5.472L3.2 14.51l-.591 2.016 1.975-.571 9.068-9.068-1.414-1.415zM13.78 3.93l1.414 1.414 1.318-1.318a.5.5 0 0 0 0-.707l-.708-.707a.5.5 0 0 0-.707 0L13.781 3.93zm3.439-2.732l.707.707a2.5 2.5 0 0 1 0 3.535L5.634 17.733l-4.22 1.22a1 1 0 0 1-1.237-1.241l1.248-4.255 12.26-12.26a2.5 2.5 0 0 1 3.535 0z"></path></svg>';
var trash = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="-3 -2 24 24" fill="currentColor"><path d="M6 2V1a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v1h4a2 2 0 0 1 2 2v1a2 2 0 0 1-2 2h-.133l-.68 10.2a3 3 0 0 1-2.993 2.8H5.826a3 3 0 0 1-2.993-2.796L2.137 7H2a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h4zm10 2H2v1h14V4zM4.141 7l.687 10.068a1 1 0 0 0 .998.932h6.368a1 1 0 0 0 .998-.934L13.862 7h-9.72zM7 8a1 1 0 0 1 1 1v7a1 1 0 0 1-2 0V9a1 1 0 0 1 1-1zm4 0a1 1 0 0 1 1 1v7a1 1 0 0 1-2 0V9a1 1 0 0 1 1-1z"></path></svg>';
showContextMenu(obj, [
{
'value': 'title',
'text': 'Image actions',
},
{
'value': 'Copy Link',
'icon': link,
'function': dissmissContextMenu
},
{
'value': 'Download',
'icon': download,
'function': dissmissContextMenu
},
{
'value': 'divider',
},
{
'value': 'Edit',
'icon': edit,
'function': dissmissContextMenu,
'type': 'critical'
},
{
'value': 'Delete',
'icon': trash,
'function': dissmissContextMenu,
'type': 'critical'
},
{
'value': 'divider',
},
{
'value': 'Edit',
'icon': edit,
'function': dissmissContextMenu,
'type': 'warning'
},
{
'value': 'Delete',
'icon': trash,
'function': dissmissContextMenu,
'type': 'warning'
},
{
'value': 'divider',
},
{
'value': 'Edit',
'icon': edit,
'function': dissmissContextMenu,
'type': 'success'
},
{
'value': 'Delete',
'icon': trash,
'function': dissmissContextMenu,
'type': 'success'
},
{
'value': 'divider',
},
{
'value': 'Edit',
'icon': edit,
'function': dissmissContextMenu,
'type': 'info'
},
{
'value': 'Delete',
'icon': trash,
'function': dissmissContextMenu,
'type': 'info'
},
{
'value': 'divider',
},
{
'value': 'gwagwa',
'function': dissmissContextMenu
}
],
)
};
</script>

130
Menus/js/main.js Normal file
View file

@ -0,0 +1,130 @@
/*
Function takes an object as a parameter to
determine where to display the context menu
menu:
value - Text to display
icon - True for default icon, false for no icon, or a string for a custom icon
function - Function to call when clicked
type - Type of menu item (critical, warning, success, info)
*/
function showContextMenu(obj, menu) {
// If the context menu is already open, close it first
if (document.querySelector(".contextMenu")) {
dissmissContextMenu();
}
// Add span to close the context menu
var closeSpan = document.createElement("span");
closeSpan.className = "contextMenuClose";
closeSpan.onclick = dissmissContextMenu;
// Create the context menu
var contextMenu = document.createElement("div");
contextMenu.className = "contextMenu";
// Create the menu items
menu.forEach(array => {
if (array.value == "divider") {
// If the menu item is a divider, create a divider
var divider = document.createElement("hr");
divider.className = "contextMenuDivider";
contextMenu.appendChild(divider);
return;
} else if (array.value == "title") {
// Create the title and add it to the context menu
var titleP = document.createElement("p");
titleP.className = "contextMenuTitle";
titleP.innerHTML = array.text;
contextMenu.appendChild(titleP);
// Add a divider after the title
var divider = document.createElement("hr");
divider.className = "contextMenuDivider";
contextMenu.appendChild(divider);
return;
}
// Create the menu item
itemBtn = document.createElement("button");
itemBtn.className = "contextMenuItem";
itemBtn.onclick = array.function;
if (array.type == "critical") {
itemBtn.classList.add("contextMenuItem__critical");
} else if (array.type == "warning") {
itemBtn.classList.add("contextMenuItem__warning");
} else if (array.type == "success") {
itemBtn.classList.add("contextMenuItem__success");
} else if (array.type == "info") {
itemBtn.classList.add("contextMenuItem__info");
}
// Create the icon for the action
itemIcon = document.createElement("span");
itemIcon.className = "contextMenuIcon";
// Determine if the menu item has an icon
if (array.icon != null) {
itemIcon.innerHTML = array.icon;
} else {
itemIcon.innerHTML = '';
}
itemBtn.appendChild(itemIcon);
// Create the text for the action
itemText = document.createElement("p");
itemText.className = "contextMenuText";
itemText.innerHTML = array.value;
itemBtn.appendChild(itemText);
// Add menu item to the context menu
contextMenu.appendChild(itemBtn);
});
// Add the context menu to the body
document.body.appendChild(contextMenu);
document.body.appendChild(closeSpan);
// Get position of the item clicked or the mouse
try {
var posX = event.clientX + 5;
var posY = event.clientY + 5;
} catch (error) {
var posX = obj.offsetLeft + (bj.offsetWidth * 0.6) + 2;
var posY = obj.offsetTop + obj.offsetHeight + 2
}
// Move the context menu if it is off the screen
if (posX + contextMenu.offsetWidth > window.innerWidth) {
posX = window.innerWidth - (contextMenu.offsetWidth + 5);
}
if (posY + contextMenu.offsetHeight > window.innerHeight) {
posY = window.innerHeight - (contextMenu.offsetHeight + 5);
}
contextMenu.style.left = posX + "px";
contextMenu.style.top = posY + "px";
setTimeout(function() {
contextMenu.classList.add("contextMenu__show");
}, 1);
}
function dissmissContextMenu() {
// Remove the close span
var contextMenu = document.querySelectorAll(".contextMenuClose");
contextMenu.forEach(menu => {
menu.remove();
});
// Get the context menu
var contextMenu = document.querySelectorAll(".contextMenu");
contextMenu.forEach(menu => {
menu.classList.add("contextMenu__hide");
// Animatin should be 500ms
setTimeout(function() {
menu.remove();
}, 500);
});
}