Make QR context menu display options more consistent with QR bar Use QR title as tooltip if set on the QR Add qr--hidden class to "invisible" context items to allow hiding with CSS Add title and isHidden props to MenuItem Remove domIcon and domLabel props: not needed for ctx menu rendering; isForceExpanded: unimplemented

3a1a955164427cfbae63c4ad97845e500dba676b

ceruleandeep <deep@cerulean.navy>

3 files changed, +45 -9Showing whitespace changes
public/scripts/extensions/quick-reply/src/ui/ctx/ContextMenu.js+5 -1
@@ -19,7 +19,7 @@ export class ContextMenu {
19 this.itemList = this.build(qr).children;19 this.itemList = this.build(qr).children;
20 this.itemList.forEach(item => {20 this.itemList.forEach(item => {
21 item.onExpand = () => {21 item.onExpand = () => {
22 this.itemList.filter(it => it != item)22 this.itemList.filter(it => it !== item)
23 .forEach(it => it.collapse());23 .forEach(it => it.collapse());
24 };24 };
25 });25 });
@@ -36,7 +36,9 @@ export class ContextMenu {
36 icon: qr.icon,36 icon: qr.icon,
37 showLabel: qr.showLabel,37 showLabel: qr.showLabel,
38 label: qr.label,38 label: qr.label,
39 title: qr.title,
39 message: (chainedMessage && qr.message ? `${chainedMessage} | ` : '') + qr.message,40 message: (chainedMessage && qr.message ? `${chainedMessage} | ` : '') + qr.message,
41 isHidden: qr.isHidden,
40 children: [],42 children: [],
41 };43 };
42 qr.contextList.forEach((cl) => {44 qr.contextList.forEach((cl) => {
@@ -51,7 +53,9 @@ export class ContextMenu {
51 subTree.icon,53 subTree.icon,
52 subTree.showLabel,54 subTree.showLabel,
53 subTree.label,55 subTree.label,
56 subTree.title,
54 subTree.message,57 subTree.message,
58 subTree.isHidden,
55 (evt) => {59 (evt) => {
56 evt.stopPropagation();60 evt.stopPropagation();
57 const finalQr = Object.assign(new QuickReply(), subQr);61 const finalQr = Object.assign(new QuickReply(), subQr);
public/scripts/extensions/quick-reply/src/ui/ctx/MenuHeader.js+1 -1
@@ -2,7 +2,7 @@ import { MenuItem } from './MenuItem.js';
22
3export class MenuHeader extends MenuItem {3export class MenuHeader extends MenuItem {
4 constructor(/**@type {String}*/label) {4 constructor(/**@type {String}*/label) {
5 super(null, null, label, null, null);5 super(null, null, label, null, null, false, null, []);
6 }6 }
77
88
public/scripts/extensions/quick-reply/src/ui/ctx/MenuItem.js+39 -7
@@ -4,11 +4,12 @@ export class MenuItem {
4 /**@type {string}*/ icon;4 /**@type {string}*/ icon;
5 /**@type {boolean}*/ showLabel;5 /**@type {boolean}*/ showLabel;
6 /**@type {string}*/ label;6 /**@type {string}*/ label;
7 /**@type {string}*/ title;
7 /**@type {object}*/ value;8 /**@type {object}*/ value;
9 /**@type {boolean}*/ isHidden = false;
8 /**@type {function}*/ callback;10 /**@type {function}*/ callback;
9 /**@type {MenuItem[]}*/ childList = [];11 /**@type {MenuItem[]}*/ childList = [];
10 /**@type {SubMenu}*/ subMenu;12 /**@type {SubMenu}*/ subMenu;
11 /**@type {boolean}*/ isForceExpanded = false;
1213
13 /**@type {HTMLElement}*/ root;14 /**@type {HTMLElement}*/ root;
1415
@@ -19,35 +20,67 @@ export class MenuItem {
1920
20 /**21 /**
21 *22 *
22 * @param {string} icon23 * @param {?string} icon
23 * @param {boolean} showLabel24 * @param {?boolean} showLabel
24 * @param {string} label25 * @param {string} label
26 * @param {?string} title Tooltip
25 * @param {object} value27 * @param {object} value
28 * @param {boolean} isHidden QR is Invisible (auto-execute only)
26 * @param {function} callback29 * @param {function} callback
27 * @param {MenuItem[]} children30 * @param {MenuItem[]} children
28 */31 */
29 constructor(icon, showLabel, label, value, callback, children = []) {32 constructor(icon, showLabel, label, title, value, isHidden, callback, children = []) {
30 this.icon = icon;33 this.icon = icon;
31 this.showLabel = showLabel;34 this.showLabel = showLabel;
32 this.label = label;35 this.label = label;
36 this.title = title;
33 this.value = value;37 this.value = value;
38 this.isHidden = isHidden;
34 this.callback = callback;39 this.callback = callback;
35 this.childList = children;40 this.childList = children;
36 }41 }
3742
3843
44 /**
45 * Renders the MenuItem
46 *
47 * A .qr--hidden class is added to:
48 * - the item if it is "Invisible (auto-execute only)"
49 * - the icon if no icon is set
50 * - the label if an icon is set and showLabel is false
51 *
52 * There is no .qr--hidden class defined in default CSS, since having items
53 * that are invisible on the QR bar but visible in the context menu,
54 * or icon-only on the QR bar but labelled in the context menu, is a valid use case.
55 *
56 * To hide optional labels when icons are present, add this user CSS:
57 * .ctx-menu .ctx-item .qr--button-label.qr--hidden {display: none;}
58 * To hide icons when no icon is present (removes unwanted padding):
59 * .ctx-menu .ctx-item .qr--button-icon.qr--hidden {display: none;}
60 * To hide items that are set "invisible":
61 * .ctx-menu .ctx-item.qr--hidden {display: none;}
62 * To target submenus only, use .ctx-menu .ctx-sub-menu .qr--hidden {display: none;}
63 *
64 * @returns {HTMLElement}
65 */
39 render() {66 render() {
40 if (!this.root) {67 if (!this.root) {
41 const item = document.createElement('li'); {68 const item = document.createElement('li'); {
42 this.root = item;69 this.root = item;
43 item.classList.add('list-group-item');70 item.classList.add('list-group-item');
44 item.classList.add('ctx-item');71 item.classList.add('ctx-item');
45 item.title = this.value;72
73 // if this item is Invisible, add the hidden class
74 if (this.isHidden) item.classList.add('qr--hidden');
75
76 // if a title/tooltip is set, add it, otherwise use the QR content
77 // same as for the main QR list
78 item.title = this.title || this.value;
79
46 if (this.callback) {80 if (this.callback) {
47 item.addEventListener('click', (evt) => this.callback(evt, this));81 item.addEventListener('click', (evt) => this.callback(evt, this));
48 }82 }
49 const icon = document.createElement('div'); {83 const icon = document.createElement('div'); {
50 this.domIcon = icon;
51 icon.classList.add('qr--button-icon');84 icon.classList.add('qr--button-icon');
52 icon.classList.add('fa-solid');85 icon.classList.add('fa-solid');
53 if (!this.icon) icon.classList.add('qr--hidden');86 if (!this.icon) icon.classList.add('qr--hidden');
@@ -55,7 +88,6 @@ export class MenuItem {
55 item.append(icon);88 item.append(icon);
56 }89 }
57 const lbl = document.createElement('div'); {90 const lbl = document.createElement('div'); {
58 this.domLabel = lbl;
59 lbl.classList.add('qr--button-label');91 lbl.classList.add('qr--button-label');
60 if (this.icon && !this.showLabel) lbl.classList.add('qr--hidden');92 if (this.icon && !this.showLabel) lbl.classList.add('qr--hidden');
61 lbl.textContent = this.label;93 lbl.textContent = this.label;