From b46cfd2bc35d81e2a86ef94b5d19ac1c208c300d Mon Sep 17 00:00:00 2001
From: Wang Sijie <wangsijie@silverhand.io>
Date: Fri, 25 Mar 2022 14:46:37 +0800
Subject: [PATCH] refactor(console): use colgroup in table (#445)

---
 .../src/components/Card/index.module.scss     |  2 +-
 .../src/components/Table/TableLoading.tsx     | 38 ++++++++++++++-----
 .../console/src/pages/ApiResources/index.tsx  | 21 ++++------
 .../console/src/pages/Applications/index.tsx  | 21 ++++------
 .../Connectors/components/ConnectorRow.tsx    |  3 +-
 .../console/src/pages/Connectors/index.tsx    | 23 ++++-------
 packages/console/src/pages/Users/index.tsx    | 23 ++++-------
 packages/console/src/scss/normalized.scss     | 15 +-------
 8 files changed, 64 insertions(+), 82 deletions(-)

diff --git a/packages/console/src/components/Card/index.module.scss b/packages/console/src/components/Card/index.module.scss
index d7b19922e..ef7a17b22 100644
--- a/packages/console/src/components/Card/index.module.scss
+++ b/packages/console/src/components/Card/index.module.scss
@@ -4,5 +4,5 @@
   background: var(--color-on-primary);
   border-radius: _.unit(4);
   padding: _.unit(6);
-  height: 100%;
+  min-height: 100%;
 }
diff --git a/packages/console/src/components/Table/TableLoading.tsx b/packages/console/src/components/Table/TableLoading.tsx
index 918309a9b..04e254fa6 100644
--- a/packages/console/src/components/Table/TableLoading.tsx
+++ b/packages/console/src/components/Table/TableLoading.tsx
@@ -1,18 +1,36 @@
-import React, { ReactNode } from 'react';
+import React, { useMemo } from 'react';
 
+import ItemPreviewLoading from './ItemPreviewLoading';
 import * as styles from './TableLoading.module.scss';
 
-export { default as ItemPreviewLoading } from './ItemPreviewLoading';
-
 type Props = {
-  children: ReactNode;
+  columns: number;
 };
 
-const TableLoading = ({ children }: Props) => (
-  <>
-    <tr className={styles.loading}>{children}</tr>
-    <tr className={styles.loading}>{children}</tr>
-  </>
-);
+const TableLoading = ({ columns }: Props) => {
+  const row = useMemo(
+    () => (
+      <tr className={styles.loading}>
+        <td>
+          <ItemPreviewLoading />
+        </td>
+        {Array.from({ length: columns - 1 }).map((_, index) => (
+          // eslint-disable-next-line react/no-array-index-key
+          <td key={index}>
+            <div />
+          </td>
+        ))}
+      </tr>
+    ),
+    [columns]
+  );
+
+  return (
+    <>
+      {row}
+      {row}
+    </>
+  );
+};
 
 export default TableLoading;
diff --git a/packages/console/src/pages/ApiResources/index.tsx b/packages/console/src/pages/ApiResources/index.tsx
index 47a166ec4..b1214e036 100644
--- a/packages/console/src/pages/ApiResources/index.tsx
+++ b/packages/console/src/pages/ApiResources/index.tsx
@@ -14,7 +14,7 @@ import CopyToClipboard from '@/components/CopyToClipboard';
 import ImagePlaceholder from '@/components/ImagePlaceholder';
 import ItemPreview from '@/components/ItemPreview';
 import TableError from '@/components/Table/TableError';
-import TableLoading, { ItemPreviewLoading } from '@/components/Table/TableLoading';
+import TableLoading from '@/components/Table/TableLoading';
 import { RequestError } from '@/hooks/use-api';
 import * as modalStyles from '@/scss/modal.module.scss';
 
@@ -62,9 +62,13 @@ const ApiResources = () => {
         </Modal>
       </div>
       <table className={styles.table}>
+        <colgroup>
+          <col className={styles.apiResourceName} />
+          <col />
+        </colgroup>
         <thead>
           <tr>
-            <th className={styles.apiResourceName}>{t('api_resources.api_name')}</th>
+            <th>{t('api_resources.api_name')}</th>
             <th>{t('api_resources.api_identifier')}</th>
           </tr>
         </thead>
@@ -75,16 +79,7 @@ const ApiResources = () => {
               onRetry={async () => mutate(undefined, true)}
             />
           )}
-          {isLoading && (
-            <TableLoading>
-              <td className={styles.apiResourceName}>
-                <ItemPreviewLoading />
-              </td>
-              <td>
-                <div />
-              </td>
-            </TableLoading>
-          )}
+          {isLoading && <TableLoading columns={2} />}
           {data?.map(({ id, name, indicator }) => (
             <tr
               key={id}
@@ -93,7 +88,7 @@ const ApiResources = () => {
                 navigate(buildDetailsLink(id));
               }}
             >
-              <td className={styles.apiResourceName}>
+              <td>
                 <ItemPreview title={name} icon={<ImagePlaceholder />} to={buildDetailsLink(id)} />
               </td>
               <td>
diff --git a/packages/console/src/pages/Applications/index.tsx b/packages/console/src/pages/Applications/index.tsx
index 57b49fdbf..4a5c390a7 100644
--- a/packages/console/src/pages/Applications/index.tsx
+++ b/packages/console/src/pages/Applications/index.tsx
@@ -14,7 +14,7 @@ import CopyToClipboard from '@/components/CopyToClipboard';
 import ImagePlaceholder from '@/components/ImagePlaceholder';
 import ItemPreview from '@/components/ItemPreview';
 import TableError from '@/components/Table/TableError';
-import TableLoading, { ItemPreviewLoading } from '@/components/Table/TableLoading';
+import TableLoading from '@/components/Table/TableLoading';
 import { RequestError } from '@/hooks/use-api';
 import * as modalStyles from '@/scss/modal.module.scss';
 import { applicationTypeI18nKey } from '@/types/applications';
@@ -60,9 +60,13 @@ const Applications = () => {
         </Modal>
       </div>
       <table className={styles.table}>
+        <colgroup>
+          <col className={styles.applicationName} />
+          <col />
+        </colgroup>
         <thead>
           <tr>
-            <th className={styles.applicationName}>{t('applications.application_name')}</th>
+            <th>{t('applications.application_name')}</th>
             <th>{t('applications.client_id')}</th>
           </tr>
         </thead>
@@ -73,16 +77,7 @@ const Applications = () => {
               onRetry={async () => mutate(undefined, true)}
             />
           )}
-          {isLoading && (
-            <TableLoading>
-              <td className={styles.applicationName}>
-                <ItemPreviewLoading />
-              </td>
-              <td>
-                <div />
-              </td>
-            </TableLoading>
-          )}
+          {isLoading && <TableLoading columns={2} />}
           {data?.map(({ id, name, type }) => (
             <tr
               key={id}
@@ -91,7 +86,7 @@ const Applications = () => {
                 navigate(`/applications/${id}`);
               }}
             >
-              <td className={styles.applicationName}>
+              <td>
                 <ItemPreview
                   title={name}
                   subtitle={t(`${applicationTypeI18nKey[type]}.title`)}
diff --git a/packages/console/src/pages/Connectors/components/ConnectorRow.tsx b/packages/console/src/pages/Connectors/components/ConnectorRow.tsx
index 85e933b62..476afca37 100644
--- a/packages/console/src/pages/Connectors/components/ConnectorRow.tsx
+++ b/packages/console/src/pages/Connectors/components/ConnectorRow.tsx
@@ -5,7 +5,6 @@ import { useTranslation } from 'react-i18next';
 import Button from '@/components/Button';
 import Status from '@/components/Status';
 
-import * as styles from '../index.module.scss';
 import ConnectorName from './ConnectorName';
 
 type Props = {
@@ -31,7 +30,7 @@ const ConnectorRow = ({ type, connector, onClickSetup }: Props) => {
 
   return (
     <tr>
-      <td className={styles.connectorName}>
+      <td>
         <ConnectorName connector={connector} titlePlaceholder={typeLabel} />
       </td>
       <td>{typeLabel}</td>
diff --git a/packages/console/src/pages/Connectors/index.tsx b/packages/console/src/pages/Connectors/index.tsx
index 5b631800d..f5bc1d8ef 100644
--- a/packages/console/src/pages/Connectors/index.tsx
+++ b/packages/console/src/pages/Connectors/index.tsx
@@ -10,7 +10,7 @@ import Card from '@/components/Card';
 import CardTitle from '@/components/CardTitle';
 import TabNav, { TabNavLink } from '@/components/TabNav';
 import TableError from '@/components/Table/TableError';
-import TableLoading, { ItemPreviewLoading } from '@/components/Table/TableLoading';
+import TableLoading from '@/components/Table/TableLoading';
 import { RequestError } from '@/hooks/use-api';
 
 import ConnectorRow from './components/ConnectorRow';
@@ -67,9 +67,14 @@ const Connectors = () => {
           <TabNavLink href="/connectors/social">{t('connectors.tab_social')}</TabNavLink>
         </TabNav>
         <table className={styles.table}>
+          <colgroup>
+            <col className={styles.connectorName} />
+            <col />
+            <col />
+          </colgroup>
           <thead>
             <tr>
-              <th className={styles.connectorName}>{t('connectors.connector_name')}</th>
+              <th>{t('connectors.connector_name')}</th>
               <th>{t('connectors.connector_type')}</th>
               <th>{t('connectors.connector_status')}</th>
             </tr>
@@ -81,19 +86,7 @@ const Connectors = () => {
                 onRetry={async () => mutate(undefined, true)}
               />
             )}
-            {isLoading && (
-              <TableLoading>
-                <td className={styles.connectorName}>
-                  <ItemPreviewLoading />
-                </td>
-                <td>
-                  <div />
-                </td>
-                <td>
-                  <div />
-                </td>
-              </TableLoading>
-            )}
+            {isLoading && <TableLoading columns={3} />}
             {socialConnectors?.length === 0 && (
               <tr>
                 <td colSpan={3}>
diff --git a/packages/console/src/pages/Users/index.tsx b/packages/console/src/pages/Users/index.tsx
index b5e4a8b2b..354f09fc8 100644
--- a/packages/console/src/pages/Users/index.tsx
+++ b/packages/console/src/pages/Users/index.tsx
@@ -11,7 +11,7 @@ import CardTitle from '@/components/CardTitle';
 import ImagePlaceholder from '@/components/ImagePlaceholder';
 import ItemPreview from '@/components/ItemPreview';
 import TableError from '@/components/Table/TableError';
-import TableLoading, { ItemPreviewLoading } from '@/components/Table/TableLoading';
+import TableLoading from '@/components/Table/TableLoading';
 import { RequestError } from '@/hooks/use-api';
 import * as modalStyles from '@/scss/modal.module.scss';
 
@@ -53,6 +53,11 @@ const Users = () => {
         </Modal>
       </div>
       <table className={styles.table}>
+        <colgroup>
+          <col className={styles.userName} />
+          <col />
+          <col />
+        </colgroup>
         <thead>
           <tr>
             <th>{t('users.user_name')}</th>
@@ -67,19 +72,7 @@ const Users = () => {
               onRetry={async () => mutate(undefined, true)}
             />
           )}
-          {isLoading && (
-            <TableLoading>
-              <td className={styles.userName}>
-                <ItemPreviewLoading />
-              </td>
-              <td>
-                <div />
-              </td>
-              <td>
-                <div />
-              </td>
-            </TableLoading>
-          )}
+          {isLoading && <TableLoading columns={3} />}
           {data?.map(({ id, name, username }) => (
             <tr
               key={id}
@@ -88,7 +81,7 @@ const Users = () => {
                 navigate(`/users/${id}`);
               }}
             >
-              <td className={styles.userName}>
+              <td>
                 <ItemPreview
                   title={name ?? '-'}
                   subtitle={username ?? '-'}
diff --git a/packages/console/src/scss/normalized.scss b/packages/console/src/scss/normalized.scss
index 8dad16267..a247ffa8e 100644
--- a/packages/console/src/scss/normalized.scss
+++ b/packages/console/src/scss/normalized.scss
@@ -22,16 +22,10 @@ table {
   border: 1px solid var(--color-neutral-90);
   border-radius: _.unit(2);
   border-spacing: 0;
+  width: 100%;
+  table-layout: fixed;
   overflow: hidden;
 
-  thead,
-  tbody,
-  tr {
-    display: table;
-    width: 100%;
-    table-layout: fixed;
-  }
-
   thead {
     th {
       font: var(--font-subhead-2);
@@ -48,11 +42,6 @@ table {
   }
 
   tbody {
-    display: block;
-    overflow: auto;
-    table-layout: fixed;
-    max-height: calc(100% - _.unit(40));
-
     td {
       border-bottom: 1px solid var(--color-neutral-90);
       padding: _.unit(5) _.unit(4);