Skip to content

Commit

Permalink
💄 Add styling for XUL menupopup and menuitems
Browse files Browse the repository at this point in the history
  • Loading branch information
kierandrewett committed Dec 30, 2023
1 parent 71dbcb0 commit 9681aa9
Show file tree
Hide file tree
Showing 7 changed files with 361 additions and 10 deletions.
9 changes: 9 additions & 0 deletions components/panels/content/xul-menu.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

{
Services.scriptloader.loadSubScript(
"chrome://dot/content/widgets/xul-menuitem.js"
);
}
41 changes: 41 additions & 0 deletions components/panels/content/xul-menuitem.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

@import url("chrome://dot/skin/input.css");
@import url("chrome://dot/content/widgets/browser-panel-button.css");

::slotted(menuitem),
::slotted(menu) {
--button-default-color: transparent !important;

padding: 6px 30px;
}

::slotted(menu) {
background-image: url(chrome://dot/skin/chevron-right.svg);

-moz-context-properties: fill, fill-opacity;
fill: currentColor;

background-repeat: no-repeat;
background-position: calc(100% - 10px) center;
}

::slotted(menuitem[type=checkbox][checked]) {
background-image: url(chrome://dot/skin/check.svg);

-moz-context-properties: fill, fill-opacity;
fill: currentColor;

background-repeat: no-repeat;
background-position: 10px center;
}

::slotted(menuseparator) {
width: calc(100% - 4px * 2);
height: 1px;
margin-block: 2px;
margin-inline: 4px;
background: linear-gradient(to top, var(--arrowpanel-border-color), var(--arrowpanel-border-color)), color-mix(in srgb, currentColor 15%, transparent 100%);
}
71 changes: 71 additions & 0 deletions components/panels/content/xul-menuitem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

{
class MozMenuItem extends MozXULElement {
/**
* The allowed customizable attributes for the menu item
*/
static get customizableAttributes() {
return {
type: (value) => {
if (!["normal", "group", "separator"].includes(value)) {
throw new Error(
`Attribute 'type' must be either "normal", "separator" or "group", got '${value}'.`
);
}

return value;
},

orientation: "orientation"
};
}

/**
* Determines what type of menu item this is
*/
get type() {
return this.getAttribute("type");
}

/**
* Determines the orientation of the menu item
*/
get orientation() {
return this.getAttribute("orientation");
}

set orientation(newValue) {
this.setAttribute("orientation", newValue);
}

/**
* Determines the icons mode of the menu item
*/
get mode() {
return this.getAttribute("mode");
}

set mode(newValue) {
this.setAttribute("mode", newValue);
}

connectedCallback() {
if (this.delayConnectedCallback()) return;

if (this.type == "group") {
if (!this.getAttribute("orientation")) {
this.orientation = "horizontal";
}
}

if (this.orientation == "horizontal") {
this.mode = "icons";
}
}
}

customElements.define("menuitem", MozMenuItem);
}
76 changes: 76 additions & 0 deletions components/panels/content/xul-menupopup.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

@import url("chrome://dot/content/widgets/xul-menuitem.css");

:host(menupopup) {
--panel-shadow-margin: 10px;

-moz-window-input-region-margin: var(--panel-shadow-margin);
margin: calc(-1 * (var(--panel-shadow-margin) + var(--panel-inner-padding, 0px)));

-moz-window-dragging: no-drag;

transition: 0.2s opacity cubic-bezier(0.19, 1, 0.22, 1);
}

:host(menupopup[animate="true"]) {
opacity: 0;
}

:host(menupopup[animate="true"][open]) {
opacity: 1;
}

:host(menupopup:not([open])) {
pointer-events: none;
}

.browser-panel-container {
display: flex;
flex-direction: column;

width: auto;
height: auto;

min-width: 16px;
min-height: 16px;

padding: 2px;
margin: var(--panel-shadow-margin);

background-color: var(--arrowpanel-background);

border: 1px solid var(--arrowpanel-border-color);
border-radius: 8px;

box-shadow: 0 3.2px 7.2px 0 rgba(0, 0, 0, .132), 0 .6px 1.8px 0 rgba(0, 0, 0, .108);

overflow: clip;

gap: 2px;
}

:host(.browser-panel-container) .browser-panel-header {
display: flex;

justify-content: center;
align-items: center;

width: 100%;
padding: 14px 0px;

border-bottom: 1px solid color-mix(in srgb, currentColor 15%, transparent 100%);

& .browser-panel-header-title {
font-weight: bold;
}
}

:host(.browser-panel-container) .browser-panel-content {
display: flex;

justify-content: center;
align-items: center;
}
110 changes: 110 additions & 0 deletions components/panels/content/xul-menupopup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// @ts-nocheck

"use strict";

// This is loaded into all XUL windows. Wrap in a block to prevent
// leaking to window scope.
{
class MozMenuPopup extends MozElements.MozElementMixin(XULPopupElement) {
constructor() {
super();

this.attachShadow({ mode: "open" });
}

/**
* The container element that holds the panel's contents
*/
get container() {
return /** @type {HTMLElement} */ (
this.shadowRoot.querySelector(".browser-panel-container")
);
}

/**
* Fires when the popup starts showing on-screen
* @param {Event} event
*/
onPopupShowing(event) {
if (event.target != this) return;

this.ensureInitialized();
}

/**
* Fires when the popup is showing
* @param {Event} event
*/
onPopupShown(event) {
this.setAttribute("open", "");
}

/**
* Fires when the popup starts being hidden
*/
onPopupHiding() {
this.removeAttribute("open");

// Remove the panel once all transitions have completed
if (this.getAttribute("animate") == "true") {
this.addEventListener(
"transitionend",
() => {
this.hidePopup();
},
{
once: true
}
);
} else {
this.hidePopup();
}
}

connectedCallback() {
if (this.delayConnectedCallback() || this.hasConnected) {
return;
}

this.setAttribute("animate", "true");
this.setAttribute("consumeoutsideclicks", "true");
this.setAttribute("incontentshell", "false");

this.addEventListener(
"popupshowing",
this.onPopupShowing.bind(this)
);

this.addEventListener("popupshown", this.onPopupShown.bind(this));

this.addEventListener("popuphiding", this.onPopupHiding.bind(this));

this.hasConnected = true;
}

ensureInitialized() {
if (this.shadowRoot.firstChild) return;

const style = document.createElement("link");
style.rel = "stylesheet";
style.href = "chrome://dot/content/widgets/xul-menupopup.css";

const container = document.createElement("div");
container.classList.add("browser-panel-container");

const slot = document.createElement("slot");

container.appendChild(slot);

super.shadowRoot.append(style, container);
}
}

customElements.define("menupopup", MozMenuPopup);

MozElements.MozMenuPopup = MozMenuPopup;
}
15 changes: 15 additions & 0 deletions components/panels/jar.mn
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,18 @@ dot.jar:

content/widgets/browser-panel-button.js (content/browser-panel-button.js)
content/widgets/browser-panel-button.css (content/browser-panel-button.css)

content/widgets/xul-menu.js (content/xul-menu.js)

content/widgets/xul-menuitem.js (content/xul-menuitem.js)
content/widgets/xul-menuitem.css (content/xul-menuitem.css)

content/widgets/xul-menupopup.js (content/xul-menupopup.js)
content/widgets/xul-menupopup.css (content/xul-menupopup.css)

% override chrome://global/content/menu.js chrome://dot/content/widgets/xul-menu.js
% override chrome://global/content/elements/menupopup.js chrome://dot/content/widgets/xul-menupopup.js

% override chrome://global/skin/popup.css chrome://dot/content/compat/blank.css
% override chrome://global/skin/menu.css chrome://dot/content/compat/blank.css
% override chrome://global/skin/menu-shared.css chrome://dot/content/compat/blank.css
Loading

0 comments on commit 9681aa9

Please sign in to comment.