Bug 1459581 - CSS and class names refactor, and fix UI glitch when sw scope is too long. r=jdescottes

This was a good time to revamp of the CSS layout we were using in the
Worker component. Changes that have been made:

- Use CSS Grid to layout the Worker component
- Rename classes to use BEM style (this is compatible with the current
  CSS guidelines for the DevTools).
- Use classes with the js- prefix for JS hooks
- Rename classes / use js- class names for hooks in other components,
  so everything is consistent.
- Some HTML markup has been fixed, where it wasn't in conflict with
  the current styling.

MozReview-Commit-ID: Doyd9mBLOMd

--HG--
extra : rebase_source : 68f0a2df08f8c1c1c958f17096bf12fbca8f6f62
This commit is contained in:
Belén Albeza 2018-05-08 17:24:52 +02:00
Родитель 5424a4d26a
Коммит 03d031315e
13 изменённых файлов: 143 добавлений и 98 удалений

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

@ -2,6 +2,38 @@
* 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/. */
/*
* General styles
*/
:root[platform="linux"],
:root[platform="linux"] button {
font-size: 11px;
}
h1 {
font-size: 22px;
font-weight: normal;
}
a {
margin: 0 10px;
}
a,
a:hover,
a:visited {
color: var(--blue-60) !important;
cursor: pointer;
}
a.disabled,
a.disabled:hover,
a.disabled:visited {
color: var(--grey-30) !important;
cursor: default;
}
/*
* The current layout of the application panel is
*
@ -17,32 +49,12 @@
*/
.application {
height: 100%;
padding: 0 0 0 20px;
padding: 0 20px;
overflow: auto;
display: flex;
flex-direction: column;
}
.application.empty {
.application--empty {
background-color: var(--grey-30);
}
h1 {
font-size: 22px;
font-weight: normal;
}
a,
a:hover,
a:visited {
color: var(--blue-60) !important;
margin: 0 10px;
cursor: pointer;
}
a.disabled,
a.disabled:hover,
a.disabled:visited {
color: var(--grey-30) !important;
cursor: default;
}

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

@ -7,7 +7,7 @@
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const { createFactory, Component } = require("devtools/client/shared/vendor/react");
const { connect } = require("devtools/client/shared/vendor/react-redux");
const { div } = require("devtools/client/shared/vendor/react-dom-factories");
const { main } = require("devtools/client/shared/vendor/react-dom-factories");
const WorkerList = createFactory(require("./WorkerList"));
const WorkerListEmpty = createFactory(require("./WorkerListEmpty"));
@ -33,8 +33,8 @@ class App extends Component {
const isEmpty = workers.length === 0;
return (
div(
{ className: `application ${isEmpty ? "empty" : ""}` },
main(
{ className: `application ${isEmpty ? "application--empty" : ""}` },
isEmpty
? WorkerListEmpty({ serviceContainer })
: WorkerList({ workers, client, serviceContainer })

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

@ -6,42 +6,65 @@
* The current layout of a service worker item is
*
* +----------------------------+----------------+
* | Service worker scope | Unregister btn |
* | Service worker scope | Unregister_btn |
* +---+----------+-------------+----------------|
* | | "Source" | script name | debug link |
* | |----------+-------------+----------------|
* | | "Status" | status | start link |
* | "Source" | script_name debug_link |
* |--------------+-------------+----------------|
* | "Status" | status start_link |
* +---+----------+-------------+----------------|
*/
.service-worker-container {
margin-bottom: 20px;
.worker {
display: grid;
grid-template-rows: auto auto auto;
grid-template-columns: auto 1fr;
width: 100%;
max-width: 600px;
position: relative;
grid-column-gap: 0;
padding: 1rem 0;
line-height: 1.5;
font-size: 13px;
font-size: 1.2rem;
}
.service-worker-container > .service-worker-scope {
padding-inline-start: 30px;
.worker:first-child {
padding-top: 0;
}
.service-worker-container > :not(.service-worker-scope) {
padding-inline-start: 70px;
.worker:not(:last-child) {
border-bottom: 1px solid var(--grey-30);
}
.service-worker-scope {
.worker__header {
grid-column: 1/3;
display: grid;
grid-template-columns: 1fr auto;
grid-column-gap: 2rem;
align-items: center;
}
.worker__scope {
font-weight: bold;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.service-worker-meta-name {
.worker__data {
display: grid;
grid-template-columns: auto 1fr;
grid-column-gap: 1rem;
}
.worker__data > * {
margin: 0;
}
.worker__meta-name {
color: var(--grey-50);
min-width: 50px;
margin-inline-end: 10px;
display: inline-block;
padding-inline-start: 4.5rem;
}
.unregister-button {
position: absolute;
right: 0;
.worker__unregister-button {
/* TODO: remove this once/if we have proper capitalization in the strings file */
text-transform: capitalize;
}

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

@ -6,7 +6,7 @@
const { Component } = require("devtools/client/shared/vendor/react");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const { a, button, div, li, span } = require("devtools/client/shared/vendor/react-dom-factories");
const { a, button, dd, dl, dt, header, li, section, span } = require("devtools/client/shared/vendor/react-dom-factories");
const Services = require("Services");
const { getUnicodeUrl, getUnicodeUrlPath } = require("devtools/client/shared/unicode-url");
@ -117,41 +117,46 @@ class Worker extends Component {
const unregisterButton = this.isActive() ?
button({
onClick: this.unregister,
className: "devtools-button unregister-button",
className: "devtools-button worker__unregister-button js-unregister-button",
"data-standalone": true
},
Strings.GetStringFromName("unregister"))
: null;
const debugLinkDisabled = this.isRunning() ? "" : "disabled";
const debugLinkDisabled = this.isRunning() ? "" : "worker__debug-link--disabled";
const debugLink = a({
onClick: this.isRunning() ? this.debug : null,
title: this.isRunning() ? null : "Only running service workers can be debugged",
className: `${debugLinkDisabled} debug-link`
className: `${debugLinkDisabled} worker__debug-link`
},
Strings.GetStringFromName("debug"));
const startLink = !this.isRunning() ?
a({ onClick: this.start, className: "start-link" },
a({ onClick: this.start, className: "worker__start-link" },
Strings.GetStringFromName("start"))
: null;
return li({ className: "service-worker-container" },
div(
{ className: "service-worker-scope" },
span({ title: worker.scope }, this.formatScope(worker.scope)),
unregisterButton),
div(
{ className: "service-worker-source" },
span({ className: "service-worker-meta-name" }, "Source"),
span({ className: "js-source-url", title: worker.scope },
this.formatSource(worker.url)),
debugLink),
div(
{ className: `service-worker-status service-worker-status-${status}` },
span({ className: "service-worker-meta-name" }, "Status"),
Strings.GetStringFromName(status).toLowerCase(),
startLink)
return li({ className: "worker js-sw-container" },
header(
{ className: "worker__header" },
span({ title: worker.scope, className: "worker__scope js-sw-scope" },
this.formatScope(worker.scope)),
section(
{ className: "worker__controls" },
unregisterButton),
),
dl(
{ className: "worker__data" },
dt({ className: "worker__meta-name" }, "Source"),
dd({},
span({ title: worker.scope, className: "js-source-url" },
this.formatSource(worker.url)),
debugLink),
dt({ className: "worker__meta-name" }, "Status"),
dd({},
Strings.GetStringFromName(status).toLowerCase(),
startLink)
)
);
}
}

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

@ -2,11 +2,15 @@
* 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/. */
.application-aboutdebugging-plug {
.aboutdebugging-plug {
text-align: right;
padding: 5px 0;
padding: 1rem 0;
}
.application-workers-container {
.aboutdebugging-plug__link {
margin-right: 0;
}
.workers-container {
flex-grow: 1;
}

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

@ -6,7 +6,7 @@
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const { createFactory, Component } = require("devtools/client/shared/vendor/react");
const { a, div, h1, ul, li } = require("devtools/client/shared/vendor/react-dom-factories");
const { a, article, footer, h1, ul } = require("devtools/client/shared/vendor/react-dom-factories");
const Worker = createFactory(require("./Worker"));
/**
@ -28,20 +28,19 @@ class WorkerList extends Component {
const { openTrustedLink } = serviceContainer;
return [
ul({ className: "application-workers-container" },
li({},
h1({ className: "application-title" }, "Service Workers")
),
workers.map(worker => Worker({
client,
debugDisabled: false,
worker,
}))
article({ className: "workers-container" },
h1({}, "Service Workers"),
ul({},
workers.map(worker => Worker({
client,
debugDisabled: false,
worker,
})))
),
div({ className: "application-aboutdebugging-plug" },
footer({ className: "aboutdebugging-plug" },
"See about:debugging for Service Workers from other domains",
a(
{ onClick: () => openTrustedLink("about:debugging#workers") },
a({ className: "aboutdebugging-plug__link",
onClick: () => openTrustedLink("about:debugging#workers") },
"Open about:debugging"
)
)

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

@ -13,7 +13,7 @@
font-size: 13px;
}
.worker-list-empty ul {
.worker-list-empty__list {
list-style: unset;
padding: 0 40px;
}

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

@ -6,7 +6,7 @@
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const { Component } = require("devtools/client/shared/vendor/react");
const { a, div, li, ul } = require("devtools/client/shared/vendor/react-dom-factories");
const { a, article, p, li, ul } = require("devtools/client/shared/vendor/react-dom-factories");
const DOC_URL = "https://developer.mozilla.org/docs/Web/API/Service_Worker_API/Using_Service_Workers" +
"?utm_source=devtools&utm_medium=sw-panel-blank";
@ -38,9 +38,9 @@ class WorkerListEmpty extends Component {
}
render() {
return div(
return article(
{ className: "worker-list-empty" },
div(
p(
{},
"You need to register a Service Worker to inspect it here.",
a(
@ -48,13 +48,13 @@ class WorkerListEmpty extends Component {
"Learn More"
)
),
div(
p(
{},
`If the current page should have a service worker, ` +
`here are some things you can try`,
`here are some things you can try:`,
),
ul(
{},
{ className: "worker-list-empty__list"},
li(
{},
"Look for errors in the Console.",

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

@ -22,7 +22,7 @@ add_task(async function() {
info("Wait until the service worker appears in the application panel");
await waitUntil(() => getWorkerContainers(doc).length === 1);
let scopeEl = getWorkerContainers(doc)[0].querySelector(".service-worker-scope");
let scopeEl = getWorkerContainers(doc)[0].querySelector(".js-sw-scope");
ok(scopeEl.textContent.startsWith("example.com"),
"First service worker registration is displayed for the correct domain");
@ -40,7 +40,7 @@ add_task(async function() {
info("Wait until the service worker appears in the application panel");
await waitUntil(() => getWorkerContainers(doc).length === 1);
scopeEl = getWorkerContainers(doc)[0].querySelector(".service-worker-scope");
scopeEl = getWorkerContainers(doc)[0].querySelector(".js-sw-scope");
ok(scopeEl.textContent.startsWith("test1.example.com"),
"Second service worker registration is displayed for the correct domain");

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

@ -21,7 +21,8 @@ add_task(async function() {
await waitUntil(() => getWorkerContainers(doc).length === 1);
info("Wait until the unregister button is displayed for the service worker");
await waitUntil(() => getWorkerContainers(doc)[0].querySelector(".unregister-button"));
await waitUntil(() => getWorkerContainers(doc)[0]
.querySelector(".js-unregister-button"));
ok(true, "First service worker registration is displayed");
@ -32,7 +33,8 @@ add_task(async function() {
await waitUntil(() => getWorkerContainers(doc).length === 2);
info("Wait until the unregister button is displayed for the service worker");
await waitUntil(() => getWorkerContainers(doc)[1].querySelector(".unregister-button"));
await waitUntil(() => getWorkerContainers(doc)[1]
.querySelector(".js-unregister-button"));
ok(true, "Second service worker registration is displayed");

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

@ -25,9 +25,9 @@ add_task(async function() {
let workerContainer = getWorkerContainers(doc)[0];
info("Wait until the unregister button is displayed for the service worker");
await waitUntil(() => workerContainer.querySelector(".unregister-button"));
await waitUntil(() => workerContainer.querySelector(".js-unregister-button"));
let scopeEl = workerContainer.querySelector(".service-worker-scope");
let scopeEl = workerContainer.querySelector(".js-sw-scope");
let expectedScope = "example.com/browser/devtools/client/application/test/" +
"service-workers/";
ok(scopeEl.textContent.startsWith(expectedScope),

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

@ -22,7 +22,7 @@ add_task(async function() {
let workerContainer = getWorkerContainers(doc)[0];
let scopeEl = workerContainer.querySelector(".service-worker-scope");
let scopeEl = workerContainer.querySelector(".js-sw-scope");
ok(
scopeEl.textContent.startsWith(
"\u03C0\u03B1\u03C1\u03AC\u03B4\u03B5\u03B9\u03B3\u03BC\u03B1." +

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

@ -37,7 +37,7 @@ async function enableApplicationPanel() {
}
function getWorkerContainers(doc) {
return doc.querySelectorAll(".service-worker-container");
return doc.querySelectorAll(".js-sw-container");
}
function navigate(target, url, waitForTargetEvent = "navigate") {