Commit 1d9b7575 authored by Mike Conley's avatar Mike Conley
Browse files

Bug 1823438 - Make it possible for panel-list to get a minimum width from its anchor. r=hjones

With this patch, users of panel-list can have the list gain a minimum width from
the anchor element by setting min-width-from-anchor="" on the panel-list element.

Differential Revision: https://phabricator.services.mozilla.com/D173058
parent 15ef80c0
Loading
Loading
Loading
Loading
+34 −5
Original line number Diff line number Diff line
@@ -22,7 +22,7 @@ const openMenu = e => {
    .toggle(e);
};

const Template = ({ isOpen, items }) =>
const Template = ({ isOpen, items, wideAnchor }) =>
  html`
    <style>
      panel-item[icon="passwords"]::part(button) {
@@ -35,6 +35,9 @@ const Template = ({ isOpen, items }) =>
        position: absolute;
        background-image: url("chrome://global/skin/icons/more.svg");
      }
      button[wide] {
        width: 400px !important;
      }
      .end {
        inset-inline-end: 30px;
      }
@@ -43,14 +46,31 @@ const Template = ({ isOpen, items }) =>
        inset-block-end: 30px;
      }
    </style>
    <button class="ghost-button icon-button" @click=${openMenu}></button>
    <button class="ghost-button icon-button end" @click=${openMenu}></button>
    <button class="ghost-button icon-button bottom" @click=${openMenu}></button>
    <button
      class="ghost-button icon-button"
      @click=${openMenu}
      ?wide="${wideAnchor}"
    ></button>
    <button
      class="ghost-button icon-button end"
      @click=${openMenu}
      ?wide="${wideAnchor}"
    ></button>
    <button
      class="ghost-button icon-button bottom"
      @click=${openMenu}
      ?wide="${wideAnchor}"
    ></button>
    <button
      class="ghost-button icon-button bottom end"
      @click=${openMenu}
      ?wide="${wideAnchor}"
    ></button>
    <panel-list ?stay-open=${isOpen} ?open=${isOpen}>
    <panel-list
      ?stay-open=${isOpen}
      ?open=${isOpen}
      ?min-width-from-anchor=${wideAnchor}
    >
      ${items.map(i =>
        i == "<hr>"
          ? html`
@@ -73,6 +93,7 @@ const Template = ({ isOpen, items }) =>
export const Simple = Template.bind({});
Simple.args = {
  isOpen: false,
  wideAnchor: false,
  items: [
    "Item One",
    { text: "Item Two (accesskey w)", accesskey: "w" },
@@ -86,6 +107,7 @@ Simple.args = {
export const Icons = Template.bind({});
Icons.args = {
  isOpen: false,
  wideAnchor: false,
  items: [
    { text: "Passwords", icon: "passwords" },
    { text: "Settings", icon: "settings" },
@@ -95,5 +117,12 @@ Icons.args = {
export const Open = Template.bind({});
Open.args = {
  ...Simple.args,
  wideAnchor: false,
  isOpen: true,
};

export const Wide = Template.bind({});
Wide.args = {
  ...Simple.args,
  wideAnchor: true,
};
+1 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ skip-if = os == 'mac'
[test_panel_item_accesskey.html]
[test_panel_list_accessibility.html]
[test_panel_list_in_xul_panel.html]
[test_panel_list_min_width_from_anchor.html]
[test_popupanchor.xhtml]
skip-if = os == 'linux' || (verify && (os == 'win')) # Bug 1335894 perma-fail on linux 16.04
[test_popupreflows.xhtml]
+7 −2
Original line number Diff line number Diff line
@@ -51,7 +51,10 @@ add_task(async function testXULPanelOpenFromClicks() {
  await xulPanelShown;

  ok(panelList.hasAttribute("inxulpanel"), "Should have inxulpanel attribute set");
  ok(!panelList.hasAttribute("style"), "top/left inline styles should not be set.");

  let style = window.getComputedStyle(panelList);
  is(style.top, "0px", "computed top inline style should be 0px.");
  is(style.left, "0px", "computed left inline style should be 0px.");

  let xulPanelHidden = BrowserTestUtils.waitForPopupEvent(xulPanel, "hidden");
  let hidden = BrowserTestUtils.waitForEvent(panelList, "hidden");
@@ -68,7 +71,9 @@ add_task(async function testXULPanelOpenProgrammatically() {
  await xulPanelShown;

  ok(panelList.hasAttribute("inxulpanel"), "Should have inxulpanel attribute set");
  ok(!panelList.hasAttribute("style"), "top/left inline styles should not be set.");
  let style = window.getComputedStyle(panelList);
  is(style.top, "0px", "computed top inline style should be 0px.");
  is(style.left, "0px", "computed left inline style should be 0px.");

  let xulPanelHidden = BrowserTestUtils.waitForPopupEvent(xulPanel, "hidden");
  let hidden = BrowserTestUtils.waitForEvent(panelList, "hidden");
+70 −0
Original line number Diff line number Diff line
<!DOCTYPE HTML>
<!-- Any copyright is dedicated to the Public Domain.
     http://creativecommons.org/publicdomain/zero/1.0/ -->
<html>
<head>
  <title>Test Panel List Min-width From Anchor</title>
  <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
  <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
  <script type="text/javascript" src="head.js"></script>
  <link rel="stylesheet" href="chrome://global/skin/global.css" type="text/css"/>
  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>

<div id="content">
  <button id="anchor-button">This is a button with a long string to act as a wide anchor.</button>
  <panel-list id="panel-list">
    <panel-item>one</panel-item>
    <panel-item>two</panel-item>
    <panel-item>three</panel-item>
    <panel-item>four</panel-item>
    <panel-item>five</panel-item>
    <panel-item>six</panel-item>
  </panel-list>
</div>

<pre id="test">

<script class="testbody" type="application/javascript">
const {BrowserTestUtils} = ChromeUtils.importESModule("resource://testing-common/BrowserTestUtils.sys.mjs");
let anchorButton, panelList;

add_setup(function setup() {
  panelList = document.getElementById("panel-list");
  anchorButton = document.getElementById("anchor-button");
  anchorButton.addEventListener("click", e => panelList.toggle(e));
});

add_task(async function minWidthFromAnchor() {
  let anchorWidth = anchorButton.getBoundingClientRect().width;
  let shown = BrowserTestUtils.waitForEvent(panelList, "shown");
  synthesizeMouseAtCenter(anchorButton, {});
  await shown;

  let panelWidth = panelList.getBoundingClientRect().width;
  isnot(anchorWidth, panelWidth, "Without min-width-from-anchor, panel should not have anchor width.");

  let hidden = BrowserTestUtils.waitForEvent(panelList, "hidden");
  synthesizeKey("Escape", {});
  await hidden;

  panelList.toggleAttribute("min-width-from-anchor", true);

  shown = BrowserTestUtils.waitForEvent(panelList, "shown");
  synthesizeMouseAtCenter(anchorButton, {});
  await shown;

  panelWidth = panelList.getBoundingClientRect().width;
  is(anchorWidth, panelWidth, "With min-width-from-anchor, panel should have anchor width.");

  hidden = BrowserTestUtils.waitForEvent(panelList, "hidden");
  synthesizeKey("Escape", {});
  await hidden;
});

</script>
</pre>
</body>
</html>
+38 −33
Original line number Diff line number Diff line
@@ -179,11 +179,9 @@

    async setAlign() {
      const hostElement = this.parentElement || this.getRootNode().host;
      if (!hostElement || this.parentIsXULPanel()) {
      if (!hostElement) {
        // This could get called before we're added to the DOM.
        // Nothing to do in that case.
        //
        // And if we're embedded in a XUL panel, let it handle alignment.
        return;
      }

@@ -238,6 +236,8 @@
        );
      });

      // If we're embedded in a XUL panel, let it handle alignment.
      if (!this.parentIsXULPanel()) {
        // Calculate the left/right alignment.
        let align;
        let leftOffset;
@@ -271,6 +271,11 @@

        this.style.left = `${leftOffset + winScrollX}px`;
        this.style.top = `${topOffset + winScrollY}px`;
      }

      this.style.minWidth = this.hasAttribute("min-width-from-anchor")
        ? `${anchorWidth}px`
        : "";

      this.removeAttribute("showing");
    }