A browser source overlay for winter vibes for your Live Streams or Videos

Added context menu & modals

+39
index.html
···
</head>
<body>
<canvas id="main"></canvas>
+
+
+
<div id="contextMenu" class="context-menu" style="display:none">
+
<ul>
+
<li><a href="#" id="openSettings">Settings</a></li>
+
<li><a href="#" id="openHelp">Help</a></li>
+
<li><a href="https://buymeacoffee.com/treysdevshed">Buy me a coffee</a></li>
+
</ul>
+
</div>
+
+
<div id="modalSettings" class="modal">
+
<div class="modal-content">
+
<div class="modal-header">
+
<span>Settings modal</span>
+
</div>
+
<div class="modal-main">
+
<span>example</span>
+
</div>
+
<div class="model-footer">
+
<button id="closeSettings">Close</button>
+
</div>
+
</div>
+
</div>
+
</div>
+
+
<div id="modalHelp" class="modal">
+
<div class="modal-content">
+
<div class="modal-header">
+
<span>Help modal</span>
+
</div>
+
<div class="modal-main">
+
<span>example</span>
+
</div>
+
<div class="model-footer">
+
<button id="closeHelp">Close</button>
+
</div>
+
</div>
+
</div>
+
<script type="module" src="/src/main.js"></script>
</body>
</html>
-10
pnpm-lock.yaml
···
.:
devDependencies:
-
typescript:
-
specifier: ^5.6.3
-
version: 5.6.3
vite:
specifier: ^5.4.10
version: 5.4.11
···
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'}
-
typescript@5.6.3:
-
resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==}
-
engines: {node: '>=14.17'}
-
hasBin: true
-
vite@5.4.11:
resolution: {integrity: sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==}
engines: {node: ^18.0.0 || >=20.0.0}
···
fsevents: 2.3.3
source-map-js@1.2.1: {}
-
-
typescript@5.6.3: {}
vite@5.4.11:
dependencies:
+36
src/contextMenu.js
···
+
document.onclick = hideMenu;
+
document.oncontextmenu = rightClick;
+
+
function hideMenu() {
+
document.getElementById("contextMenu").style.display = "none"
+
}
+
+
function rightClick(e) {
+
e.preventDefault();
+
+
if (document.getElementById(
+
"contextMenu").style.display == "block")
+
hideMenu();
+
else {
+
let menu = document
+
.getElementById("contextMenu")
+
+
menu.style.display = 'block';
+
menu.style.left = e.pageX + "px";
+
menu.style.top = e.pageY + "px";
+
}
+
}
+
+
/**
+
* @param {string} modalId
+
* @param {boolean} isShowing
+
*/
+
function toggleModal(modalId, isShowing) {
+
const modal = document.getElementById(modalId);
+
if (isShowing) {
+
console.log(modalId, isShowing);
+
modal.style.display = isShowing ? 'block' : 'none';
+
}
+
}
+
+
export { toggleModal };
+15
src/main.js
···
snowAccumulatorCollisionX,
} from "./snow_accumulator";
import { createPlow, drawPlow, movePlow, plowDone } from "./plow";
+
import { toggleModal } from "./contextMenu";
+
+
// Modals & buttons
+
const openSettings = document.getElementById('openSettings');
+
const openHelp = document.getElementById('openHelp');
+
const closeSettings = document.getElementById('closeSettings');
+
const closeHelp = document.getElementById('closeHelp');
+
+
openSettings.addEventListener('click', () => toggleModal('modalSettings', true));
+
openHelp.addEventListener('click', () => toggleModal('modalHelp', true));
+
+
// Closing doesn't call the function idk why its stupid... assuming its something to do with DOM
+
closeSettings.addEventListener('click', () => toggleModal('modalSettings', false));
+
closeSettings.addEventListener('click', () => console.log('close settings'));
+
closeHelp.addEventListener('click', () => toggleModal('modalHelp', false));
/**
* @type{Array.<Snowflake>}
+63 -1
src/style.css
···
+
@import url('https://fonts.googleapis.com/css2?family=Pixelify+Sans:wght@400..700&display=swap');
+
*,
*:after,
-
*:befpre {
+
*:before {
box-sizing: border-box;
}
body {
+
font-family: "Pixelify Sans", sans-serif;
+
font-style: normal;
background-color: #091e36;
min-width: 100vw;
min-height: 100vh;
···
height: 100%;
image-rendering: pixelated;
}
+
+
.context-menu {
+
border-radius: 10px;
+
position: absolute;
+
text-align: center;
+
background-color: beige;
+
border: 1px solid black;
+
}
+
+
.context-menu ul {
+
padding: 0px;
+
margin: 0px;
+
min-width: 150px;
+
list-style: none;
+
}
+
+
.context-menu ul li {
+
border-radius: 10px;
+
padding-bottom: 7px;
+
padding-top: 7px;
+
}
+
+
.context-menu ul li a {
+
border-radius: 10px;
+
text-decoration: none;
+
color: black;
+
}
+
+
.context-menu ul li:hover {
+
border-radius: 10px;
+
background-color: bisque;
+
}
+
+
.modal {
+
display: none;
+
position: fixed;
+
z-index: 100;
+
left: 0;
+
top: 0;
+
width: 100%;
+
height: 100%;
+
background-color: rgba(0, 0, 0, 0.4);
+
}
+
+
.modal-content {
+
text-align: center;
+
background-color: beige;
+
margin: 15% auto;
+
padding: 20px;
+
border: 1px solid #888;
+
width: 30%;
+
border: 1px solid black;
+
border-radius: 10px;
+
}
+
+
.modal-header {
+
font-size: 20px;
+
}