From e4610f07430909d8b5eb4d5654df7cccd659c76d Mon Sep 17 00:00:00 2001 From: Cameron Fraser Date: Thu, 7 Dec 2023 15:41:20 -0800 Subject: [PATCH 1/9] rename component --- .../components/MetadataViewer/index.tsx | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/aics-image-viewer/components/MetadataViewer/index.tsx b/src/aics-image-viewer/components/MetadataViewer/index.tsx index 3a603ab2..ebc7540f 100644 --- a/src/aics-image-viewer/components/MetadataViewer/index.tsx +++ b/src/aics-image-viewer/components/MetadataViewer/index.tsx @@ -19,7 +19,7 @@ interface CollapsibleCategoryProps extends MetadataTableProps { const isCategory = (val: MetadataEntry): val is MetadataRecord => typeof val === "object" && val !== null; /** Component to hold collapse state */ -const MetadataCollapsibleCategory: React.FC = ({ metadata, title, categoryFollows }) => { +const MetadataCategory: React.FC = ({ metadata, title, categoryFollows }) => { const [collapsed, setCollapsed] = React.useState(true); const toggleCollapsed = (): void => setCollapsed(!collapsed); @@ -64,14 +64,7 @@ const MetadataTable: React.FC = ({ metadata, categoryFollows const nextItem = metadataIsArray ? metadata[idx + 1] : metadata[metadataKeys[idx + 1]]; const categoryBelow = idx + 1 >= metadataKeys.length ? isCategory(nextItem) : categoryFollows; - return ( - - ); + return ; } else { return ( From 005505c1c87965096c67283bc7b18120d47e10bf Mon Sep 17 00:00:00 2001 From: Cameron Fraser Date: Thu, 7 Dec 2023 15:41:37 -0800 Subject: [PATCH 2/9] adjust metadata table padding for better alignment --- src/aics-image-viewer/components/MetadataViewer/styles.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/aics-image-viewer/components/MetadataViewer/styles.css b/src/aics-image-viewer/components/MetadataViewer/styles.css index 2f88a6fe..a8c1cc46 100644 --- a/src/aics-image-viewer/components/MetadataViewer/styles.css +++ b/src/aics-image-viewer/components/MetadataViewer/styles.css @@ -49,7 +49,7 @@ } &.metadata-key { - padding-left: 24px; + padding-left: 16px; } &.metadata-value { @@ -59,12 +59,12 @@ } &:last-child { - padding-right: 16px; + padding-right: 8px; } &.metadata-collapse-content { padding: 0; - padding-left: 16px; + padding-left: 24px; border-bottom: none; } From 33babe894e97a7c9827e8a065df5ea824fb4d652 Mon Sep 17 00:00:00 2001 From: Cameron Fraser Date: Tue, 12 Dec 2023 16:29:52 -0800 Subject: [PATCH 3/9] make category bottom borders appear below content, not title --- .../components/MetadataViewer/index.tsx | 19 +++++------ .../components/MetadataViewer/styles.css | 34 ++++++++++++------- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/src/aics-image-viewer/components/MetadataViewer/index.tsx b/src/aics-image-viewer/components/MetadataViewer/index.tsx index ebc7540f..d5758c46 100644 --- a/src/aics-image-viewer/components/MetadataViewer/index.tsx +++ b/src/aics-image-viewer/components/MetadataViewer/index.tsx @@ -10,6 +10,7 @@ interface MetadataTableProps { // up with the top border of the lower category and create the appearance of a single thick, uneven border. // (there is not a way to prevent this with pure CSS to my knowledge) categoryFollows: boolean; + topLevel?: boolean; } interface CollapsibleCategoryProps extends MetadataTableProps { @@ -23,14 +24,12 @@ const MetadataCategory: React.FC = ({ metadata, title, const [collapsed, setCollapsed] = React.useState(true); const toggleCollapsed = (): void => setCollapsed(!collapsed); + const rowClass = + (collapsed ? " metadata-collapse-collapsed" : "") + (!categoryFollows ? " metadata-collapse-bottom-border" : ""); + return ( <> - + @@ -38,7 +37,7 @@ const MetadataCategory: React.FC = ({ metadata, title, {title} - + @@ -47,12 +46,12 @@ const MetadataCategory: React.FC = ({ metadata, title, ); }; -const MetadataTable: React.FC = ({ metadata, categoryFollows }) => { +const MetadataTable: React.FC = ({ metadata, categoryFollows, topLevel }) => { const metadataKeys = Object.keys(metadata); const metadataIsArray = Array.isArray(metadata); return ( - +
{metadataKeys.map((key, idx) => { const metadataValue = metadataIsArray ? metadata[idx] : metadata[key]; @@ -80,7 +79,7 @@ const MetadataTable: React.FC = ({ metadata, categoryFollows }; const MetadataViewer: React.FC<{ metadata: MetadataRecord }> = ({ metadata }) => ( - + ); export default MetadataViewer; diff --git a/src/aics-image-viewer/components/MetadataViewer/styles.css b/src/aics-image-viewer/components/MetadataViewer/styles.css index a8c1cc46..d667a979 100644 --- a/src/aics-image-viewer/components/MetadataViewer/styles.css +++ b/src/aics-image-viewer/components/MetadataViewer/styles.css @@ -2,6 +2,14 @@ width: 100%; table-layout: fixed; + &.metadata-top-level { + border-bottom: 1px solid #6e6e6e; + + > tbody > tr.metadata-collapse-title:first-child { + border-top: none; + } + } + tbody { padding: 10px; } @@ -12,28 +20,28 @@ background-color: #3a3a3a; } - &.metadata-collapse-collapsed { - visibility: collapse; - height: 0px; - display: none; - } - &.metadata-collapse-title { color: white; background-color: #4b4b4b; - &:not(.metadata-collapse-no-bottom-border) { + border-top: 1px solid #6e6e6e; + + &.metadata-collapse-collapsed.metadata-collapse-bottom-border:not(:nth-last-child(2)) { border-bottom: 1px solid #6e6e6e; } - &.metadata-collapse-no-bottom-border > td { - padding-bottom: 5px; - } - &:not(:first-child) { - border-top: 1px solid #6e6e6e; - } } &.metadata-collapse-content-row { background-color: #313131; + + &.metadata-collapse-collapsed { + visibility: collapse; + height: 0px; + display: none; + } + + &:not(.metadata-collapse-collapsed).metadata-collapse-bottom-border:not(:last-child) { + border-bottom: 1px solid #6e6e6e; + } } } From 55de5ace07a47c7a60f595a4370efa18977d17f7 Mon Sep 17 00:00:00 2001 From: Cameron Fraser Date: Tue, 12 Dec 2023 16:45:13 -0800 Subject: [PATCH 4/9] sort metadata categories before values --- .../components/MetadataViewer/index.tsx | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/aics-image-viewer/components/MetadataViewer/index.tsx b/src/aics-image-viewer/components/MetadataViewer/index.tsx index d5758c46..418fedf1 100644 --- a/src/aics-image-viewer/components/MetadataViewer/index.tsx +++ b/src/aics-image-viewer/components/MetadataViewer/index.tsx @@ -17,7 +17,25 @@ interface CollapsibleCategoryProps extends MetadataTableProps { title: string; } -const isCategory = (val: MetadataEntry): val is MetadataRecord => typeof val === "object" && val !== null; +const isCategory = (entry: MetadataEntry): entry is MetadataRecord => typeof entry === "object" && entry !== null; + +const sortCategoriesFirst = (entry: MetadataEntry): MetadataEntry => { + if (!isCategory(entry) || Array.isArray(entry)) { + return entry; + } + + const cats: MetadataRecord = {}; + const vals: MetadataRecord = {}; + for (const key in entry) { + if (isCategory(entry[key])) { + cats[key] = entry[key]; + } else { + vals[key] = entry[key]; + } + } + + return { ...cats, ...vals }; +}; /** Component to hold collapse state */ const MetadataCategory: React.FC = ({ metadata, title, categoryFollows }) => { @@ -54,7 +72,7 @@ const MetadataTable: React.FC = ({ metadata, categoryFollows
{metadataKeys.map((key, idx) => { - const metadataValue = metadataIsArray ? metadata[idx] : metadata[key]; + const metadataValue = sortCategoriesFirst(metadataIsArray ? metadata[idx] : metadata[key]); if (isCategory(metadataValue)) { // Determine whether this category is followed by another category, ignoring data hierarchy: From fe1a9627e9216f5fa3b9bd453129fa9c4e7b8899 Mon Sep 17 00:00:00 2001 From: Cameron Fraser Date: Tue, 12 Dec 2023 16:59:47 -0800 Subject: [PATCH 5/9] fix metadata category title border misalignment, mostly --- .../components/MetadataViewer/styles.css | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/aics-image-viewer/components/MetadataViewer/styles.css b/src/aics-image-viewer/components/MetadataViewer/styles.css index d667a979..a9b127e2 100644 --- a/src/aics-image-viewer/components/MetadataViewer/styles.css +++ b/src/aics-image-viewer/components/MetadataViewer/styles.css @@ -5,8 +5,10 @@ &.metadata-top-level { border-bottom: 1px solid #6e6e6e; - > tbody > tr.metadata-collapse-title:first-child { - border-top: none; + > tbody { + > tr.metadata-collapse-title:first-child { + border-top: none; + } } } @@ -24,9 +26,15 @@ color: white; background-color: #4b4b4b; border-top: 1px solid #6e6e6e; + > td { + padding-bottom: 5px; + } &.metadata-collapse-collapsed.metadata-collapse-bottom-border:not(:nth-last-child(2)) { border-bottom: 1px solid #6e6e6e; + > td { + padding-bottom: 6px; + } } } From 443c25894b8fdd232446e71c305af2f4f277afb8 Mon Sep 17 00:00:00 2001 From: Cameron Fraser Date: Tue, 12 Dec 2023 17:08:50 -0800 Subject: [PATCH 6/9] fix border misalignments all the way --- .../components/MetadataViewer/styles.css | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/aics-image-viewer/components/MetadataViewer/styles.css b/src/aics-image-viewer/components/MetadataViewer/styles.css index a9b127e2..0b268cdd 100644 --- a/src/aics-image-viewer/components/MetadataViewer/styles.css +++ b/src/aics-image-viewer/components/MetadataViewer/styles.css @@ -5,10 +5,14 @@ &.metadata-top-level { border-bottom: 1px solid #6e6e6e; - > tbody { - > tr.metadata-collapse-title:first-child { + > tbody > tr.metadata-collapse-title { + &:first-child { border-top: none; } + + &:nth-last-child(2).metadata-collapse-collapsed > td { + padding-bottom: 6px; + } } } From 36945d373079286ae12bf49e78b7210e1548cf52 Mon Sep 17 00:00:00 2001 From: Cameron Fraser Date: Tue, 12 Dec 2023 17:38:39 -0800 Subject: [PATCH 7/9] document my incomprehensible css --- .../components/MetadataViewer/styles.css | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/aics-image-viewer/components/MetadataViewer/styles.css b/src/aics-image-viewer/components/MetadataViewer/styles.css index 0b268cdd..55ffa2dd 100644 --- a/src/aics-image-viewer/components/MetadataViewer/styles.css +++ b/src/aics-image-viewer/components/MetadataViewer/styles.css @@ -2,6 +2,7 @@ width: 100%; table-layout: fixed; + /* On the top nest level, the top border is given by the panel header, and the bottom by the containing table */ &.metadata-top-level { border-bottom: 1px solid #6e6e6e; @@ -20,7 +21,7 @@ padding: 10px; } - /* Table rows */ + /* ----- TABLE ROWS ----- */ tr { &:nth-child(odd) { background-color: #3a3a3a; @@ -34,6 +35,11 @@ padding-bottom: 5px; } + /* This complex rule decides if the title should have its own bottom border, or if a line is already drawn below: + - If the category is not collapsed, the bottom border is the responsibility of the content row + - If the next sibling is a category (React determines this), they are separated by the sibling's top border + - If this is the last entry in its category, the parent category's longer bottom border is below + */ &.metadata-collapse-collapsed.metadata-collapse-bottom-border:not(:nth-last-child(2)) { border-bottom: 1px solid #6e6e6e; > td { @@ -51,13 +57,14 @@ display: none; } + /* Same as above, but the content takes the bottom border when this category is NOT collapsed. */ &:not(.metadata-collapse-collapsed).metadata-collapse-bottom-border:not(:last-child) { border-bottom: 1px solid #6e6e6e; } } } - /* Table cells */ + /* ----- TABLE CELLS ----- */ td { padding: 6px 0; overflow-wrap: break-word; From f39c2aaf57c4a44b0522704c0ee1504b432ad6a2 Mon Sep 17 00:00:00 2001 From: Cameron Fraser Date: Tue, 12 Dec 2023 18:52:24 -0800 Subject: [PATCH 8/9] there was an easier way to do borders this whole time... --- .../components/MetadataViewer/index.tsx | 30 +++------ .../components/MetadataViewer/styles.css | 65 +++++++------------ 2 files changed, 31 insertions(+), 64 deletions(-) diff --git a/src/aics-image-viewer/components/MetadataViewer/index.tsx b/src/aics-image-viewer/components/MetadataViewer/index.tsx index 418fedf1..d68c65e8 100644 --- a/src/aics-image-viewer/components/MetadataViewer/index.tsx +++ b/src/aics-image-viewer/components/MetadataViewer/index.tsx @@ -5,11 +5,6 @@ import "./styles.css"; interface MetadataTableProps { metadata: MetadataRecord; - // Track whether a category title will abut another category title below when in the collapsed state. - // If so, this category title should not render a bottom border when collapsed, otherwise the border will double - // up with the top border of the lower category and create the appearance of a single thick, uneven border. - // (there is not a way to prevent this with pure CSS to my knowledge) - categoryFollows: boolean; topLevel?: boolean; } @@ -38,16 +33,13 @@ const sortCategoriesFirst = (entry: MetadataEntry): MetadataEntry => { }; /** Component to hold collapse state */ -const MetadataCategory: React.FC = ({ metadata, title, categoryFollows }) => { +const MetadataCategory: React.FC = ({ metadata, title }) => { const [collapsed, setCollapsed] = React.useState(true); - const toggleCollapsed = (): void => setCollapsed(!collapsed); - - const rowClass = - (collapsed ? " metadata-collapse-collapsed" : "") + (!categoryFollows ? " metadata-collapse-bottom-border" : ""); + const collapsedClass = collapsed ? " metadata-collapse-collapsed" : ""; return ( <> - + setCollapsed(!collapsed)}> - + ); }; -const MetadataTable: React.FC = ({ metadata, categoryFollows, topLevel }) => { +const MetadataTable: React.FC = ({ metadata, topLevel }) => { const metadataKeys = Object.keys(metadata); const metadataIsArray = Array.isArray(metadata); @@ -75,13 +67,7 @@ const MetadataTable: React.FC = ({ metadata, categoryFollows const metadataValue = sortCategoriesFirst(metadataIsArray ? metadata[idx] : metadata[key]); if (isCategory(metadataValue)) { - // Determine whether this category is followed by another category, ignoring data hierarchy: - // - If this is the last element in the table, this category has another category below if the table does. - // - Otherwise, just check if the next element in this table is a category. - const nextItem = metadataIsArray ? metadata[idx + 1] : metadata[metadataKeys[idx + 1]]; - const categoryBelow = idx + 1 >= metadataKeys.length ? isCategory(nextItem) : categoryFollows; - - return ; + return ; } else { return ( @@ -97,7 +83,7 @@ const MetadataTable: React.FC = ({ metadata, categoryFollows }; const MetadataViewer: React.FC<{ metadata: MetadataRecord }> = ({ metadata }) => ( - + ); export default MetadataViewer; diff --git a/src/aics-image-viewer/components/MetadataViewer/styles.css b/src/aics-image-viewer/components/MetadataViewer/styles.css index 55ffa2dd..e76fe595 100644 --- a/src/aics-image-viewer/components/MetadataViewer/styles.css +++ b/src/aics-image-viewer/components/MetadataViewer/styles.css @@ -2,65 +2,47 @@ width: 100%; table-layout: fixed; + tbody { + padding: 10px; + } + /* On the top nest level, the top border is given by the panel header, and the bottom by the containing table */ &.metadata-top-level { border-bottom: 1px solid #6e6e6e; - > tbody > tr.metadata-collapse-title { - &:first-child { - border-top: none; - } - - &:nth-last-child(2).metadata-collapse-collapsed > td { - padding-bottom: 6px; - } + > tbody > tr.metadata-row-collapse-title:first-child { + border-top: none; } } - tbody { - padding: 10px; - } - /* ----- TABLE ROWS ----- */ tr { - &:nth-child(odd) { + &:nth-child(odd):not(.metadata-row-collapse-content) { background-color: #3a3a3a; } - &.metadata-collapse-title { + /* CATEGORY TITLE */ + &.metadata-row-collapse-title { color: white; - background-color: #4b4b4b; - border-top: 1px solid #6e6e6e; - > td { - padding-bottom: 5px; - } + background-color: #4b4b4b !important; - /* This complex rule decides if the title should have its own bottom border, or if a line is already drawn below: - - If the category is not collapsed, the bottom border is the responsibility of the content row - - If the next sibling is a category (React determines this), they are separated by the sibling's top border - - If this is the last entry in its category, the parent category's longer bottom border is below - */ - &.metadata-collapse-collapsed.metadata-collapse-bottom-border:not(:nth-last-child(2)) { - border-bottom: 1px solid #6e6e6e; - > td { - padding-bottom: 6px; - } + /* Keeps borders aligned when this category opens and closes */ + &:not(.metadata-collapse-collapsed) > td { + padding-bottom: 5px; } } - &.metadata-collapse-content-row { - background-color: #313131; - - &.metadata-collapse-collapsed { - visibility: collapse; - height: 0px; - display: none; - } + /* CATEGORY CONTENT */ + &.metadata-row-collapse-content.metadata-collapse-collapsed { + visibility: collapse; + height: 0px; + display: none; + } - /* Same as above, but the content takes the bottom border when this category is NOT collapsed. */ - &:not(.metadata-collapse-collapsed).metadata-collapse-bottom-border:not(:last-child) { - border-bottom: 1px solid #6e6e6e; - } + /* ROW BORDERS: all categories have top borders; any row which follows a category provides its bottom border */ + tr.metadata-row-collapse-title, + &.metadata-row-collapse-content + tr { + border-top: 1px solid #6e6e6e; } } @@ -92,7 +74,6 @@ &.metadata-collapse-content { padding: 0; padding-left: 24px; - border-bottom: none; } i { From 02ebc3465738c263369f78310283ec7eba3fa459 Mon Sep 17 00:00:00 2001 From: Cameron Fraser Date: Tue, 12 Dec 2023 19:03:23 -0800 Subject: [PATCH 9/9] fix metadata viewer prop types --- .../components/MetadataViewer/index.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/aics-image-viewer/components/MetadataViewer/index.tsx b/src/aics-image-viewer/components/MetadataViewer/index.tsx index d68c65e8..98e7f827 100644 --- a/src/aics-image-viewer/components/MetadataViewer/index.tsx +++ b/src/aics-image-viewer/components/MetadataViewer/index.tsx @@ -3,14 +3,15 @@ import React from "react"; import { MetadataEntry, MetadataRecord } from "../../shared/types"; import "./styles.css"; -interface MetadataTableProps { +type MetadataTableProps = { metadata: MetadataRecord; topLevel?: boolean; -} +}; -interface CollapsibleCategoryProps extends MetadataTableProps { +type CollapsibleCategoryProps = { + metadata: MetadataRecord; title: string; -} +}; const isCategory = (entry: MetadataEntry): entry is MetadataRecord => typeof entry === "object" && entry !== null;
@@ -55,16 +47,16 @@ const MetadataCategory: React.FC = ({ metadata, title, {title}
- +