Skip to content

Commit 9681aa9

Browse files
committed
💄 Add styling for XUL menupopup and menuitems
1 parent 71dbcb0 commit 9681aa9

File tree

7 files changed

+361
-10
lines changed

7 files changed

+361
-10
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
{
6+
Services.scriptloader.loadSubScript(
7+
"chrome://dot/content/widgets/xul-menuitem.js"
8+
);
9+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
@import url("chrome://dot/skin/input.css");
6+
@import url("chrome://dot/content/widgets/browser-panel-button.css");
7+
8+
::slotted(menuitem),
9+
::slotted(menu) {
10+
--button-default-color: transparent !important;
11+
12+
padding: 6px 30px;
13+
}
14+
15+
::slotted(menu) {
16+
background-image: url(chrome://dot/skin/chevron-right.svg);
17+
18+
-moz-context-properties: fill, fill-opacity;
19+
fill: currentColor;
20+
21+
background-repeat: no-repeat;
22+
background-position: calc(100% - 10px) center;
23+
}
24+
25+
::slotted(menuitem[type=checkbox][checked]) {
26+
background-image: url(chrome://dot/skin/check.svg);
27+
28+
-moz-context-properties: fill, fill-opacity;
29+
fill: currentColor;
30+
31+
background-repeat: no-repeat;
32+
background-position: 10px center;
33+
}
34+
35+
::slotted(menuseparator) {
36+
width: calc(100% - 4px * 2);
37+
height: 1px;
38+
margin-block: 2px;
39+
margin-inline: 4px;
40+
background: linear-gradient(to top, var(--arrowpanel-border-color), var(--arrowpanel-border-color)), color-mix(in srgb, currentColor 15%, transparent 100%);
41+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
{
6+
class MozMenuItem extends MozXULElement {
7+
/**
8+
* The allowed customizable attributes for the menu item
9+
*/
10+
static get customizableAttributes() {
11+
return {
12+
type: (value) => {
13+
if (!["normal", "group", "separator"].includes(value)) {
14+
throw new Error(
15+
`Attribute 'type' must be either "normal", "separator" or "group", got '${value}'.`
16+
);
17+
}
18+
19+
return value;
20+
},
21+
22+
orientation: "orientation"
23+
};
24+
}
25+
26+
/**
27+
* Determines what type of menu item this is
28+
*/
29+
get type() {
30+
return this.getAttribute("type");
31+
}
32+
33+
/**
34+
* Determines the orientation of the menu item
35+
*/
36+
get orientation() {
37+
return this.getAttribute("orientation");
38+
}
39+
40+
set orientation(newValue) {
41+
this.setAttribute("orientation", newValue);
42+
}
43+
44+
/**
45+
* Determines the icons mode of the menu item
46+
*/
47+
get mode() {
48+
return this.getAttribute("mode");
49+
}
50+
51+
set mode(newValue) {
52+
this.setAttribute("mode", newValue);
53+
}
54+
55+
connectedCallback() {
56+
if (this.delayConnectedCallback()) return;
57+
58+
if (this.type == "group") {
59+
if (!this.getAttribute("orientation")) {
60+
this.orientation = "horizontal";
61+
}
62+
}
63+
64+
if (this.orientation == "horizontal") {
65+
this.mode = "icons";
66+
}
67+
}
68+
}
69+
70+
customElements.define("menuitem", MozMenuItem);
71+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
@import url("chrome://dot/content/widgets/xul-menuitem.css");
6+
7+
:host(menupopup) {
8+
--panel-shadow-margin: 10px;
9+
10+
-moz-window-input-region-margin: var(--panel-shadow-margin);
11+
margin: calc(-1 * (var(--panel-shadow-margin) + var(--panel-inner-padding, 0px)));
12+
13+
-moz-window-dragging: no-drag;
14+
15+
transition: 0.2s opacity cubic-bezier(0.19, 1, 0.22, 1);
16+
}
17+
18+
:host(menupopup[animate="true"]) {
19+
opacity: 0;
20+
}
21+
22+
:host(menupopup[animate="true"][open]) {
23+
opacity: 1;
24+
}
25+
26+
:host(menupopup:not([open])) {
27+
pointer-events: none;
28+
}
29+
30+
.browser-panel-container {
31+
display: flex;
32+
flex-direction: column;
33+
34+
width: auto;
35+
height: auto;
36+
37+
min-width: 16px;
38+
min-height: 16px;
39+
40+
padding: 2px;
41+
margin: var(--panel-shadow-margin);
42+
43+
background-color: var(--arrowpanel-background);
44+
45+
border: 1px solid var(--arrowpanel-border-color);
46+
border-radius: 8px;
47+
48+
box-shadow: 0 3.2px 7.2px 0 rgba(0, 0, 0, .132), 0 .6px 1.8px 0 rgba(0, 0, 0, .108);
49+
50+
overflow: clip;
51+
52+
gap: 2px;
53+
}
54+
55+
:host(.browser-panel-container) .browser-panel-header {
56+
display: flex;
57+
58+
justify-content: center;
59+
align-items: center;
60+
61+
width: 100%;
62+
padding: 14px 0px;
63+
64+
border-bottom: 1px solid color-mix(in srgb, currentColor 15%, transparent 100%);
65+
66+
& .browser-panel-header-title {
67+
font-weight: bold;
68+
}
69+
}
70+
71+
:host(.browser-panel-container) .browser-panel-content {
72+
display: flex;
73+
74+
justify-content: center;
75+
align-items: center;
76+
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
// @ts-nocheck
6+
7+
"use strict";
8+
9+
// This is loaded into all XUL windows. Wrap in a block to prevent
10+
// leaking to window scope.
11+
{
12+
class MozMenuPopup extends MozElements.MozElementMixin(XULPopupElement) {
13+
constructor() {
14+
super();
15+
16+
this.attachShadow({ mode: "open" });
17+
}
18+
19+
/**
20+
* The container element that holds the panel's contents
21+
*/
22+
get container() {
23+
return /** @type {HTMLElement} */ (
24+
this.shadowRoot.querySelector(".browser-panel-container")
25+
);
26+
}
27+
28+
/**
29+
* Fires when the popup starts showing on-screen
30+
* @param {Event} event
31+
*/
32+
onPopupShowing(event) {
33+
if (event.target != this) return;
34+
35+
this.ensureInitialized();
36+
}
37+
38+
/**
39+
* Fires when the popup is showing
40+
* @param {Event} event
41+
*/
42+
onPopupShown(event) {
43+
this.setAttribute("open", "");
44+
}
45+
46+
/**
47+
* Fires when the popup starts being hidden
48+
*/
49+
onPopupHiding() {
50+
this.removeAttribute("open");
51+
52+
// Remove the panel once all transitions have completed
53+
if (this.getAttribute("animate") == "true") {
54+
this.addEventListener(
55+
"transitionend",
56+
() => {
57+
this.hidePopup();
58+
},
59+
{
60+
once: true
61+
}
62+
);
63+
} else {
64+
this.hidePopup();
65+
}
66+
}
67+
68+
connectedCallback() {
69+
if (this.delayConnectedCallback() || this.hasConnected) {
70+
return;
71+
}
72+
73+
this.setAttribute("animate", "true");
74+
this.setAttribute("consumeoutsideclicks", "true");
75+
this.setAttribute("incontentshell", "false");
76+
77+
this.addEventListener(
78+
"popupshowing",
79+
this.onPopupShowing.bind(this)
80+
);
81+
82+
this.addEventListener("popupshown", this.onPopupShown.bind(this));
83+
84+
this.addEventListener("popuphiding", this.onPopupHiding.bind(this));
85+
86+
this.hasConnected = true;
87+
}
88+
89+
ensureInitialized() {
90+
if (this.shadowRoot.firstChild) return;
91+
92+
const style = document.createElement("link");
93+
style.rel = "stylesheet";
94+
style.href = "chrome://dot/content/widgets/xul-menupopup.css";
95+
96+
const container = document.createElement("div");
97+
container.classList.add("browser-panel-container");
98+
99+
const slot = document.createElement("slot");
100+
101+
container.appendChild(slot);
102+
103+
super.shadowRoot.append(style, container);
104+
}
105+
}
106+
107+
customElements.define("menupopup", MozMenuPopup);
108+
109+
MozElements.MozMenuPopup = MozMenuPopup;
110+
}

‎components/panels/jar.mn

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,18 @@ dot.jar:
2323

2424
content/widgets/browser-panel-button.js (content/browser-panel-button.js)
2525
content/widgets/browser-panel-button.css (content/browser-panel-button.css)
26+
27+
content/widgets/xul-menu.js (content/xul-menu.js)
28+
29+
content/widgets/xul-menuitem.js (content/xul-menuitem.js)
30+
content/widgets/xul-menuitem.css (content/xul-menuitem.css)
31+
32+
content/widgets/xul-menupopup.js (content/xul-menupopup.js)
33+
content/widgets/xul-menupopup.css (content/xul-menupopup.css)
34+
35+
% override chrome://global/content/menu.js chrome://dot/content/widgets/xul-menu.js
36+
% override chrome://global/content/elements/menupopup.js chrome://dot/content/widgets/xul-menupopup.js
37+
38+
% override chrome://global/skin/popup.css chrome://dot/content/compat/blank.css
39+
% override chrome://global/skin/menu.css chrome://dot/content/compat/blank.css
40+
% override chrome://global/skin/menu-shared.css chrome://dot/content/compat/blank.css

0 commit comments

Comments
 (0)