Bug 1399897 - Restrict the height of console table and add sticky headers; r=nchevobbe
authorTowkir Ahmed <towkir17@gmail.com>
Thu, 07 Dec 2017 22:05:18 +0600
changeset 450772 914fce4a03e31172958705299a83128633911d48
parent 450771 4a9f600f565806c895708e43ffda1baa8d5888fc
child 450773 83acad9bf47b7c32947d37f03e60622722c1fd88
push id8543
push userryanvm@gmail.com
push dateTue, 16 Jan 2018 14:33:22 +0000
treeherdermozilla-beta@a6525ed16a32 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnchevobbe
bugs1399897
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1399897 - Restrict the height of console table and add sticky headers; r=nchevobbe Since table elements (th, tr) do not support sticky headers, the console table now uses only sibling divs for the cells, with appropriate aria attributes and a CSS grid to mimic an actual table. MozReview-Commit-ID: J8hmy7H4GKL
devtools/client/themes/webconsole.css
devtools/client/webconsole/new-console-output/components/ConsoleTable.js
--- a/devtools/client/themes/webconsole.css
+++ b/devtools/client/themes/webconsole.css
@@ -1088,66 +1088,55 @@ a.learn-more-link.webconsole-learn-more-
 .theme-light .webconsole-output-wrapper .message.error .stacktrace {
   /* Removing specificity from the old console */
   background-color: inherit;
 }
 
 /* console.table() */
 .new-consoletable {
   width: 100%;
-  border-collapse: collapse;
   --consoletable-border: var(--theme-splitter-color);
   margin-block-end: var(--attachment-margin-block-end);
   color: var(--theme-body-color);
-}
-
-.new-consoletable thead {
+  display: grid;
+  max-height: 250px;
+  overflow-y: auto;
   border: 1px solid var(--consoletable-border);
+  /* border at the left side will be added by the inner divs [role=gridcell] */
+  border-left: none;
 }
 
-.new-consoletable tbody {
-  background-color: var(--theme-body-background);
-  border: 1px solid var(--consoletable-border);
-  border-block-start-width: 0;
+.new-consoletable > div {
+  border-left: 1px solid var(--consoletable-border);
 }
 
-.new-consoletable th {
+.new-consoletable-header {
+  position: sticky;
+  top: 0;
+  border-bottom: 1px solid var(--consoletable-border);
   background-color: var(--theme-toolbar-background);
   color: var(--theme-body-color);
   margin: 0;
-  padding: 5px 0 0;
+  padding: 5px 4px;
   font-weight: inherit;
+  z-index: 1;
 }
 
-.new-consoletable th:not(:last-of-type) {
-  border-inline-end: 1px solid var(--consoletable-border);
+.new-consoletable > [role=gridcell] {
+  background-color: var(--theme-body-background);
+  padding: 3px 4px;
+  min-width: 100px;
+  color: var(--theme-body-color);
 }
 
-.new-consoletable tr:nth-of-type(even) {
+.new-consoletable > [role=gridcell].even {
   background-color: var(--table-zebra-background);
 }
 
-.new-consoletable td {
-  padding: 3px 4px;
-  min-width: 100px;
-  -moz-user-focus: normal;
-  color: var(--theme-body-color);
-  height: 1.25em;
-  line-height: 1.25em;
-  /* Objects are expandable in cells, and if one gets tall,
-   * we still want other columns to stick to the top.
-   */
-  vertical-align: top;
-}
-
-.new-consoletable tr td:not(:last-of-type) {
-  border-inline-end: 1px solid var(--consoletable-border);
-}
 /* Layout */
-
 .webconsole-output {
   flex: 1;
   direction: ltr;
   overflow: auto;
   -moz-user-select: text;
   position: relative;
   grid-row: 2 / 3;
 }
--- a/devtools/client/webconsole/new-console-output/components/ConsoleTable.js
+++ b/devtools/client/webconsole/new-console-output/components/ConsoleTable.js
@@ -45,43 +45,50 @@ class ConsoleTable extends Component {
     let dataType = getParametersDataType(parameters);
 
     // Get all the object properties.
     dispatch(actions.messageTableDataGet(id, client, dataType));
   }
 
   getHeaders(columns) {
     let headerItems = [];
-    columns.forEach((value, key) => headerItems.push(dom.th({}, value)));
+    columns.forEach((value, key) => headerItems.push(dom.div({
+      className: "new-consoletable-header",
+      role: "columnheader"
+    }, value))
+  );
     return headerItems;
   }
 
   getRows(columns, items) {
     const {
       dispatch,
       serviceContainer,
     } = this.props;
 
-    return items.map(item => {
+    return items.map((item, index) => {
       let cells = [];
       columns.forEach((value, key) => {
         cells.push(
-          dom.td(
-            {},
+          dom.div(
+            {
+              role: "gridcell",
+              className: (index % 2) ? "odd" : "even"
+            },
             GripMessageBody({
               grip: item[key],
               mode: MODE.SHORT,
               useQuotes: false,
               serviceContainer,
               dispatch,
             })
           )
         );
       });
-      return dom.tr({}, cells);
+      return cells;
     });
   }
 
   render() {
     const {parameters, tableData} = this.props;
     const headersGrip = parameters[1];
     const headers = headersGrip && headersGrip.preview ? headersGrip.preview.items : null;
 
@@ -92,19 +99,25 @@ class ConsoleTable extends Component {
 
     const {columns, items} = getTableItems(
       tableData,
       getParametersDataType(parameters),
       headers
     );
 
     return (
-      dom.table({className: "new-consoletable devtools-monospace"},
-        dom.thead({}, this.getHeaders(columns)),
-        dom.tbody({}, this.getRows(columns, items))
+      dom.div({
+        className: "new-consoletable",
+        role: "grid",
+        style: {
+          gridTemplateColumns: `repeat(${columns.size}, auto)`
+        }
+      },
+        this.getHeaders(columns),
+        this.getRows(columns, items)
       )
     );
   }
 }
 
 function getParametersDataType(parameters = null) {
   if (!Array.isArray(parameters) || parameters.length === 0) {
     return null;