From 7d9d21f181904e13d090af72eeb5c367e45e6941 Mon Sep 17 00:00:00 2001 From: Hanna Jones Date: Wed, 6 Mar 2024 20:09:39 +0000 Subject: [PATCH] Bug 1880481 - Create a story for panel-list submenu r=reusable-components-reviewers,desktop-theme-reviewers,fxview-reviewers,emilio,sclements This patch adds a story for `panel-list` submenus to document how to create them. It also amends the README with a small code example, and moves the submenu slot creation out of the constructor to the connectedCallback, since we can't reliably read attribute values in custom element constructors. Differential Revision: https://phabricator.services.mozilla.com/D202012 --- .../components/firefoxview/firefoxview.css | 4 -- .../widgets/panel-list/README.stories.md | 22 ++++++- .../content/widgets/panel-list/panel-list.css | 4 ++ .../content/widgets/panel-list/panel-list.js | 59 +++++++++---------- .../widgets/panel-list/panel-list.stories.mjs | 45 ++++++++++---- 5 files changed, 87 insertions(+), 47 deletions(-) diff --git a/browser/components/firefoxview/firefoxview.css b/browser/components/firefoxview/firefoxview.css index b343e31a9826..6811ca54c4e7 100644 --- a/browser/components/firefoxview/firefoxview.css +++ b/browser/components/firefoxview/firefoxview.css @@ -148,10 +148,6 @@ panel-item::part(button):hover:active { background-color: var(--fxview-element-background-active); } -panel-list { - overflow-y: visible; -} - fxview-empty-state:not([isSelectedTab]) button[slot="primary-action"] { margin-inline-start: 0; } diff --git a/toolkit/content/widgets/panel-list/README.stories.md b/toolkit/content/widgets/panel-list/README.stories.md index b8800e2b5f7a..3e8617958eac 100644 --- a/toolkit/content/widgets/panel-list/README.stories.md +++ b/toolkit/content/widgets/panel-list/README.stories.md @@ -6,7 +6,7 @@ children and optional `hr` elements as separators. The `panel-list` will anchor itself to the target of the initiating event when opened with `panelList.toggle(event)`. -Note: Nested menus are not currently supported. XUL is currently required to +Note: XUL is currently required to support accesskey underlining (although using `moz-label` could change that). Shortcuts are not displayed automatically in the `panel-item`. @@ -229,3 +229,23 @@ grow larger than its containing window if needed. ``` + +### Submenus + +`panel-list` supports nested submenus. Submenus can be created by nesting a second `panel-list` in a `panel-item`'s `submenu` slot and specifying a `submenu` attribute on that `panel-item` that points to the nested list's ID. For example: + +```html + + No submenu + No submenu + + Has a submenu + + I'm a submenu item! + I'm also a submenu item! + + + +``` + +As of February 2024 submenus are only in use in Firefox View and support for nesting beyond one submenu may be limited. diff --git a/toolkit/content/widgets/panel-list/panel-list.css b/toolkit/content/widgets/panel-list/panel-list.css index 4358fc0cf855..619e6919a399 100644 --- a/toolkit/content/widgets/panel-list/panel-list.css +++ b/toolkit/content/widgets/panel-list/panel-list.css @@ -26,6 +26,10 @@ box-sizing: border-box; } +:host([has-submenu]) { + overflow-y: visible; +} + :host(:not([slot=submenu])) { max-height: 100%; } diff --git a/toolkit/content/widgets/panel-list/panel-list.js b/toolkit/content/widgets/panel-list/panel-list.js index 1cc1f865c3de..2e93b4ddc3e4 100644 --- a/toolkit/content/widgets/panel-list/panel-list.js +++ b/toolkit/content/widgets/panel-list/panel-list.js @@ -308,7 +308,7 @@ } addHideListeners() { - if (this.hasAttribute("stay-open") && !this.lastAnchorNode.hasSubmenu) { + if (this.hasAttribute("stay-open") && !this.lastAnchorNode?.hasSubmenu) { // This is intended for inspection in Storybook. return; } @@ -631,31 +631,12 @@ this.#defaultSlot = document.createElement("slot"); this.#defaultSlot.style.display = "none"; - if (this.hasSubmenu) { - this.icon = document.createElement("div"); - this.icon.setAttribute("class", "submenu-icon"); - this.label.setAttribute("class", "submenu-label"); - - this.button.setAttribute("class", "submenu-container"); - this.button.appendChild(this.icon); - - this.submenuSlot = document.createElement("slot"); - this.submenuSlot.name = "submenu"; - - this.shadowRoot.append( - style, - this.button, - this.#defaultSlot, - this.submenuSlot - ); - } else { - this.shadowRoot.append( - style, - this.button, - supportLinkSlot, - this.#defaultSlot - ); - } + this.shadowRoot.append( + style, + this.button, + supportLinkSlot, + this.#defaultSlot + ); } connectedCallback() { @@ -664,6 +645,10 @@ this._l10nRootConnected = true; } + this.panel = + this.getRootNode()?.host?.closest("panel-list") || + this.closest("panel-list"); + if (!this.#initialized) { this.#initialized = true; // When click listeners are added to the panel-item it creates a node in @@ -683,18 +668,28 @@ }); if (this.hasSubmenu) { + this.panel.setAttribute("has-submenu", ""); + this.icon = document.createElement("div"); + this.icon.setAttribute("class", "submenu-icon"); + this.label.setAttribute("class", "submenu-label"); + + this.button.setAttribute("class", "submenu-container"); + this.button.appendChild(this.icon); + + this.submenuSlot = document.createElement("slot"); + this.submenuSlot.name = "submenu"; + + this.shadowRoot.append(this.submenuSlot); + this.setSubmenuContents(); } } - this.panel = - this.getRootNode()?.host?.closest("panel-list") || - this.closest("panel-list"); - if (this.panel) { this.panel.addEventListener("hidden", this); this.panel.addEventListener("shown", this); } + if (this.hasSubmenu) { this.addEventListener("mouseenter", this); this.addEventListener("mouseleave", this); @@ -762,7 +757,9 @@ setSubmenuContents() { this.submenuPanel = this.submenuSlot.assignedNodes()[0]; - this.shadowRoot.append(this.submenuPanel); + if (this.submenuPanel) { + this.shadowRoot.append(this.submenuPanel); + } } get disabled() { diff --git a/toolkit/content/widgets/panel-list/panel-list.stories.mjs b/toolkit/content/widgets/panel-list/panel-list.stories.mjs index 9c5a4cbe1f2c..db0ab7597c0a 100644 --- a/toolkit/content/widgets/panel-list/panel-list.stories.mjs +++ b/toolkit/content/widgets/panel-list/panel-list.stories.mjs @@ -22,6 +22,9 @@ panel-list-checked = Checked panel-list-badged = Badged, look at me panel-list-passwords = Passwords panel-list-settings = Settings +submenu-item-one = Submenu Item One +submenu-item-two = Submenu Item Two +submenu-item-three = Submenu Item Three `, }, }; @@ -36,7 +39,7 @@ function openMenu(event) { } } -const Template = ({ isOpen, items, wideAnchor }) => +const Template = ({ isOpen, items, wideAnchor, hasSubMenu }) => html`