extraInfo: show info in chips

This CL redesigns the way extra info is presented to the user. Now, it
is presented in chips rather than in plain text. See the screenshots in
the linked bug.

Fixed: twpowertools:108
Change-Id: Idebdd91039540e87a3db83b3c6f80cd42c64e61e
diff --git a/src/contentScripts/communityConsole/extraInfo.js b/src/contentScripts/communityConsole/extraInfo.js
index acea6fe..9b1cd9a 100644
--- a/src/contentScripts/communityConsole/extraInfo.js
+++ b/src/contentScripts/communityConsole/extraInfo.js
@@ -253,32 +253,48 @@
     return this.optionsWatcher.isEnabled(feature);
   }
 
-  // Add a pretty component which contains |info| to |node|.
-  addExtraInfoElement(info, node) {
+  // Add chips which contain |info| to |node|. If |withContainer| is set to
+  // true, a container will contain all the chips.
+  addExtraInfoElement(info, node, withContainer = false) {
     // Don't create if there's nothing to show
     if (info.length == 0) return;
 
-    let container = document.createElement('div');
-    container.classList.add('TWPT-extrainfo-container');
-
-    let badgeCell = document.createElement('div');
-    badgeCell.classList.add('TWPT-extrainfo-badge-cell');
-
-    const [badge, badgeTooltip] = createExtBadge();
-    badgeCell.append(badge);
-
-    let infoCell = document.createElement('div');
-    infoCell.classList.add('TWPT-extrainfo-info-cell');
-
-    for (const i of info) {
-      let iRow = document.createElement('div');
-      iRow.append(i);
-      infoCell.append(iRow);
+    let container;
+    if (withContainer) {
+      container = document.createElement('div');
+      container.classList.add('TWPT-extrainfo-container');
+    } else {
+      container = node;
     }
 
-    container.append(badgeCell, infoCell);
-    node.append(container);
-    new MDCTooltip(badgeTooltip);
+    let tooltips = [];
+
+    for (const i of info) {
+      let chip = document.createElement('material-chip');
+      chip.classList.add('TWPT-extrainfo-chip');
+
+      let chipCont = document.createElement('div');
+      chipCont.classList.add('TWPT-chip-content-container');
+
+      let content = document.createElement('div');
+      content.classList.add('TWPT-content');
+
+      const [badge, badgeTooltip] = createExtBadge();
+
+      let span = document.createElement('span');
+      span.append(i);
+
+      content.append(badge, span);
+      chipCont.append(content);
+      chip.append(chipCont);
+      container.append(chip);
+
+      tooltips.push(badgeTooltip);
+    }
+
+    if (withContainer) node.append(container);
+
+    for (const tooltip of tooltips) new MDCTooltip(tooltip);
   }
 
   fieldInfo(field, value) {
@@ -334,7 +350,7 @@
           if (appealCount !== undefined)
             info.push(this.fieldInfo('Number of appeals', appealCount));
 
-          this.addExtraInfoElement(info, card);
+          this.addExtraInfoElement(info, card, true);
         })
         .catch(err => {
           console.error(
@@ -543,19 +559,13 @@
     return [info, tooltips];
   }
 
-  injectAtQuestion(question) {
+  injectAtQuestion(stateChips) {
     let currentPage = parseUrl(location.href);
     if (currentPage === false) {
       console.error('extraInfo: couldn\'t parse current URL:', location.href);
       return;
     }
 
-    let content = question.querySelector('ec-question > .content');
-    if (!content) {
-      console.error('extraInfo: question doesn\'t have .content:', messageNode);
-      return;
-    }
-
     waitFor(
         () => {
           let now = Date.now();
@@ -573,7 +583,7 @@
         })
         .then(thread => {
           const [info, tooltips] = this.getThreadInfo(thread.body?.['1']);
-          this.addExtraInfoElement(info, content);
+          this.addExtraInfoElement(info, stateChips, false);
           for (const tooltip of tooltips) new MDCTooltip(tooltip);
         })
         .catch(err => {
@@ -582,9 +592,9 @@
         });
   }
 
-  injectAtQuestionIfEnabled(question) {
+  injectAtQuestionIfEnabled(stateChips) {
     this.isEnabled('extrainfo').then(isEnabled => {
-      if (isEnabled) return this.injectAtQuestion(question);
+      if (isEnabled) return this.injectAtQuestion(stateChips);
     });
   }
 
@@ -721,7 +731,7 @@
               this.getLiveReviewStatusInfo(liveReviewStatus);
           if (liveReviewInfo) info.push(liveReviewInfo);
 
-          this.addExtraInfoElement(info, footer);
+          this.addExtraInfoElement(info, footer, true);
           if (pendingTooltip) new MDCTooltip(pendingTooltip);
           if (liveReviewTooltip) new MDCTooltip(liveReviewTooltip);
         })
@@ -838,7 +848,7 @@
         })
         .then(thread => {
           const [info, tooltips] = this.getThreadInfo(thread);
-          this.addExtraInfoElement(info, toolbelt);
+          this.addExtraInfoElement(info, toolbelt, true);
           for (const tooltip of tooltips) new MDCTooltip(tooltip);
         })
         .catch(err => {
diff --git a/src/contentScripts/communityConsole/main.js b/src/contentScripts/communityConsole/main.js
index d140484..8c67bb5 100644
--- a/src/contentScripts/communityConsole/main.js
+++ b/src/contentScripts/communityConsole/main.js
@@ -56,8 +56,8 @@
   'ec-canned-response-row .tags',
   'ec-canned-response-row .main .toolbelt',
 
-  // Div containing ec-question (for the extra info feature)
-  'ec-thread div[role="list"]',
+  // Question state chips container (for the extra info feature)
+  'ec-question .state-chips',
 
   // Replies (for the extra info feature)
   'ec-thread ec-message',
@@ -172,9 +172,8 @@
     }
 
     // Show additional details in the thread view.
-    if (node.matches('ec-thread div[role="list"]')) {
-      const question = node.querySelector('ec-question');
-      if (question) window.TWPTExtraInfo.injectAtQuestionIfEnabled(question);
+    if (node.matches('ec-question .state-chips')) {
+      window.TWPTExtraInfo.injectAtQuestionIfEnabled(node);
     }
     if (node.matches('ec-thread ec-message')) {
       window.TWPTExtraInfo.injectAtMessageIfEnabled(node);
diff --git a/src/static/css/ccdarktheme.css b/src/static/css/ccdarktheme.css
index c993334..ff61d2e 100644
--- a/src/static/css/ccdarktheme.css
+++ b/src/static/css/ccdarktheme.css
@@ -18,7 +18,9 @@
   --TWPT-blue-100: #BBDEFB;
   --TWPT-blue-A100: #82B1FF;
   --TWPT-bad-text: #f6aea9;
+  --TWPT-bad-text-lightbg: #ffc4c0;
   --TWPT-good-text: #34a853;
+  --TWPT-good-text-lightbg: #3cc160;
   --TWPT-interop-primary-text: var(--TWPT-primary-text);
   --TWPT-interop-secondary-text: #c4c7c5;
   --TWPT-interop-subtle-border: #474747;
@@ -407,14 +409,17 @@
   color: var(--TWPT-primary-text-alt) !important;
 }
 
-ec-question .state-chips material-chip {
+ec-question .state-chips material-chip,
+    .TWPT-extrainfo-chip {
   background-color: var(--TWPT-button-background)!important;
+  border: none!important;
   box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2),
       0 1px 1px 0 rgba(0, 0, 0, 0.14),
-      0 1px 3px 0 rgba(0, 0, 0, 0.12);
+      0 1px 3px 0 rgba(0, 0, 0, 0.12)!important;
 }
 
-ec-question .state-chips material-chip .content {
+ec-question .state-chips material-chip .content,
+    .TWPT-extrainfo-chip .TWPT-content {
   color: var(--TWPT-primary-text)!important;
 }
 
diff --git a/src/static/css/extrainfo.css b/src/static/css/extrainfo.css
index 6813195..a7bc977 100644
--- a/src/static/css/extrainfo.css
+++ b/src/static/css/extrainfo.css
@@ -1,26 +1,57 @@
 .TWPT-extrainfo-container {
-  display: inline-flex;
-  color: var(--TWPT-interop-secondary-text, #444746)!important;
-  align-items: center;
-}
-
-.TWPT-extrainfo-badge-cell {
-  margin: 0 8px;
-  --icon-size: 14px;
-  opacity: 0.4;
-}
-
-.TWPT-extrainfo-info-cell {
-  border-inline-start: solid 1px var(--TWPT-interop-subtle-border, #ababab);
-  padding-inline-start: 8px;
   display: flex;
-  flex-direction: column;
+  align-items: center;
+  flex-wrap: wrap;
 }
 
-.TWPT-extrainfo-info-cell > div:not(:last-child) {
-  margin-bottom: 2px;
+.TWPT-extrainfo-chip,
+    ec-canned-response-row .TWPT-tag {
+  background-color: transparent;
+  color: #474747;
+  border: 1px solid #ababab;
+  display: flex;
+  align-items: center;
+  border-radius: 16px;
+  height: 32px;
+  overflow: hidden;
 }
 
+.TWPT-extrainfo-chip {
+  margin: 4px;
+}
+
+ec-canned-response-row .TWPT-tag {
+  margin: 0 0 0 4px;
+}
+
+.TWPT-extrainfo-chip .TWPT-chip-content-container,
+    ec-canned-response-row .TWPT-chip-content-container {
+  margin: 0 12px;
+  overflow: hidden;
+  white-space: nowrap;
+}
+
+.TWPT-extrainfo-chip .TWPT-content,
+    ec-canned-response-row .TWPT-content {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  display: flex;
+  align-items: center;
+  color: var(--TWPT-interop-secondary-text, #444746);
+}
+
+.TWPT-extrainfo-chip .TWPT-content .TWPT-badge,
+    ec-canned-response-row .TWPT-content .TWPT-badge {
+  --icon-size: 14px;
+  margin-inline-end: 6px;
+}
+
+.TWPT-extrainfo-chip .TWPT-content span[aria-describedby],
+    ec-canned-response-row .TWPT-content span[aria-describedby] {
+  cursor: help;
+}
+
+
 /* Specific styles inside context */
 
 ec-unified-user .scTailwindUser_profileUsercardmain {
@@ -33,87 +64,51 @@
   align-self: end;
 }
 
-ec-question .TWPT-extrainfo-container,
-    ec-message .footer .TWPT-extrainfo-container {
+/* This modifies the CC styles */
+ec-question .state-chips {
+  align-items: center;
+  flex-wrap: wrap;
+}
+
+ec-question .TWPT-extrainfo-chip,
+    ec-message .footer .TWPT-extrainfo-chip,
+    ec-thread-summary .main .toolbelt .TWPT-extrainfo-chip {
+  height: 30px;
+  font-size: 12px;
   color: var(--TWPT-secondary-text, #6c6c6c);
 }
 
-ec-question .TWPT-extrainfo-container {
-  font-size: 13px;
-  position: absolute;
-  bottom: 25px;
-  inset-inline-end: 48px;
+ec-question .TWPT-extrainfo-chip .TWPT-chip-content-container,
+    ec-message .footer .TWPT-extrainfo-chip .TWPT-chip-content-container,
+    ec-thread-summary .main .toolbelt .TWPT-extrainfo-chip .TWPT-chip-content-container {
+  margin: 0 10px 0 6px;
 }
 
 ec-message .footer .TWPT-extrainfo-container {
   margin-top: 8px;
-  font-size: 12px;
-}
-
-ec-message .footer .TWPT-extrainfo-badge-cell {
-  margin: 0 6px 0 0;
-  --icon-size: 12px;
-}
-
-ec-message .footer .TWPT-extrainfo-info-cell {
-  padding-inline-start: 6px;
 }
 
 ec-thread-summary .main .toolbelt .TWPT-extrainfo-container {
   margin-inline-start: 115px;
   margin-bottom: 16px;
-  font-size: 12px;
 }
 
+
 /* Special styles for good/bad labels */
 .TWPT-extrainfo-good {
-  color: var(--TWPT-good-text, green)!important;
+  color: var(--TWPT-good-text-lightbg, #198639)!important;
 }
 
 .TWPT-extrainfo-warning {
-  color: var(--TWPT-warning-text, orange)!important;
+  color: var(--TWPT-warning-text-lightbg, orange)!important;
 }
 
 .TWPT-extrainfo-bad {
-  color: var(--TWPT-bad-text, red)!important;
+  color: var(--TWPT-bad-text-lightbg, #d50000)!important;
 }
 
-/* Special tags components for canned responses */
-ec-canned-response-row .TWPT-tag {
-  background-color: transparent;
-  color: #474747;
-  margin: 0 0 0 4px;
-  border: 1px solid #ababab;
-  display: flex;
-  align-items: center;
-  border-radius: 16px;
-  height: 32px;
-  overflow: hidden;
-}
 
-ec-canned-response-row .TWPT-chip-content-container {
-  margin: 0 12px;
-  overflow: hidden;
-  white-space: nowrap;
-}
-
-ec-canned-response-row .TWPT-content {
-  overflow: hidden;
-  text-overflow: ellipsis;
-  display: flex;
-  align-items: center;
-}
-
-ec-canned-response-row .TWPT-content .TWPT-badge {
-  --icon-size: 14px;
-  margin-inline-end: 6px;
-}
-
-ec-canned-response-row .TWPT-content span[aria-describedby] {
-  cursor: help;
-}
-
-/* Special component for the thread list */
+/* Special component for the thread list statuses */
 ec-thread-summary .header-content .TWPT-label {
   display: flex;
   align-items: center;
@@ -126,6 +121,7 @@
   margin-right: 2px;
 }
 
+
 /* Per-forum stats section */
 .TWPT-scTailwindSharedActivitychartroot .scTailwindSharedActivitychartchart {
   margin-top: 26px;