Bug 1381819 - Align exception/xhr/group arrows with ones in ObjectInspector; r=bgrins.
We now use the same image for the arrow, and the console component which render
this arrow was changed for consistency with the objectInspector naming.
Some alignment properties needed to be changed so everything lines up perfectly.
Tests were updated to match the new arrow classnames.
MozReview-Commit-ID: 2JFAyv8YbTa
--- a/devtools/client/themes/webconsole.css
+++ b/devtools/client/themes/webconsole.css
@@ -1208,24 +1208,55 @@ body #output-container {
border-inline-start-color: var(--console-output-indent-border-color);
}
.webconsole-output-wrapper .object-inspector.tree .tree-node:hover:not(.focused) {
background-color: var(--object-inspector-hover-background);
}
/*
- * Make the arrow the same color and approximately the same size of the twisty icon.
- * Should be properly fixed in https://bugzilla.mozilla.org/show_bug.cgi?id=1307937.
+ * Make console.group, exception and XHR message's arrow look the same as the arrow
+ * used in the ObjectInspector (same background-image, width, transition).
+ * Properties were copied from devtools/client/shared/components/reps/reps.css.
*/
-.webconsole-output-wrapper .object-inspector.tree .tree-node .arrow {
+.webconsole-output-wrapper img.collapse-button.arrow {
+ mask: url("chrome://devtools/skin/images/devtools-components/arrow.svg") no-repeat;
+ mask-size: 100%;
+ width: 9px;
+ height: 9px;
+ margin-block-start: 5px;
+ margin-inline-start: 4px;
+ margin-inline-end: 1px;
+ transform: rotate(-90deg);
+ transition: transform 0.125s ease;
+}
+
+/*
+ * We need to override the margin for group arrow in order to keep the alignment
+ * with the indent border.
+ */
+.webconsole-output-wrapper .message.startGroup img.collapse-button.arrow,
+.webconsole-output-wrapper .message.startGroupCollapsed img.collapse-button.arrow {
+ margin-inline-start: 2px;
+}
+
+html[dir="rtl"] .webconsole-output-wrapper img.collapse-button.arrow:not(.expanded) {
+ transform: rotate(90deg);
+}
+
+.webconsole-output-wrapper img.collapse-button.arrow.expanded {
+ transform: rotate(0deg);
+}
+
+/* Apply the same color to both message arrows and ObjectInspector ones. */
+.webconsole-output-wrapper .message img.arrow {
background-color: #AFA8AB;
}
-.theme-dark .webconsole-output-wrapper .object-inspector.tree .tree-node .arrow {
+.theme-dark .webconsole-output-wrapper .message img.arrow {
background-color: #7F7E81;
}
/* Sidebar */
.sidebar {
display: flex;
grid-row: 1 / -1;
grid-column: -1 / -2;
--- a/devtools/client/webconsole/new-console-output/components/CollapseButton.js
+++ b/devtools/client/webconsole/new-console-output/components/CollapseButton.js
@@ -13,22 +13,22 @@ const messageToggleDetails = l10n.getStr
function CollapseButton(props) {
const {
open,
onClick,
title = messageToggleDetails,
} = props;
- let classes = ["theme-twisty"];
+ let classes = ["arrow", "collapse-button"];
if (open) {
- classes.push("open");
+ classes.push("expanded");
}
- return dom.a({
+ return dom.img({
className: classes.join(" "),
onClick,
title: title,
});
}
module.exports = CollapseButton;
--- a/devtools/client/webconsole/new-console-output/test/components/console-api-call.test.js
+++ b/devtools/client/webconsole/new-console-output/test/components/console-api-call.test.js
@@ -290,17 +290,17 @@ describe("ConsoleAPICall component:", ()
});
describe("console.group", () => {
it("renders", () => {
const message = stubPreparedMessages.get("console.group('bar')");
const wrapper = render(ConsoleApiCall({ message, serviceContainer, open: true }));
expect(wrapper.find(".message-body").text()).toBe("bar");
- expect(wrapper.find(".theme-twisty.open").length).toBe(1);
+ expect(wrapper.find(".collapse-button.expanded").length).toBe(1);
});
it("renders group with custom style", () => {
const message = stubPreparedMessages.get("console.group(%cfoo%cbar)");
const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
expect(wrapper.find(".message-body").text()).toBe("foobar");
const elements = wrapper.find(".objectBox-string");
@@ -330,32 +330,32 @@ describe("ConsoleAPICall component:", ()
let wrapper = mount(Provider({store},
ConsoleApiCall({
message,
open: true,
dispatch: store.dispatch,
serviceContainer,
})
));
- wrapper.find(".theme-twisty.open").simulate("click");
+ wrapper.find(".collapse-button.expanded").simulate("click");
let call = store.dispatch.getCall(0);
expect(call.args[0]).toEqual({
id: message.id,
type: MESSAGE_CLOSE
});
wrapper = mount(Provider({store},
ConsoleApiCall({
message,
open: false,
dispatch: store.dispatch,
serviceContainer,
})
));
- wrapper.find(".theme-twisty").simulate("click");
+ wrapper.find(".collapse-button").simulate("click");
call = store.dispatch.getCall(1);
expect(call.args[0]).toEqual({
id: message.id,
type: MESSAGE_OPEN
});
});
it("toggle the group when the group name is clicked", () => {
@@ -423,17 +423,17 @@ describe("ConsoleAPICall component:", ()
});
describe("console.groupCollapsed", () => {
it("renders", () => {
const message = stubPreparedMessages.get("console.groupCollapsed('foo')");
const wrapper = render(ConsoleApiCall({ message, serviceContainer, open: false}));
expect(wrapper.find(".message-body").text()).toBe("foo");
- expect(wrapper.find(".theme-twisty:not(.open)").length).toBe(1);
+ expect(wrapper.find(".collapse-button:not(.expanded)").length).toBe(1);
});
it("renders group with custom style", () => {
const message = stubPreparedMessages.get("console.groupCollapsed(%cfoo%cbaz)");
const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
const elements = wrapper.find(".objectBox-string");
expect(elements.text()).toBe("foobaz");
--- a/devtools/client/webconsole/new-console-output/test/components/page-error.test.js
+++ b/devtools/client/webconsole/new-console-output/test/components/page-error.test.js
@@ -109,17 +109,17 @@ describe("PageError component:", () => {
expect(call.args[0]).toEqual(message.exceptionDocURL);
});
it("has a stacktrace which can be openned", () => {
const message = stubPreparedMessages.get("ReferenceError: asdf is not defined");
const wrapper = render(PageError({ message, serviceContainer, open: true }));
// There should be a collapse button.
- expect(wrapper.find(".theme-twisty.open").length).toBe(1);
+ expect(wrapper.find(".collapse-button.expanded").length).toBe(1);
// There should be five stacktrace items.
const frameLinks = wrapper.find(`.stack-trace span.frame-link`);
expect(frameLinks.length).toBe(5);
});
it("toggle the stacktrace when the collapse button is clicked", () => {
const store = setupStore();
@@ -129,32 +129,32 @@ describe("PageError component:", () => {
let wrapper = mount(Provider({store},
PageError({
message,
open: true,
dispatch: store.dispatch,
serviceContainer,
})
));
- wrapper.find(".theme-twisty.open").simulate("click");
+ wrapper.find(".collapse-button.expanded").simulate("click");
let call = store.dispatch.getCall(0);
expect(call.args[0]).toEqual({
id: message.id,
type: MESSAGE_CLOSE
});
wrapper = mount(Provider({store},
PageError({
message,
open: false,
dispatch: store.dispatch,
serviceContainer,
})
));
- wrapper.find(".theme-twisty").simulate("click");
+ wrapper.find(".collapse-button").simulate("click");
call = store.dispatch.getCall(1);
expect(call.args[0]).toEqual({
id: message.id,
type: MESSAGE_OPEN
});
});
it("has the expected indent", () => {
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_console_group.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_console_group.js
@@ -100,17 +100,17 @@ function testIndent(node, indent) {
async function testGroupToggle({
node,
store,
shouldBeOpen,
visibleMessageIdsAfterExpand,
visibleMessageIdsAfterCollapse
}) {
- let toggleArrow = node.querySelector(".theme-twisty");
+ let toggleArrow = node.querySelector(".collapse-button");
const isOpen = node2 => node2.classList.contains("open");
const assertVisibleMessageIds = (expanded) => {
let visibleMessageIds = store.getState().messages.visibleMessages;
expanded ? is(visibleMessageIds.toString(), visibleMessageIdsAfterExpand.toString()) :
is(visibleMessageIds.toString(), visibleMessageIdsAfterCollapse.toString());
};
await waitFor(() => isOpen(node) === shouldBeOpen);