Improve the UX of the menubar and context menu

This commit is contained in:
Nariman Jelveh 2024-05-30 13:02:00 -07:00
parent a62a56fd7b
commit 60f0ade3c1
3 changed files with 43 additions and 15 deletions

View File

@ -30,7 +30,7 @@ import path from "./lib/path.js";
import UIContextMenu from './UI/UIContextMenu.js';
/**
* In Puter, apps are loaded in iframes and communicate with the graphical user interface (GUI) aand each other using the postMessage API.
* In Puter, apps are loaded in iframes and communicate with the graphical user interface (GUI), and each other, using the postMessage API.
* The following sets up an Inter-Process Messaging System between apps and the GUI that enables communication
* for various tasks such as displaying alerts, prompts, managing windows, handling file operations, and more.
*
@ -360,17 +360,20 @@ window.addEventListener('message', async (event) => {
else if(event.data.msg === 'setMenubar') {
const el_window = window.window_for_app_instance(event.data.appInstanceID);
console.error(`EXPERIMENTAL: setMenubar is a work-in-progress`);
const hydrator = puter.util.rpc.getHydrator({
target: target_iframe.contentWindow,
});
const value = hydrator.hydrate(event.data.value);
console.log('hydrated value', value);
// Show menubar
const $menubar = $(el_window).find('.window-menubar')
$menubar.show();
// disable system context menu
$menubar.on('contextmenu', (e) => {
e.preventDefault();
});
const sanitize_items = items => {
return items.map(item => {
return {
@ -405,7 +408,10 @@ window.addEventListener('message', async (event) => {
const ctxMenu = UIContextMenu({
delay,
parent_element,
position: {top: pos.top + 28, left: pos.left},
position: {top: pos.top + 30, left: pos.left},
css: {
'box-shadow': '0px 2px 6px #00000059'
},
items: sanitize_items(items),
});
@ -429,17 +435,15 @@ window.addEventListener('message', async (event) => {
const label = html_encode(item.label);
const el_item = $(`<div class="window-menubar-item"><span>${label}</span></div>`);
const parent_element = el_item.parent()[0];
el_item.on('click', () => {
el_item.on('mousedown', (e) => {
if ( state_open ) {
state_open = false;
current && current.cancel({ meta: 'menubar' });
current_i = null;
current = null;
return;
}
if (item.action) {
item.action();
} else if (item.items) {
if (item.items) {
const pos = el_item[0].getBoundingClientRect();
open_menu({
i,
@ -447,8 +451,19 @@ window.addEventListener('message', async (event) => {
parent_element,
items: item.items,
});
e.stopPropagation();
e.preventDefault();
return;
}
})
// Clicking an item with an action will trigger that action
el_item.on('click', () => {
if (item.action) {
item.action();
}
});
el_item.on('mouseover', () => {
if ( ! state_open ) return;
if ( ! item.items ) return;

View File

@ -124,11 +124,23 @@ function UIContextMenu(options){
top: y_pos + "px",
left: x_pos + "px"
});
// Some times we need to apply custom CSS to the context menu
// This is different from the option flags for positioning and other basic styling
// This is for more advanced styling , like adding a border radius or a shadow that don't merit a new option
// Option flags should be reserved for essential styling that may have logic and sanitization attached to them
if(options.css){
$(contextMenu).css(options.css);
}
// Show ContextMenu
if ( options?.delay === false ) {
if ( options?.delay === false) {
$(contextMenu).show(0);
} else if(options?.delay === true || options?.delay === 1 || options?.delay === undefined) {
console.log('delay')
$(contextMenu).fadeIn(80).show(0);
} else {
$(contextMenu).delay(100).show(0);
$(contextMenu).fadeIn(options?.delay).show(0);
}
// mark other context menus as inactive

View File

@ -751,7 +751,7 @@ span.header-sort-icon img {
border-bottom: 1px solid #e3e3e3;
background-color: #fafafa;
--scale: 2pt;
padding: 0 2pt;
padding: 2px 5px;
}
.window-menubar-item {
@ -766,10 +766,10 @@ span.header-sort-icon img {
border-radius: calc(1.5 * var(--scale));
}
.window-menubar-item:hover > span,
.window-menubar-item.active > span {
background-color: var(--select-color);
color: white;
/* background-color: var(--select-color);
color: white; */
background-color: #e2e2e2;
}
.explorer-empty-message {
@ -1454,6 +1454,7 @@ span.header-sort-icon img {
min-width: 200px;
background-color: rgba(231, 238, 245, .98);
border: 1px solid #e4ebf3de;
border: 1px solid #CCC;
box-shadow: 0px 0px 15px #00000066;
padding-left: 6px;
padding-right: 6px;