Bug 1461522 - Add doorhanger type to HTMLTooltip; r=jdescottes

MozReview-Commit-ID: 6Oq9qauwngX

--HG--
extra : rebase_source : 0e6d333aa10e1580840fe107a8812260d16d0379
This commit is contained in:
Brian Birtles 2018-06-28 15:04:13 +09:00
Родитель ae34b55b6a
Коммит b8e1efcc44
8 изменённых файлов: 652 добавлений и 33 удалений

Просмотреть файл

@ -13,6 +13,8 @@ support-files =
doc_html_tooltip.xul
doc_html_tooltip_arrow-01.xul
doc_html_tooltip_arrow-02.xul
doc_html_tooltip_doorhanger-01.xul
doc_html_tooltip_doorhanger-02.xul
doc_html_tooltip_hover.xul
doc_html_tooltip_rtl.xul
doc_inplace-editor_autocomplete_offset.xul
@ -138,6 +140,8 @@ skip-if = e10s # Bug 1221911, bug 1222289, frequent e10s timeouts
[browser_html_tooltip_arrow-01.js]
[browser_html_tooltip_arrow-02.js]
[browser_html_tooltip_consecutive-show.js]
[browser_html_tooltip_doorhanger-01.js]
[browser_html_tooltip_doorhanger-02.js]
[browser_html_tooltip_height-auto.js]
[browser_html_tooltip_hover.js]
[browser_html_tooltip_offset.js]

Просмотреть файл

@ -0,0 +1,91 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* import-globals-from helper_html_tooltip.js */
"use strict";
/**
* Test the HTMLTooltip "doorhanger" type's hang direction. It should hang
* towards the middle of the screen.
*/
const HTML_NS = "http://www.w3.org/1999/xhtml";
const TEST_URI = CHROME_URL_ROOT + "doc_html_tooltip_doorhanger-01.xul";
const {HTMLTooltip} =
require("devtools/client/shared/widgets/tooltip/HTMLTooltip");
loadHelperScript("helper_html_tooltip.js");
let useXulWrapper;
add_task(async function() {
// Force the toolbox to be 200px high;
await pushPref("devtools.toolbox.footer.height", 200);
await addTab("about:blank");
const [,, doc] = await createHost("bottom", TEST_URI);
info("Run tests for a Tooltip without using a XUL panel");
useXulWrapper = false;
await runTests(doc);
info("Run tests for a Tooltip with a XUL panel");
useXulWrapper = true;
await runTests(doc);
});
async function runTests(doc) {
info("Create HTML tooltip");
const tooltip = new HTMLTooltip(doc, {type: "doorhanger", useXulWrapper});
const div = doc.createElementNS(HTML_NS, "div");
div.style.width = "200px";
div.style.height = "35px";
tooltip.setContent(div);
const docBounds = doc.documentElement.getBoundingClientRect();
const elements = [...doc.querySelectorAll(".anchor")];
for (const el of elements) {
info("Display the tooltip on an anchor.");
await showTooltip(tooltip, el);
const arrow = tooltip.arrow;
ok(arrow, "Tooltip has an arrow");
// Get the geometry of the anchor, the tooltip panel & arrow.
const anchorBounds = el.getBoxQuads({ relativeTo: doc })[0].getBounds();
const panelBounds =
tooltip.panel.getBoxQuads({ relativeTo: doc })[0].getBounds();
const arrowBounds = arrow.getBoxQuads({ relativeTo: doc })[0].getBounds();
// Work out which side of the view the anchor is on.
const center = bounds => bounds.left + bounds.width / 2;
const anchorSide =
center(anchorBounds) < center(docBounds)
? "left"
: "right";
// Work out which direction the doorhanger hangs.
//
// We can do that just by checking which edge of the panel the center of the
// arrow is closer to.
const panelDirection =
center(arrowBounds) - panelBounds.left <
panelBounds.right - center(arrowBounds)
? "right"
: "left";
const params =
`document: ${docBounds.left}<->${docBounds.right}, ` +
`anchor: ${anchorBounds.left}<->${anchorBounds.right}, ` +
`panel: ${panelBounds.left}<->${panelBounds.right}, ` +
`anchor side: ${anchorSide}, ` +
`panel direction: ${panelDirection}`;
ok(anchorSide !== panelDirection,
`Doorhanger hangs towards center (${params})`);
await hideTooltip(tooltip);
}
tooltip.destroy();
}

Просмотреть файл

@ -0,0 +1,72 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* import-globals-from helper_html_tooltip.js */
"use strict";
/**
* Test the HTMLTooltip "doorhanger" type's arrow tip is precisely centered on
* the anchor when the anchor is small.
*/
const HTML_NS = "http://www.w3.org/1999/xhtml";
const TEST_URI = CHROME_URL_ROOT + "doc_html_tooltip_doorhanger-02.xul";
const {HTMLTooltip} =
require("devtools/client/shared/widgets/tooltip/HTMLTooltip");
loadHelperScript("helper_html_tooltip.js");
let useXulWrapper;
add_task(async function() {
// Force the toolbox to be 200px high;
await pushPref("devtools.toolbox.footer.height", 200);
await addTab("about:blank");
const [,, doc] = await createHost("bottom", TEST_URI);
info("Run tests for a Tooltip without using a XUL panel");
useXulWrapper = false;
await runTests(doc);
info("Run tests for a Tooltip with a XUL panel");
useXulWrapper = true;
await runTests(doc);
});
async function runTests(doc) {
info("Create HTML tooltip");
const tooltip = new HTMLTooltip(doc, {type: "doorhanger", useXulWrapper});
const div = doc.createElementNS(HTML_NS, "div");
div.style.width = "200px";
div.style.height = "35px";
tooltip.setContent(div);
const elements = [...doc.querySelectorAll(".anchor")];
for (const el of elements) {
info("Display the tooltip on an anchor.");
await showTooltip(tooltip, el);
const arrow = tooltip.arrow;
ok(arrow, "Tooltip has an arrow");
// Get the geometry of the anchor and arrow.
const anchorBounds = el.getBoxQuads({ relativeTo: doc })[0].getBounds();
const arrowBounds = arrow.getBoxQuads({ relativeTo: doc })[0].getBounds();
// Compare the centers
const center = bounds => bounds.left + bounds.width / 2;
const delta = Math.abs(center(anchorBounds) - center(arrowBounds));
const describeBounds = bounds =>
`${bounds.left}<--[${center(bounds)}]-->${bounds.right}`;
const params =
`anchor: ${describeBounds(anchorBounds)}, ` +
`arrow: ${describeBounds(arrowBounds)}`;
ok(delta < 1,
`Arrow center is roughly aligned with anchor center (${params})`);
await hideTooltip(tooltip);
}
tooltip.destroy();
}

Просмотреть файл

@ -0,0 +1,48 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/global.css"?>
<?xml-stylesheet href="chrome://devtools/skin/light-theme.css"?>
<window class="theme-light"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
title="Tooltip test">
<vbox flex="1" style="position: relative">
<!-- Left edge -->
<html:div class="anchor"
style="width:10px; height: 10px; position: absolute; background: red;
top: 0; left: 0;">
</html:div>
<!-- Not left edge but still left of center plus RTL direction (which should
no affect the hang direction) -->
<html:div class="anchor"
style="width:10px; height: 10px; position: absolute; background: red;
top: 0; left: 25px; direction: rtl">
</html:div>
<!-- Wide but still left of center -->
<html:div class="anchor"
style="width:80%; height: 10px; position: absolute; background: red;
top: 0; left: 50px;">
</html:div>
<!-- Right edge -->
<html:div class="anchor"
style="width:10px; height: 10px; position: absolute; background: red;
bottom: 0; right: 0;">
</html:div>
<!-- Not right edge but still right of center plus RTL direction (which should
no affect the hang direction) -->
<html:div class="anchor"
style="width:10px; height: 10px; position: absolute; background: red;
bottom: 0; right: 25px; direction: rtl">
</html:div>
<!-- Wide but still right of center -->
<html:div class="anchor"
style="width:80%; height: 10px; position: absolute; background: red;
bottom: 0; right: 50px;">
</html:div>
</vbox>
</window>

Просмотреть файл

@ -0,0 +1,34 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/global.css"?>
<?xml-stylesheet href="chrome://devtools/skin/light-theme.css"?>
<window class="theme-light"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
title="Tooltip test">
<vbox flex="1" style="position: relative">
<!-- Towards the left -->
<html:div class="anchor"
style="width:10px; height: 10px; position: absolute; background: red;
top: 0; left: 25px;">
</html:div>
<!-- Towards the left with RTL direction -->
<html:div class="anchor"
style="width:10px; height: 10px; position: absolute; background: red;
top: 0; left: 50px; direction: rtl;">
</html:div>
<!-- Towards the right -->
<html:div class="anchor"
style="width:10px; height: 10px; position: absolute; background: red;
bottom: 0; right: 25px;">
</html:div>
<!-- Towards the right with RTL direction -->
<html:div class="anchor"
style="width:10px; height: 10px; position: absolute; background: red;
bottom: 0; right: 50px; direction: rtl;">
</html:div>
</vbox>
</window>

Просмотреть файл

@ -24,24 +24,41 @@ module.exports.POSITION = POSITION;
const TYPE = {
NORMAL: "normal",
ARROW: "arrow",
DOORHANGER: "doorhanger",
};
module.exports.TYPE = TYPE;
const ARROW_WIDTH = 32;
const ARROW_WIDTH = {
"normal": 0,
"arrow": 32,
// This is the value calculated for the .tooltip-arrow element in tooltip.css
// which includes the arrow width (20px) plus the extra margin added so that
// the drop shadow is not cropped (2px each side).
"doorhanger": 24,
};
// Default offset between the tooltip's left edge and the tooltip arrow.
const ARROW_OFFSET = 20;
const ARROW_OFFSET = {
"normal": 0,
// Default offset between the tooltip's edge and the tooltip arrow.
"arrow": 20,
// Match other Firefox menus which use 10px from edge (but subtract the 2px
// margin included in the ARROW_WIDTH above).
"doorhanger": 8,
};
const EXTRA_HEIGHT = {
"normal": 0,
// The arrow is 16px tall, but merges on 3px with the panel border
"arrow": 13,
// The doorhanger arrow is 10px tall, but merges on 1px with the panel border
"doorhanger": 9,
};
const EXTRA_BORDER = {
"normal": 0,
"arrow": 3,
"doorhanger": 0,
};
/**
@ -120,12 +137,20 @@ const calculateVerticalPosition = (
* Bounding rectangle for the viewport. top/left can be different from
* 0 if some space should not be used by tooltips (for instance OS
* toolbars, taskbars etc.).
* @param {DOMRect} windowRect
* Bounding rectangle for the window. Used to determine which direction
* doorhangers should hang.
* @param {Number} width
* Preferred width for the tooltip.
* @param {String} type
* The tooltip type (e.g. "arrow").
* @param {Number} offset
* Horizontal offset in pixels.
* @param {Number} borderRadius
* The border radius of the panel. This is added to ARROW_OFFSET to
* calculate the distance from the edge of the tooltip to the start
* of arrow. It is separate from ARROW_OFFSET since it will vary by
* platform.
* @param {Boolean} isRtl
* If the anchor is in RTL, the tooltip should be aligned to the right.
* @return {Object}
@ -136,13 +161,38 @@ const calculateVerticalPosition = (
const calculateHorizontalPosition = (
anchorRect,
viewportRect,
windowRect,
width,
type,
offset,
borderRadius,
isRtl
) => {
// Which direction should the tooltip go?
const hangDirection = isRtl ? "left" : "right";
//
// For tooltips we follow the writing direction but for doorhangers the
// guidelines[1] say that,
//
// "Doorhangers opening on the right side of the view show the directional
// arrow on the right.
//
// Doorhangers opening on the left side of the view show the directional
// arrow on the left.
//
// Never place the directional arrow at the center of doorhangers."
//
// [1] https://design.firefox.com/photon/components/doorhangers.html#directional-arrow
//
// So for those we need to check if the anchor is more right or left.
let hangDirection;
if (type === TYPE.DOORHANGER) {
const anchorCenter = anchorRect.left + anchorRect.width / 2;
const viewCenter = windowRect.left + windowRect.width / 2;
hangDirection = anchorCenter >= viewCenter ? "left" : "right";
} else {
hangDirection = isRtl ? "left" : "right";
}
const anchorWidth = anchorRect.width;
// Calculate logical start of anchor relative to the viewport.
@ -160,12 +210,14 @@ const calculateHorizontalPosition = (
tooltipStart = Math.max(0, tooltipStart);
// Calculate arrow start (tooltip's start might be updated)
const arrowWidth = type === TYPE.ARROW ? ARROW_WIDTH : 0;
const arrowWidth = ARROW_WIDTH[type];
let arrowStart;
// Arrow style tooltips may need to be shifted
if (type === TYPE.ARROW) {
// Arrow and doorhanger style tooltips may need to be shifted
if (type === TYPE.ARROW || type === TYPE.DOORHANGER) {
const arrowOffset = ARROW_OFFSET[type] + borderRadius;
// Where will the point of the arrow be if we apply the standard offset?
const arrowCenter = tooltipStart + ARROW_OFFSET + arrowWidth / 2;
const arrowCenter = tooltipStart + arrowOffset + arrowWidth / 2;
// How does that compare to the center of the anchor?
const anchorCenter = anchorStart + anchorWidth / 2;
@ -175,12 +227,12 @@ const calculateHorizontalPosition = (
tooltipStart = Math.max(0, tooltipStart - (arrowCenter - anchorCenter));
}
// Arrow's start offset relative to the anchor.
arrowStart = Math.min(ARROW_OFFSET, (anchorWidth - arrowWidth) / 2) | 0;
arrowStart = Math.min(arrowOffset, (anchorWidth - arrowWidth) / 2) | 0;
// Translate the coordinate to tooltip container
arrowStart += anchorStart - tooltipStart;
// Make sure the arrow remains in the tooltip container.
arrowStart = Math.min(arrowStart, tooltipWidth - arrowWidth);
arrowStart = Math.max(arrowStart, 0);
arrowStart = Math.min(arrowStart, tooltipWidth - arrowWidth - borderRadius);
arrowStart = Math.max(arrowStart, borderRadius);
}
// Convert from logical coordinates to physical
@ -232,7 +284,8 @@ const getRelativeRect = function(node, relativeTo) {
* The toolbox document to attach the HTMLTooltip popup.
* @param {Object}
* - {String} type
* Display type of the tooltip. Possible values: "normal", "arrow"
* Display type of the tooltip. Possible values: "normal", "arrow", and
* "doorhanger".
* - {Boolean} autofocus
* Defaults to false. Should the tooltip be focused when opening it.
* - {Boolean} consumeOutsideClicks
@ -375,8 +428,7 @@ HTMLTooltip.prototype = {
anchorRect = this._convertToScreenRect(anchorRect);
}
// Get viewport size
const viewportRect = this._getViewportRect();
const { viewportRect, windowRect } = this._getBoundingRects();
// Calculate the horizonal position and width
let preferredWidth;
@ -399,9 +451,29 @@ HTMLTooltip.prototype = {
}
const anchorWin = anchor.ownerDocument.defaultView;
const isRtl = anchorWin.getComputedStyle(anchor).direction === "rtl";
const anchorCS = anchorWin.getComputedStyle(anchor);
const isRtl = anchorCS.direction === "rtl";
let borderRadius = 0;
if (this.type === TYPE.DOORHANGER) {
borderRadius = parseFloat(
anchorCS.getPropertyValue("--theme-arrowpanel-border-radius")
);
if (Number.isNaN(borderRadius)) {
borderRadius = 0;
}
}
const {left, width, arrowLeft} = calculateHorizontalPosition(
anchorRect, viewportRect, preferredWidth, this.type, x, isRtl);
anchorRect,
viewportRect,
windowRect,
preferredWidth,
this.type,
x,
borderRadius,
isRtl
);
// If we constrained the width, then any measured height we have is no
// longer valid.
@ -411,10 +483,22 @@ HTMLTooltip.prototype = {
// Apply width and arrow positioning
this.container.style.width = width + "px";
if (this.type === TYPE.ARROW) {
if (this.type === TYPE.ARROW || this.type === TYPE.DOORHANGER) {
this.arrow.style.left = arrowLeft + "px";
}
// Work out how much vertical margin we have.
//
// This relies on us having set either .tooltip-top or .tooltip-bottom
// and on the margins for both being symmetrical. Fortunately the call to
// _measureContainerSize above will set .tooltip-top for us and it also
// assumes these styles are symmetrical so this should be ok.
const panelWindow = this.panel.ownerDocument.defaultView;
const panelComputedStyle = panelWindow.getComputedStyle(this.panel);
const verticalMargin =
parseFloat(panelComputedStyle.marginTop) +
parseFloat(panelComputedStyle.marginBottom);
// Calculate the vertical position and height
let preferredHeight;
if (this.preferredHeight === "auto") {
@ -424,8 +508,12 @@ HTMLTooltip.prototype = {
} else {
({ height: preferredHeight } = this._measureContainerSize());
}
preferredHeight += verticalMargin;
} else {
const themeHeight = EXTRA_HEIGHT[this.type] + 2 * EXTRA_BORDER[this.type];
const themeHeight =
EXTRA_HEIGHT[this.type] +
verticalMargin +
2 * EXTRA_BORDER[this.type];
preferredHeight = this.preferredHeight + themeHeight;
}
@ -467,22 +555,47 @@ HTMLTooltip.prototype = {
},
/**
* Calculate the rect of the viewport that limits the tooltip dimensions. When using a
* XUL panel wrapper, the viewport will be able to use the whole screen (excluding space
* reserved by the OS for toolbars etc.). Otherwise, the viewport is limited to the
* tooltip's document.
* Calculate the following boundary rectangles:
*
* @return {Object} DOMRect-like object with the Number properties: top, right, bottom,
* left, width, height
* - Viewport rect: This is the region that limits the tooltip dimensions.
* When using a XUL panel wrapper, the tooltip will be able to use the whole
* screen (excluding space reserved by the OS for toolbars etc.) and hence
* the result will be in screen coordinates.
* Otherwise, the tooltip is limited to the tooltip's document.
*
* - Window rect: This is the bounds of the view in which the tooltip is
* presented. It is reported in the same coordinates as the viewport
* rect and is used for determining in which direction a doorhanger-type
* tooltip should "hang".
* When using the XUL panel wrapper this will be the dimensions of the
* window in screen coordinates. Otherwise it will be the same as the
* viewport rect.
*
* @return {Object} An object with the following properties
* viewportRect {Object} DOMRect-like object with the Number
* properties: top, right, bottom, left, width, height
* representing the viewport rect.
* windowRect {Object} DOMRect-like object with the Number
* properties: top, right, bottom, left, width, height
* representing the viewport rect.
*/
_getViewportRect: function() {
_getBoundingRects: function() {
let viewportRect;
let windowRect;
if (this.useXulWrapper) {
// availLeft/Top are the coordinates first pixel available on the screen for
// applications (excluding space dedicated for OS toolbars, menus etc...)
// availWidth/Height are the dimensions available to applications excluding all
// the OS reserved space
const {availLeft, availTop, availHeight, availWidth} = this.doc.defaultView.screen;
return {
// availLeft/Top are the coordinates first pixel available on the screen
// for applications (excluding space dedicated for OS toolbars, menus
// etc...)
// availWidth/Height are the dimensions available to applications
// excluding all the OS reserved space
const {
availLeft,
availTop,
availHeight,
availWidth,
} = this.doc.defaultView.screen;
viewportRect = {
top: availTop,
right: availLeft + availWidth,
bottom: availTop + availHeight,
@ -490,9 +603,27 @@ HTMLTooltip.prototype = {
width: availWidth,
height: availHeight,
};
const {
screenX,
screenY,
outerWidth,
outerHeight,
} = this.doc.defaultView;
windowRect = {
top: screenY,
right: screenX + outerWidth,
bottom: screenY + outerHeight,
left: screenX,
width: outerWidth,
height: outerHeight,
};
} else {
viewportRect = windowRect =
this.doc.documentElement.getBoundingClientRect();
}
return this.doc.documentElement.getBoundingClientRect();
return { viewportRect, windowRect };
},
_measureContainerSize: function() {
@ -573,7 +704,7 @@ HTMLTooltip.prototype = {
let html = '<div class="tooltip-filler"></div>';
html += '<div class="tooltip-panel"></div>';
if (this.type === TYPE.ARROW) {
if (this.type === TYPE.ARROW || this.type === TYPE.DOORHANGER) {
html += '<div class="tooltip-arrow"></div>';
}
// eslint-disable-next-line no-unsanitized/property

Просмотреть файл

@ -262,6 +262,212 @@
transform: rotate(45deg);
}
/* Tooltip : doorhanger style */
:root {
--theme-arrowpanel-border-radius: 0px;
}
:root[platform="mac"] {
--theme-arrowpanel-border-radius: 3.5px;
}
.tooltip-container[type="doorhanger"] > .tooltip-panel {
padding: 4px 0;
color: var(--theme-arrowpanel-color);
margin: 4px;
max-width: 320px;
}
.tooltip-container[type="doorhanger"] > .tooltip-panel,
.tooltip-container[type="doorhanger"] > .tooltip-arrow::before {
background: var(--theme-arrowpanel-background);
border: 1px solid var(--theme-arrowpanel-border-color);
border-radius: var(--theme-arrowpanel-border-radius);
box-shadow: 0 0 4px hsla(210,4%,10%,.2);
}
:root[platform="mac"] .tooltip-container[type="doorhanger"] > .tooltip-panel,
:root[platform="mac"] .tooltip-container[type="doorhanger"] > .tooltip-arrow::before {
box-shadow: none;
/*
* The above should be:
*
* box-shadow: 0 0 0 1px var(--theme-arrowpanel-border-color);
*
* but although that gives the right emphasis to the border it makes the
* platform shadow much too dark.
*/
}
:root[platform="mac"].theme-light .tooltip-container[type="doorhanger"] > .tooltip-panel,
:root[platform="mac"].theme-light .tooltip-container[type="doorhanger"] > .tooltip-arrow::before {
border: none;
}
.tooltip-container[type="doorhanger"] > .tooltip-arrow {
/* Desired width of the arrow */
--arrow-width: 20px;
/* Amount of room to allow for the shadow. Should be about half the radius. */
--shadow-radius: 4px;
--shadow-margin: calc(var(--shadow-radius) / 2);
/*
* Crop the arrow region to show half the arrow plus allow room for margins.
*
* The ARROW_WIDTH in HTMLTooltip.js needs to match the following value.
*/
width: calc(var(--arrow-width) + 2 * var(--shadow-margin));
height: calc(var(--arrow-width) / 2 + var(--shadow-margin));
}
.tooltip-container[type="doorhanger"] > .tooltip-arrow::before {
/* Make sure the border is included in the size */
box-sizing: border-box;
/* Don't inherit any rounded corners. */
border-radius: 0;
/*
* When the box is rotated, it should have width <arrow-width>.
* That makes the length of one side of the box equal to:
*
* (<arrow-width> / 2) / sin 45
*/
--sin-45: 0.707106781;
--square-side: calc(var(--arrow-width) / 2 / var(--sin-45));
width: var(--square-side);
height: var(--square-side);
/*
* The rotated square will overshoot the left side
* and need to be shifted in by:
*
* (<arrow-width> - square side) / 2
*
* But we also want to shift it in so that the box-shadow
* is not clipped when we clip the parent so we add
* a suitable margin for that.
*/
--overhang: calc((var(--arrow-width) - var(--square-side)) / 2);
margin-left: calc(var(--overhang) + var(--shadow-margin));
}
.tooltip-container[type="doorhanger"].tooltip-top > .tooltip-panel {
/* Drop the margin between the doorhanger and the arrow. */
margin-bottom: 0;
}
.tooltip-container[type="doorhanger"].tooltip-bottom > .tooltip-panel {
/* Drop the margin between the doorhanger and the arrow. */
margin-top: 0;
}
.tooltip-container[type="doorhanger"].tooltip-top > .tooltip-arrow {
/* Overlap the arrow with the 1px border of the doorhanger */
margin-top: -1px;
}
.tooltip-container[type="doorhanger"].tooltip-bottom > .tooltip-arrow {
/* Overlap the arrow with the 1px border of the doorhanger */
margin-bottom: -1px;
}
.tooltip-container[type="doorhanger"].tooltip-top > .tooltip-arrow::before {
/* Show only the bottom half of the box */
margin-top: calc(var(--square-side) / -2);
}
.tooltip-container[type="doorhanger"].tooltip-bottom > .tooltip-arrow::before {
/* Shift the rotated box in so that it is not clipped */
margin-top: calc(var(--overhang) + var(--shadow-margin));
}
.tooltip-container[type="doorhanger"] .tooltip-panel ul {
/* Override the display: -moz-box declaration in minimal-xul.css
* or else menu items won't stack. */
display: block;
}
.tooltip-container[type="doorhanger"] .menuitem > .command {
display: flex;
align-items: baseline;
margin: 0;
padding: 4px 12px;
outline: none;
}
.tooltip-container[type="doorhanger"] .menuitem > button.command:-moz-any([role="menuitem"],[role="menuitemcheckbox"]) {
-moz-appearance: none;
border: none;
color: var(--theme-arrowpanel-color);
background-color: transparent;
text-align: start;
width: 100%;
}
.tooltip-container[type="doorhanger"] .menuitem > .command:not(:-moz-any([disabled],[open],:active)):-moz-any(:hover,:focus) {
background-color: var(--theme-arrowpanel-dimmed);
}
.tooltip-container[type="doorhanger"] .menuitem > .command:-moz-focusring::-moz-focus-inner {
border-color: transparent;
}
.tooltip-container[type="doorhanger"] .menuitem > .command:not([disabled]):-moz-any([open],:hover:active) {
background-color: var(--theme-arrowpanel-dimmed-further);
box-shadow: 0 1px 0 hsla(210,4%,10%,.03) inset;
}
.tooltip-container[type="doorhanger"] .menuitem > .command[aria-checked="true"] {
list-style-image: none;
-moz-context-properties: fill;
fill: currentColor;
background: url(chrome://browser/skin/check.svg) no-repeat transparent;
background-size: 11px 11px;
background-position: center left 7px;
}
.tooltip-container[type="doorhanger"] .menuitem > .command[aria-checked="true"]:-moz-locale-dir(rtl) {
background-position: center right 7px;
}
.tooltip-container[type="doorhanger"] .menuitem > .command > .label {
flex: 1;
padding-inline-start: 16px;
font: menu;
}
.tooltip-container[type="doorhanger"] .menuitem > .command.iconic > .label::before {
content: " ";
display: inline-block;
margin-inline-end: 8px;
width: 16px;
height: 16px;
vertical-align: top;
-moz-context-properties: fill;
fill: currentColor;
/*
* The icons in the sidebar menu have opacity: 0.8 here, but those in the
* hamburger menu don't. For now we match the hamburger menu styling,
* especially because the 80% opacity makes the icons look dull in dark mode.
*/
}
.tooltip-container[type="doorhanger"] .menuitem > .command > .accelerator {
margin-inline-start: 10px;
color: var(--theme-arrowpanel-disabled-color);
font: message-box;
}
.tooltip-container[type="doorhanger"] hr {
display: block;
border: none;
border-top: 1px solid var(--theme-arrowpanel-separator);
margin: 6px 0;
padding: 0;
}
/* Tooltip: Events */
.event-header {

Просмотреть файл

@ -93,6 +93,17 @@
--theme-tooltip-background: rgba(255, 255, 255, .9);
--theme-tooltip-shadow: rgba(155, 155, 155, 0.26);
/* Doorhangers */
/* These colors are based on the colors used for doorhangers elsewhere in
* Firefox. */
--theme-arrowpanel-background: white;
--theme-arrowpanel-color: -moz-fieldText;
--theme-arrowpanel-border-color: var(--grey-90-a20);
--theme-arrowpanel-separator: var(--grey-90-a20);
--theme-arrowpanel-dimmed: hsla(0,0%,80%,.3);
--theme-arrowpanel-dimmed-further: hsla(0,0%,80%,.45);
--theme-arrowpanel-disabled-color: GrayText;
/* Command line */
--theme-command-line-image: url(chrome://devtools/skin/images/commandline-icon.svg#light-theme);
--theme-command-line-image-focus: url(chrome://devtools/skin/images/commandline-icon.svg#light-theme-focus);
@ -101,6 +112,16 @@
--theme-messageCloseButtonFilter: invert(0);
}
/*
* For doorhangers elsewhere in Fireflox, Mac uses a fixed color different to
* -moz-fieldText and a slightly lighter border color (presumably since it
* combines with the platform shadow).
*/
:root[platform="mac"].theme-light {
--theme-arrowpanel-color: rgb(26,26,26);
--theme-arrowpanel-border-color: hsla(210,4%,10%,.05);
}
:root.theme-dark {
--theme-body-background: var(--grey-80);
--theme-sidebar-background: #1B1B1D;
@ -180,6 +201,17 @@
--theme-tooltip-background: rgba(19, 28, 38, .9);
--theme-tooltip-shadow: rgba(25, 25, 25, 0.76);
/* Doorhangers */
/* These colors are based on the colors used for doorhangers elsewhere in
* Firefox. */
--theme-arrowpanel-background: var(--grey-60);
--theme-arrowpanel-color: rgb(249,249,250);
--theme-arrowpanel-border-color: #27272b;
--theme-arrowpanel-separator: rgba(249,249,250,.1);
--theme-arrowpanel-dimmed: rgba(249,249,250,.1);
--theme-arrowpanel-dimmed-further: rgba(249,249,250,.15);
--theme-arrowpanel-disabled-color: rgba(249,249,250,.5);
/* Command line */
--theme-command-line-image: url(chrome://devtools/skin/images/commandline-icon.svg#dark-theme);
--theme-command-line-image-focus: url(chrome://devtools/skin/images/commandline-icon.svg#dark-theme-focus);
@ -252,5 +284,6 @@
--grey-80: #2a2a2e;
--grey-90: #0c0c0d;
--grey-90-a10: rgba(12, 12, 13, 0.1);
--grey-90-a20: rgba(12, 12, 13, 0.2);
--grey-90-a80: rgba(12, 12, 13, 0.8);
}