From b1ec1a51196cb5df7f71f5a5ad389d7d9a6c685f Mon Sep 17 00:00:00 2001 From: Marissa Huysentruyt Date: Tue, 27 May 2025 17:32:08 -0400 Subject: [PATCH 01/17] feat(table): adds light/dark custom vars for selected row --- tokens/custom/dark-vars.css | 2 ++ tokens/custom/light-vars.css | 2 ++ 2 files changed, 4 insertions(+) diff --git a/tokens/custom/dark-vars.css b/tokens/custom/dark-vars.css index 2f1fd03fed2..50174fa532e 100644 --- a/tokens/custom/dark-vars.css +++ b/tokens/custom/dark-vars.css @@ -57,6 +57,8 @@ --spectrum-steplist-current-marker-color-key-focus: var(--spectrum-blue-700); + --spectrum-table-selected-row-background-color-rgb: var(--spectrum-blue-800-rgb); + --spectrum-treeview-item-background-color-quiet-selected: rgb(var(--spectrum-gray-900-rgb), 0.07); --spectrum-treeview-item-background-color-selected: rgb(var(--spectrum-blue-800-rgb), 0.15); } diff --git a/tokens/custom/light-vars.css b/tokens/custom/light-vars.css index 7f344e23fa7..f1ae0d95ed2 100644 --- a/tokens/custom/light-vars.css +++ b/tokens/custom/light-vars.css @@ -55,6 +55,8 @@ --spectrum-steplist-current-marker-color-key-focus: var(--spectrum-blue-800); + --spectrum-table-selected-row-background-color-rgb: var(--spectrum-blue-900-rgb); + --spectrum-treeview-item-background-color-quiet-selected: rgb(var(--spectrum-gray-900-rgb), 0.06); --spectrum-treeview-item-background-color-selected: rgb(var(--spectrum-blue-900-rgb), 0.1); } From da31efabda9d58770fadf45a370ddd8cf8cca03a Mon Sep 17 00:00:00 2001 From: Marissa Huysentruyt Date: Wed, 28 May 2025 11:34:45 -0400 Subject: [PATCH 02/17] docs(table): add focused cell to table states story --- components/table/stories/table.stories.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/components/table/stories/table.stories.js b/components/table/stories/table.stories.js index ff16c7518bb..d9026cfd0c2 100644 --- a/components/table/stories/table.stories.js +++ b/components/table/stories/table.stories.js @@ -384,8 +384,11 @@ TableStates.args = { cellContent: "Table row bravo", }, { - cellContent: "Selected unfocused row, no rounded corners", + cellContent: ["Selected unfocused row, with a focused cell", "Focused cell", "Unfocused cell"], isSelected: true, + cellCustomClasses: { + 1: ["is-focused"] + } }, { cellContent: "Focused unselected row, no rounded corners", From b38534339ce9db74d2f2d05447f53f7d63d8a56c Mon Sep 17 00:00:00 2001 From: Marissa Huysentruyt Date: Tue, 27 May 2025 18:01:29 -0400 Subject: [PATCH 03/17] feat(table): update tokens to s2 colors - updates row colors for header row, summary, section header, and selected row - updates sort icon colors - updates disclosure/menu icons - fixes checkbox indeterminate icon color - adds .spectrum-Table-headCell--alignEnd class - selected rows have a 1px border around all cells in blue - row focus should be indicated by the side-focus-indicator regardless of selection state. this means a focused+unselected row will have a 1px gray border around cells, while a focused+selected row will have a 1px blue border around cells. - adjacent selected rows have a 1px border between them in blue (avoids duplicate borders between cells) - adds support for CJK languages for line-height - adds missing font tokens for header and body row text - remove quiet table cell background colors lines - there's not really color changes specc'd out for the header table cell background states, so header table cell background states are removed - quiet and scroller styles fixed up --- components/table/index.css | 182 +++++++++++++++++++++++++------------ 1 file changed, 124 insertions(+), 58 deletions(-) diff --git a/components/table/index.css b/components/table/index.css index 3fd1f5f836b..04cf3824af6 100644 --- a/components/table/index.css +++ b/components/table/index.css @@ -16,15 +16,17 @@ --spectrum-table-transition-duration: var(--spectrum-animation-duration-100); /* Background colors */ - --spectrum-table-header-background-color: var(--spectrum-transparent-white-25); + --spectrum-table-header-background-color: var(--spectrum-gray-75); --spectrum-table-row-background-color: var(--spectrum-gray-25); - /* @todo Refactor or remove these properties once the RGB stripped value is available. */ - --spectrum-table-row-background-color-hover: rgb(var(--spectrum-gray-900-rgb), var(--spectrum-table-row-hover-opacity)); + --spectrum-table-summary-row-background-color: var(--spectrum-gray-200); - --spectrum-table-section-header-background-color: var(--spectrum-gray-100); - --spectrum-table-selected-row-background-color: rgb(var(--spectrum-blue-900-rgb), var(--spectrum-table-selected-row-background-opacity)); + --spectrum-table-section-header-background-color: var(--spectrum-gray-200); + + /* @todo Refactor or remove these properties once the RGB stripped value is available. */ + --spectrum-table-selected-row-background-color: rgb(var(--spectrum-table-selected-row-background-color-rgb), var(--spectrum-table-selected-row-background-opacity)); --spectrum-table-selected-row-background-color-non-emphasized: rgb(var(--spectrum-gray-700-rgb), var(--spectrum-table-selected-row-background-opacity-non-emphasized)); - --spectrum-table-selected-row-background-color-focus: rgb(var(--spectrum-blue-900-rgb), var(--spectrum-table-selected-row-background-opacity-hover)); + --spectrum-table-selected-row-background-color-hover: rgb(var(--spectrum-table-selected-row-background-color-rgb), var(--spectrum-table-selected-row-background-opacity-hover)); + --spectrum-table-selected-row-background-color-active: rgb(var(--spectrum-table-selected-row-background-color-rgb), var(--spectrum-table-selected-row-background-opacity-hover)); --spectrum-table-selected-row-background-color-non-emphasized-focus: rgb(var(--spectrum-gray-700-rgb), var(--spectrum-table-selected-row-background-opacity-non-emphasized-hover)); --spectrum-table-cell-background-color: var(--highcontrast-table-row-background-color, var(--mod-table-row-background-color, var(--spectrum-table-row-background-color))); @@ -33,8 +35,10 @@ --spectrum-table-drop-zone-background-color: rgb(var(--spectrum-drop-zone-background-color-rgb), var(--spectrum-drop-zone-background-color-opacity)); --spectrum-table-drop-zone-outline-color: var(--spectrum-accent-visual-color); - /* Row Selection */ - --spectrum-table-row-active-color: rgb(var(--spectrum-gray-900-rgb), var(--spectrum-table-row-down-opacity)); /* active/down state background color */ + /* Row States */ + /* @todo Refactor or remove these properties once the RGB stripped value is available. */ + --spectrum-table-row-background-color-hover: rgb(var(--spectrum-gray-900-rgb), var(--spectrum-table-row-hover-opacity)); + --spectrum-table-row-background-color-active: rgb(var(--spectrum-gray-900-rgb), var(--spectrum-table-row-down-opacity)); /* active/down state background color */ /* Border */ --spectrum-table-border-color: var(--spectrum-gray-300); @@ -56,15 +60,18 @@ --spectrum-table-selected-cell-background-color-focus: var(--highcontrast-table-selected-row-background-color-focus, var(--mod-table-selected-row-background-color-non-emphasized-focus, var(--spectrum-table-selected-row-background-color-non-emphasized-focus))); /* Visual (avatar, icons, thumbnails) */ - --spectrum-table-icon-color-default: var(--spectrum-neutral-subdued-content-color-default); - --spectrum-table-icon-color-hover: var(--spectrum-neutral-subdued-content-color-hover); - --spectrum-table-icon-color-active: var(--spectrum-neutral-subdued-content-color-down); - --spectrum-table-icon-color-focus: var(--spectrum-neutral-subdued-content-color-key-focus); - --spectrum-table-icon-color-focus-hover: var(--spectrum-neutral-subdued-content-color-key-focus); - --spectrum-table-icon-color-key-focus: var(--spectrum-neutral-subdued-content-color-key-focus); + --spectrum-table-icon-color-default: var(--spectrum-neutral-content-color-default); + --spectrum-table-icon-color-hover: var(--spectrum-neutral-content-color-hover); + --spectrum-table-icon-color-active: var(--spectrum-neutral-content-color-down); + --spectrum-table-icon-color-key-focus: var(--spectrum-neutral-content-color-key-focus); --spectrum-table-disclosure-icon-size: var(--spectrum-component-height-100); --spectrum-table-icon-color: var(--highcontrast-table-icon-color, var(--mod-table-icon-color-default, var(--spectrum-table-icon-color-default))); + --spectrum-table-header-icons-color-default: var(--spectrum-neutral-subdued-content-color-default); + --spectrum-table-header-icons-color-hover: var(--spectrum-neutral-subdued-content-color-hover); + --spectrum-table-header-icons-color-active: var(--spectrum-neutral-subdued-content-color-down); + --spectrum-table-header-icons-color-key-focus: var(--spectrum-neutral-subdued-content-color-key-focus); + /* Alignment */ --spectrum-table-default-vertical-align: middle; @@ -77,6 +84,9 @@ --spectrum-table-row-font-style: var(--spectrum-default-font-style); --spectrum-table-row-line-height: var(--spectrum-line-height-100); --spectrum-table-row-text-color: var(--spectrum-neutral-content-color-default); + --spectrum-table-row-text-color-hover: var(--spectrum-neutral-content-color-hover); + --spectrum-table-row-text-color-active: var(--spectrum-neutral-content-color-down); + --spectrum-table-row-text-color-key-focus: var(--spectrum-neutral-content-color-key-focus); --spectrum-table-row-font-size: var(--spectrum-font-size-100); --spectrum-table-summary-row-font-weight: var(--spectrum-bold-font-weight); @@ -136,6 +146,12 @@ &:dir(rtl) { --spectrum-logical-rotation: matrix(-1, 0, 0, 1, 0, 0); } + + &:lang(ja), + &:lang(zh), + &:lang(ko) { + --spectrum-table-row-line-height: var(--spectrum-cjk-line-height-100); + } } /********* VARIANTS *********/ @@ -170,36 +186,48 @@ .spectrum-Table--emphasized, .spectrum-Table-row .is-emphasized { --spectrum-table-selected-cell-background-color: var(--highcontrast-table-selected-row-background-color, var(--mod-table-selected-row-background-color, var(--spectrum-table-selected-row-background-color))); - --spectrum-table-selected-cell-background-color-focus: var(--highcontrast-table-selected-row-background-color-focus, var(--mod-table-selected-row-background-color-focus, var(--spectrum-table-selected-row-background-color-focus))); + --spectrum-table-selected-cell-background-color-focus: var(--highcontrast-table-selected-row-background-color-focus, var(--mod-table-selected-row-background-color-focus, var(--spectrum-table-selected-row-background-color-hover))); } .spectrum-Table--quiet { --spectrum-table-border-radius: var(--mod-table-border-radius-quiet, 0px); --spectrum-table-outer-border-inline-width: var(--mod-table-outer-border-inline-width-quiet, 0px); - --spectrum-table-header-background-color: var(--mod-table-header-background-color-quiet, var(--spectrum-transparent-white-100)); - --spectrum-table-row-background-color: var(--mod-table-row-background-color-quiet, var(--spectrum-transparent-white-100)); - --spectrum-table-border-color: transparent; } -.spectrum-Table-row { - &:hover, +.spectrum-Table-row, +.spectrum-Table-headRow { + &.is-focused, &:focus-visible, - &.is-focused { + &:focus { + --highcontrast-table-row-text-color: var(--highcontrast-table-row-text-color-focus); + --highcontrast-table-icon-color: var(--highcontrast-table-row-text-color-focus); + --spectrum-table-row-text-color: var(--spectrum-table-row-text-color-key-focus); + + &:hover { + --spectrum-table-row-text-color: var(--spectrum-table-row-text-color-key-focus); + } + } + + &:hover { --highcontrast-table-row-text-color: var(--highcontrast-table-row-text-color-hover); --highcontrast-table-icon-color: var(--highcontrast-table-row-text-color-hover); --spectrum-table-cell-background-color: var(--highcontrast-table-row-background-color-hover, var(--mod-table-row-background-color-hover, var(--spectrum-table-row-background-color-hover))); + --spectrum-table-row-text-color: var(--highcontrast-table-row-text-color-hover, var(--mod-table-row-text-color-hover, var(--spectrum-table-row-text-color-hover))); } &:active { --highcontrast-table-row-text-color: var(--highcontrast-table-row-text-color-hover); --highcontrast-table-icon-color: var(--highcontrast-table-row-text-color-hover); - --spectrum-table-cell-background-color: var(--highcontrast-table-row-background-color-hover, var(--mod-table-row-active-color, var(--spectrum-table-row-active-color))); + --spectrum-table-cell-background-color: var(--highcontrast-table-row-background-color-hover, var(--mod-table-row-background-color-active-color, var(--spectrum-table-row-background-color-active))); + --spectrum-table-row-text-color: var(--highcontrast-table-row-text-color-hover, var(--mod-table-row-text-color-active, var(--spectrum-table-row-text-color-active))); } &.is-selected { --highcontrast-table-row-text-color: var(--highcontrast-table-selected-row-text-color); --highcontrast-table-icon-color: var(--highcontrast-table-selected-row-text-color); --spectrum-table-cell-background-color: var(--highcontrast-table-selected-row-background-color, var(--spectrum-table-selected-cell-background-color)); + --spectrum-table-divider-color: var(--spectrum-table-focus-indicator-color); + --spectrum-table-border-color: var(--spectrum-table-focus-indicator-color); &:hover, &:focus-visible, @@ -208,6 +236,10 @@ --highcontrast-table-icon-color: var(--highcontrast-table-selected-row-text-color-focus); --spectrum-table-cell-background-color: var(--highcontrast-table-selected-row-background-color-focus, var(--spectrum-table-selected-cell-background-color-focus)); } + + &:active { + --spectrum-table-cell-background-color: var(--spectrum-table-selected-row-background-color-active); + } } &.is-drop-target, @@ -222,24 +254,17 @@ &.is-sortable, &.spectrum-Table-hasMenuButton { &:hover { - --spectrum-table-icon-color: var(--highcontrast-table-icon-color-focus, var(--mod-table-icon-color-hover, var(--spectrum-table-icon-color-hover))); + --spectrum-table-icon-color: var(--highcontrast-table-icon-color-focus, var(--mod-table-header-icons-color-hover, var(--spectrum-table-header-icons-color-hover))); } &:active { - --spectrum-table-icon-color: var(--highcontrast-table-icon-color-focus, var(--mod-table-icon-color-active, var(--spectrum-table-icon-color-active))); - } - - &:focus { - --spectrum-table-icon-color: var(--highcontrast-table-icon-color-focus, var(--mod-table-icon-color-focus, var(--spectrum-table-icon-color-focus))); - } - - &:focus:hover { - --spectrum-table-icon-color: var(--highcontrast-table-icon-color-focus, var(--mod-table-icon-color-focus-hover, var(--spectrum-table-icon-color-focus-hover))); + --spectrum-table-icon-color: var(--highcontrast-table-icon-color-focus, var(--mod-table-header-icons-color-active, var(--spectrum-table-header-icons-color-active))); } + &:focus, &:focus-visible, &.is-keyboardFocused { - --spectrum-table-icon-color: var(--highcontrast-table-icon-color-focus, var(--mod-table-icon-color-key-focus, var(--spectrum-table-icon-color-key-focus))); + --spectrum-table-icon-color: var(--highcontrast-table-icon-color-focus, var(--mod-table-header-icons-color-key-focus, var(--spectrum-table-header-icons-color-key-focus))); } } @@ -249,14 +274,33 @@ --spectrum-table-header-row-top-to-text: 0; --spectrum-table-header-row-bottom-to-text: 0; } -} -.spectrum-Table-scroller { - --spectrum-table-header-background-color: var(--mod-table-header-background-color-scrollable, var(--spectrum-background-layer-1-color, var(--spectrum-gray-75))); + /* These styles get applied to the icon within that menu button. */ + & .spectrum-Table-menuButton { + --mod-icon-color: var(--spectrum-table-icon-color); + + &:hover { + --mod-icon-color: var(--spectrum-table-icon-color-hover); + } + + &:active { + --mod-icon-color: var(--spectrum-table-icon-color-active); + } + + &:focus, + &:focus:hover, + &:focus-visible { + --mod-icon-color: var(--spectrum-table-icon-color-key-focus); + } + } } .spectrum-Table-row--summary { --spectrum-table-cell-background-color: var(--highcontrast-table-row-background-color, var(--mod-table-summary-row-background-color, var(--spectrum-table-summary-row-background-color))); + + &:hover { + --spectrum-table-cell-background-color: var(--highcontrast-table-row-background-color, var(--mod-table-summary-row-background-color, var(--spectrum-table-summary-row-background-color))); + } } .spectrum-Table-row--sectionHeader { @@ -286,6 +330,7 @@ font-family: var(--mod-table-header-font-family, var(--spectrum-table-row-font-family)); font-size: var(--mod-table-header-font-size, var(--spectrum-table-row-font-size)); font-weight: var(--mod-table-header-font-weight, var(--spectrum-table-header-font-weight)); + font-style: var(--mod-table-header-font-style, var(--spectrum-table-row-font-style)); line-height: var(--mod-table-header-line-height, var(--spectrum-table-row-line-height)); text-transform: var(--mod-table-header-text-transform, none); @@ -340,6 +385,28 @@ } } +/* Quiet table header rows do not have inline borders */ +.spectrum-Table--quiet .spectrum-Table-headRow:first-child { + .spectrum-Table-headCell:first-child { + border-inline-start: 0; + } + + .spectrum-Table-headCell:last-child { + border-inline-end: 0; + } +} + +/* Quiet table header rows do not have inline borders */ +.spectrum-Table--quiet .spectrum-Table-headRow:first-child { + .spectrum-Table-headCell:first-child { + border-inline-start: 0; + } + + .spectrum-Table-headCell:last-child { + border-inline-end: 0; + } +} + /********* ICONS- SORT, DISCLOSURE/MENU *********/ /* Head cell column text */ .spectrum-Table-columnTitle { @@ -408,7 +475,8 @@ text-align: start; } -.spectrum-Table-cell--alignEnd { +.spectrum-Table-cell--alignEnd, +.spectrum-Table-headRow .spectrum-Table-headCell--alignEnd { text-align: end; } @@ -453,6 +521,8 @@ /* Cells within table body */ box-sizing: border-box; + font-family: var(--mod-table-row-font-family, var(--spectrum-table-row-font-family)); + font-style: var(--mod-table-row-font-style, var(--spectrum-table-row-font-style)); font-size: var(--mod-table-row-font-size, var(--spectrum-table-row-font-size)); font-weight: var(--mod-table-row-font-weight, var(--spectrum-table-row-font-weight)); line-height: var(--mod-table-row-line-height, var(--spectrum-table-row-line-height)); @@ -557,6 +627,19 @@ border-end-end-radius: var(--mod-table-border-radius, var(--spectrum-table-border-radius)); } + /* Selected rows */ + &.is-selected { + .spectrum-Table-cell { + /* Remove bottom border by default for all selected rows to conditionally add it back. */ + border-block-end: none; + } + } + + /* Adding the bottom border only to the last selected row in a sequence achieves 1px border between adjacent selected rows */ + &.is-selected:not(:has(+ .is-selected)) .spectrum-Table-cell { + border-block-end: var(--mod-table-border-width, var(--spectrum-table-border-width)) solid var(--highcontrast-table-focus-indicator-color, var(--mod-table-focus-indicator-color, var(--spectrum-table-focus-indicator-color))); + } + /* Row focus indicator */ &.is-focused, &:focus-visible, @@ -567,9 +650,8 @@ .spectrum-Table-cell:first-child { position: relative; border-inline-start: 0; - border-block: var(--spectrum-table-border-width) solid var(--highcontrast-table-focus-indicator-color, var(--mod-table-focus-indicator-color, var(--spectrum-table-focus-indicator-color))); - /* Because the ::before element technically removes the table's inline border, the first cell needs the entire cell padding to avoid horizontal layout shift when a row is focused. */ + /* Because the ::before element technically removes the table's inline border, the first cell needs the entire cell-inline-padding padding to avoid horizontal layout shift when a row is focused. */ padding-inline-start: var(--mod-table-cell-inline-spacing, var(--spectrum-table-cell-inline-spacing)); /* The side row focus indicator line */ @@ -585,19 +667,6 @@ } } - /* All other cells in focused rows (including the first rows after the header row and last rows in the table) need the focus indicator border */ - &:first-child .spectrum-Table-cell, - &:last-child .spectrum-Table-cell, - .spectrum-Table-cell { - border-block: var(--spectrum-table-border-width) solid var(--highcontrast-table-focus-indicator-color, var(--mod-table-focus-indicator-color, var(--spectrum-table-focus-indicator-color))); - } - - /* Last cell of focused row needs the fancy new focus indicator borders at the end */ - .spectrum-Table-cell:last-child { - border-inline-end: var(--spectrum-table-border-width) solid var(--highcontrast-table-focus-indicator-color, var(--mod-table-focus-indicator-color, var(--spectrum-table-focus-indicator-color))); - border-block-end: var(--spectrum-table-border-width) solid var(--highcontrast-table-focus-indicator-color, var(--mod-table-focus-indicator-color, var(--spectrum-table-focus-indicator-color))); - } - /* In a focused row that is last in the table, the first cell needs rounded corners at the bottom of the row focus indicator line */ &:last-child .spectrum-Table-cell:first-child::before { border-end-start-radius: var(--mod-table-border-radius, var(--spectrum-table-border-radius)); @@ -707,10 +776,6 @@ --mod-table-current-header-height should be dynamically updated with JS to match the table header height. */ scroll-padding-top: var(--mod-table-current-header-height, calc((var(--mod-table-header-line-height, var(--spectrum-table-row-line-height)) * var(--mod-table-header-font-size, var(--spectrum-table-row-font-size))) + var(--mod-table-header-row-top-to-text, var(--spectrum-table-header-row-top-to-text)) + var(--mod-table-header-row-bottom-to-text, var(--spectrum-table-header-row-bottom-to-text)) + var(--mod-table-border-width, var(--spectrum-table-border-width)))); - &.spectrum-Table--quiet { - border-block-start: none; - } - .spectrum-Table-head { position: sticky; inset-block-start: 0; @@ -844,10 +909,10 @@ } &:focus { - --spectrum-table-icon-color: var(--highcontrast-table-icon-color, var(--mod-table-icon-color-focus, var(--spectrum-table-icon-color-focus))); + --spectrum-table-icon-color: var(--highcontrast-table-icon-color, var(--mod-table-icon-color-focus, var(--spectrum-table-icon-color-key-focus))); &:hover { - --spectrum-table-icon-color: var(--highcontrast-table-icon-color, var(--mod-table-icon-color-focus-hover, var(--spectrum-table-icon-color-focus-hover))); + --spectrum-table-icon-color: var(--highcontrast-table-icon-color, var(--mod-table-icon-color-focus-hover, var(--spectrum-table-icon-color-key-focus))); } } @@ -903,6 +968,7 @@ --highcontrast-table-selected-row-text-color-focus: HighlightText; --highcontrast-table-row-background-color-hover: Highlight; --highcontrast-table-row-text-color-hover: HighlightText; + --highcontrast-table-row-text-color-focus: HighlightText; --highcontrast-table-section-header-text-color: Canvas; --highcontrast-table-section-header-background-color: CanvasText; From 45754e08af25354ad719bdea6a2321ee83cef24f Mon Sep 17 00:00:00 2001 From: Marissa Huysentruyt Date: Tue, 3 Jun 2025 09:06:05 -0400 Subject: [PATCH 04/17] fix(table): correct the WHCM text color - in focused unselected rows, the text color was the same as the background color. This is now fixed, and should also distinguish the focused+selected rows from the focused+unselected rows as well. --- components/table/index.css | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/components/table/index.css b/components/table/index.css index 04cf3824af6..574de0d86a8 100644 --- a/components/table/index.css +++ b/components/table/index.css @@ -199,7 +199,6 @@ &.is-focused, &:focus-visible, &:focus { - --highcontrast-table-row-text-color: var(--highcontrast-table-row-text-color-focus); --highcontrast-table-icon-color: var(--highcontrast-table-row-text-color-focus); --spectrum-table-row-text-color: var(--spectrum-table-row-text-color-key-focus); @@ -277,20 +276,20 @@ /* These styles get applied to the icon within that menu button. */ & .spectrum-Table-menuButton { - --mod-icon-color: var(--spectrum-table-icon-color); + --mod-icon-color: var(--spectrum-table-header-icons-color-default); &:hover { - --mod-icon-color: var(--spectrum-table-icon-color-hover); + --mod-icon-color: var(--spectrum-table-header-icons-color-hover); } &:active { - --mod-icon-color: var(--spectrum-table-icon-color-active); + --mod-icon-color: var(--spectrum-table-header-icons-color-active); } &:focus, &:focus:hover, &:focus-visible { - --mod-icon-color: var(--spectrum-table-icon-color-key-focus); + --mod-icon-color: var(--spectrum-table-header-icons-color-key-focus); } } } From 8dffcf0c33a2a84a13a674466cec1a53db015946 Mon Sep 17 00:00:00 2001 From: Marissa Huysentruyt Date: Tue, 27 May 2025 18:06:12 -0400 Subject: [PATCH 05/17] docs(table): add sparkline chart story - adds hasChartContent arg to story file and story - handles hasChartContent in template markup - add sparkline svgs - add sparkline test case --- .../assets/images/sparkline-informative.svg | 17 +++++++ .../assets/images/sparkline-negative.svg | 17 +++++++ .storybook/assets/images/sparkline-notice.svg | 17 +++++++ .../assets/images/sparkline-positive.svg | 17 +++++++ components/table/stories/table.stories.js | 45 +++++++++++++++++++ components/table/stories/table.test.js | 25 +++++++++++ components/table/stories/template.js | 11 ++++- 7 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 .storybook/assets/images/sparkline-informative.svg create mode 100644 .storybook/assets/images/sparkline-negative.svg create mode 100644 .storybook/assets/images/sparkline-notice.svg create mode 100644 .storybook/assets/images/sparkline-positive.svg diff --git a/.storybook/assets/images/sparkline-informative.svg b/.storybook/assets/images/sparkline-informative.svg new file mode 100644 index 00000000000..5998b3e03b0 --- /dev/null +++ b/.storybook/assets/images/sparkline-informative.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/.storybook/assets/images/sparkline-negative.svg b/.storybook/assets/images/sparkline-negative.svg new file mode 100644 index 00000000000..d31715827f7 --- /dev/null +++ b/.storybook/assets/images/sparkline-negative.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/.storybook/assets/images/sparkline-notice.svg b/.storybook/assets/images/sparkline-notice.svg new file mode 100644 index 00000000000..80d18bc0e30 --- /dev/null +++ b/.storybook/assets/images/sparkline-notice.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/.storybook/assets/images/sparkline-positive.svg b/.storybook/assets/images/sparkline-positive.svg new file mode 100644 index 00000000000..f5a80fa6ec7 --- /dev/null +++ b/.storybook/assets/images/sparkline-positive.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/components/table/stories/table.stories.js b/components/table/stories/table.stories.js index d9026cfd0c2..15994ffbf7d 100644 --- a/components/table/stories/table.stories.js +++ b/components/table/stories/table.stories.js @@ -116,6 +116,17 @@ export default { rowItems: { table: { disable: true }, }, + hasChartContent: { + name: "Chart content in cells", + description: "In some instances, a chart can be displayed in the cells of the table.", + type: { name: "boolean" }, + table: { + type: { summary: "boolean" }, + category: "Component", + disable: true, + }, + control: "boolean", + }, }, args: { rootClass: "spectrum-Table", @@ -129,6 +140,7 @@ export default { useScroller: false, hasColumnDividers: false, hasMenu: false, + hasChartContent: false, isSortable: false, sortIcon: "Sort", rowItems: [ @@ -465,6 +477,39 @@ WithMenuButton.parameters = { }; WithMenuButton.tags = ["!dev"]; +/** + * In some use cases, a sparkline chart can be displayed in a cell of the table. There are informative, negative, positive, and notice sparkline charts available for implementations. + */ +export const WithChartContent = Template.bind({}); +WithChartContent.args = { + hasChartContent: true, + rowItems: [ + { cellContent: ["Informative sparkline", "200", "sparkline-informative.svg"], + textAlignment: { + 1: "end" + } + }, + { cellContent: ["Negative sparkline", "0", "sparkline-negative.svg"], + textAlignment: { + 1: "end" + } + }, + { cellContent: ["Positive sparkline", "600", "sparkline-positive.svg"], + textAlignment: { + 1: "end" + } + },{ cellContent: ["Notice sparkline", "400", "sparkline-notice.svg"], + textAlignment: { + 1: "end" + } + }, + ] +}; +WithChartContent.storyName = "With chart content"; +WithChartContent.parameters = { + chromatic: { disableSnapshot: true }, +}; + /** * A quiet multi-select table has emphasized styling by default, but excluding the `.spectrum-Table--emphasized` class will change the style of selected rows. */ diff --git a/components/table/stories/table.test.js b/components/table/stories/table.test.js index 3d0eba27f69..9bfcb6e8e7a 100644 --- a/components/table/stories/table.test.js +++ b/components/table/stories/table.test.js @@ -492,6 +492,31 @@ export const TableGroup = Variants({ isSelected: true, } ], + }, + { + testHeading: "Sparkline charts", + hasChartContent: true, + rowItems: [ + { cellContent: ["Informative sparkline", "200", "sparkline-informative.svg"], + textAlignment: { + 1: "end" + } + }, + { cellContent: ["Negative sparkline", "0", "sparkline-negative.svg"], + textAlignment: { + 1: "end" + } + }, + { cellContent: ["Positive sparkline", "600", "sparkline-positive.svg"], + textAlignment: { + 1: "end" + } + },{ cellContent: ["Notice sparkline", "400", "sparkline-notice.svg"], + textAlignment: { + 1: "end" + } + }, + ] } ], }); diff --git a/components/table/stories/template.js b/components/table/stories/template.js index f90d4e1e0e8..283d2cce67a 100644 --- a/components/table/stories/template.js +++ b/components/table/stories/template.js @@ -36,6 +36,7 @@ export const TableRowItem = ({ ariaControls, customClasses = [], cellCustomClasses = {}, + hasChartContent = false, } = {}, context = {}) => { const useVisuals = visualElement !== undefined && !isSummaryRow && !isSectionHeader; const useColumnDividers = hasColumnDividers && !isSummaryRow && !isSectionHeader; @@ -199,7 +200,13 @@ export const TableRowItem = ({ [`${rootClass}-cell--alignEnd`]: getTextAlignment(2) === "end", ...cellCustomClasses?.[showCheckbox ? 3 : 2]?.reduce((a, c) => ({ ...a, [c]: true }), {}), })} - >${getCellContent(2)}` + > + ${when(hasChartContent, () => html` +
+ Chart +
+ `, () => getCellContent(2))} + ` )} `; @@ -220,6 +227,7 @@ export const Template = ({ isSortable = false, sortIcon = "Sort", hasMenu = false, + hasChartContent = false, rowItems = [], customClasses = [], id = getRandomId("table"), @@ -368,6 +376,7 @@ export const Template = ({ visualElement, hasColumnDividers, hasMenu, + hasChartContent, isEmphasized, ...item, }, context) From 2671461501a75f586ef2bbb21865f704cb8e0110 Mon Sep 17 00:00:00 2001 From: Marissa Huysentruyt Date: Tue, 3 Jun 2025 10:24:35 -0400 Subject: [PATCH 06/17] feat(table): add sparkline chart styles --- components/table/index.css | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/components/table/index.css b/components/table/index.css index 574de0d86a8..2e37f22e618 100644 --- a/components/table/index.css +++ b/components/table/index.css @@ -945,6 +945,15 @@ } } +/********* SPARKLINE CHARTS *********/ +.spectrum-Table-chartContent { + .spectrum-Table-chartImage { + display: block; + inline-size: fit-content; + block-size: auto; + } +} + /********* HIGH CONTRAST *********/ @media (forced-colors: active) { .spectrum-Table { From d67d829f3d457a5f7372c97114afd6e5d3e1af58 Mon Sep 17 00:00:00 2001 From: Marissa Huysentruyt Date: Fri, 6 Jun 2025 09:54:39 -0400 Subject: [PATCH 07/17] fix(table): button styles in header cell - opts for border on the ::after pesudo element for the button's focus indicator - styles the button so it fills the header cell's space - corrects the icon colors in the head cells --- components/table/index.css | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/components/table/index.css b/components/table/index.css index 2e37f22e618..f09cc3f2815 100644 --- a/components/table/index.css +++ b/components/table/index.css @@ -125,7 +125,6 @@ --mod-avatar-inline-size: var(--mod-table-avatar-size, var(--spectrum-table-avatar-size)); /* Button for menus in header cells */ - --mod-button-border-radius: 0; --mod-button-font-weight: var(--spectrum-table-header-font-weight); --mod-button-font-size: var(--spectrum-table-row-font-size); --mod-button-font-family: var(--spectrum-table-row-font-family); @@ -141,7 +140,7 @@ --mod-button-edge-to-text: var(--spectrum-table-cell-inline-spacing); --mod-button-padding-label-to-icon: var(--spectrum-table-visual-to-text); --mod-button-height: var(--spectrum-table-min-header-row-height); - --mod-button-focus-ring-border-radius: var(--spectrum-table-focused-cell-border-radius); + --mod-button-focus-ring-border-radius: calc(var(--mod-table-border-radius, var(--spectrum-table-focused-cell-border-radius)) - var(--mod-table-border-width, var(--spectrum-table-border-width))); &:dir(rtl) { --spectrum-logical-rotation: matrix(-1, 0, 0, 1, 0, 0); @@ -251,7 +250,10 @@ .spectrum-Table-headCell { &.is-sortable, - &.spectrum-Table-hasMenuButton { + &.spectrum-Table-hasMenuButton, + .spectrum-Table-sortButton { + --spectrum-table-icon-color: var(--mod-table-header-icons-color-default, var(--spectrum-table-header-icons-color-default)); + &:hover { --spectrum-table-icon-color: var(--highcontrast-table-icon-color-focus, var(--mod-table-header-icons-color-hover, var(--spectrum-table-header-icons-color-hover))); } @@ -433,12 +435,20 @@ .spectrum-Table-headCell.spectrum-Table-hasMenuButton { .spectrum-Table-sortButton { min-block-size: calc(var(--spectrum-table-min-header-row-height) + var(--mod-table-border-width, var(--spectrum-table-border-width))); + min-inline-size: 100%; + justify-content: flex-start; - /* Focus indicator- brings the focus indicator above the border and matches the table cell dimensions. */ - &::after { - /* Multiply by 3 to account for the borders on the top, side and bottom of the table cell. */ - inset: calc(3 * var(--mod-table-border-width, var(--spectrum-table-border-width))); + /* Focus indicator- brings the focus indicator above the cell borders and matches the table cell dimensions. */ + &:focus-visible::after, + &.is-focused::after { + inset: var(--mod-table-border-width, var(--spectrum-table-border-width)); z-index: 1; + + /* Remove the box-shadow of .spectrum-Button, which was generating a different corner radius for the focus indicator. */ + box-shadow: none; + + /* Add focus indicator border to match the other table cell focus indicators. */ + border: var(--mod-table-focus-indicator-thickness, var(--spectrum-table-focus-indicator-thickness)) solid var(--highcontrast-table-cell-focus-indicator-color, var(--highcontrast-table-focus-indicator-color, var(--mod-table-focus-indicator-color, var(--spectrum-table-focus-indicator-color)))); } .spectrum-Button-label { From 805084c23ab23a715b4a6d4adda3c75057fec93a Mon Sep 17 00:00:00 2001 From: Marissa Huysentruyt Date: Fri, 6 Jun 2025 09:09:08 -0400 Subject: [PATCH 08/17] chore(table): update metadata --- components/table/dist/metadata.json | 102 +++++++++++++++++++--------- 1 file changed, 71 insertions(+), 31 deletions(-) diff --git a/components/table/dist/metadata.json b/components/table/dist/metadata.json index 277dc9d978c..30f8f827b50 100644 --- a/components/table/dist/metadata.json +++ b/components/table/dist/metadata.json @@ -5,6 +5,8 @@ ".spectrum-Table--compact", ".spectrum-Table--emphasized", ".spectrum-Table--quiet", + ".spectrum-Table--quiet .spectrum-Table-headRow:first-child .spectrum-Table-headCell:first-child", + ".spectrum-Table--quiet .spectrum-Table-headRow:first-child .spectrum-Table-headCell:last-child", ".spectrum-Table--spacious", ".spectrum-Table-body", ".spectrum-Table-body .spectrum-Table-row .spectrum-Table-cell:first-child", @@ -12,6 +14,7 @@ ".spectrum-Table-body .spectrum-Table-row:first-child .spectrum-Table-cell", ".spectrum-Table-body .spectrum-Table-row:last-child .spectrum-Table-cell", ".spectrum-Table-body.is-drop-target", + ".spectrum-Table-body.is-drop-target .spectrum-Table-headRow", ".spectrum-Table-body.is-drop-target .spectrum-Table-row", ".spectrum-Table-body.is-drop-target .spectrum-Table-row .spectrum-Table-checkbox .spectrum-Checkbox-box:before", ".spectrum-Table-body.is-drop-target:after", @@ -24,6 +27,7 @@ ".spectrum-Table-cell.is-focused:after", ".spectrum-Table-cell:focus-visible", ".spectrum-Table-cell:focus-visible:after", + ".spectrum-Table-chartContent .spectrum-Table-chartImage", ".spectrum-Table-checkboxCell", ".spectrum-Table-checkboxCell .spectrum-Table-checkbox", ".spectrum-Table-collapseInner", @@ -40,6 +44,18 @@ ".spectrum-Table-head", ".spectrum-Table-head [role=\"row\"]", ".spectrum-Table-headCell", + ".spectrum-Table-headCell .spectrum-Table-menuButton", + ".spectrum-Table-headCell .spectrum-Table-menuButton:active", + ".spectrum-Table-headCell .spectrum-Table-menuButton:focus", + ".spectrum-Table-headCell .spectrum-Table-menuButton:focus-visible", + ".spectrum-Table-headCell .spectrum-Table-menuButton:focus:hover", + ".spectrum-Table-headCell .spectrum-Table-menuButton:hover", + ".spectrum-Table-headCell .spectrum-Table-sortButton", + ".spectrum-Table-headCell .spectrum-Table-sortButton.is-keyboardFocused", + ".spectrum-Table-headCell .spectrum-Table-sortButton:active", + ".spectrum-Table-headCell .spectrum-Table-sortButton:focus", + ".spectrum-Table-headCell .spectrum-Table-sortButton:focus-visible", + ".spectrum-Table-headCell .spectrum-Table-sortButton:hover", ".spectrum-Table-headCell.is-focused", ".spectrum-Table-headCell.is-focused:after", ".spectrum-Table-headCell.is-sortable", @@ -49,19 +65,18 @@ ".spectrum-Table-headCell.is-sortable:active", ".spectrum-Table-headCell.is-sortable:focus", ".spectrum-Table-headCell.is-sortable:focus-visible", - ".spectrum-Table-headCell.is-sortable:focus:hover", ".spectrum-Table-headCell.is-sortable:hover", ".spectrum-Table-headCell.spectrum-Table-hasMenuButton", ".spectrum-Table-headCell.spectrum-Table-hasMenuButton .spectrum-Table-sortButton", ".spectrum-Table-headCell.spectrum-Table-hasMenuButton .spectrum-Table-sortButton .spectrum-Button-label", ".spectrum-Table-headCell.spectrum-Table-hasMenuButton .spectrum-Table-sortButton .spectrum-Button-label:after", ".spectrum-Table-headCell.spectrum-Table-hasMenuButton .spectrum-Table-sortButton .spectrum-Icon", - ".spectrum-Table-headCell.spectrum-Table-hasMenuButton .spectrum-Table-sortButton:after", + ".spectrum-Table-headCell.spectrum-Table-hasMenuButton .spectrum-Table-sortButton.is-focused:after", + ".spectrum-Table-headCell.spectrum-Table-hasMenuButton .spectrum-Table-sortButton:focus-visible:after", ".spectrum-Table-headCell.spectrum-Table-hasMenuButton.is-keyboardFocused", ".spectrum-Table-headCell.spectrum-Table-hasMenuButton:active", ".spectrum-Table-headCell.spectrum-Table-hasMenuButton:focus", ".spectrum-Table-headCell.spectrum-Table-hasMenuButton:focus-visible", - ".spectrum-Table-headCell.spectrum-Table-hasMenuButton:focus:hover", ".spectrum-Table-headCell.spectrum-Table-hasMenuButton:hover", ".spectrum-Table-headCell:focus-visible", ".spectrum-Table-headCell:focus-visible:after", @@ -69,8 +84,23 @@ ".spectrum-Table-headRow .spectrum-Table-checkboxCell", ".spectrum-Table-headRow .spectrum-Table-checkboxCell .spectrum-Table-checkbox", ".spectrum-Table-headRow .spectrum-Table-headCell", + ".spectrum-Table-headRow .spectrum-Table-headCell--alignEnd", ".spectrum-Table-headRow .spectrum-Table-headCell.is-sortable", + ".spectrum-Table-headRow.is-drop-target", + ".spectrum-Table-headRow.is-focused", + ".spectrum-Table-headRow.is-focused:hover", + ".spectrum-Table-headRow.is-selected", + ".spectrum-Table-headRow.is-selected.is-focused", + ".spectrum-Table-headRow.is-selected:active", + ".spectrum-Table-headRow.is-selected:focus-visible", + ".spectrum-Table-headRow.is-selected:hover", + ".spectrum-Table-headRow:active", ".spectrum-Table-headRow:first-child .spectrum-Table-headCell:first-child", + ".spectrum-Table-headRow:focus", + ".spectrum-Table-headRow:focus-visible", + ".spectrum-Table-headRow:focus-visible:hover", + ".spectrum-Table-headRow:focus:hover", + ".spectrum-Table-headRow:hover", ".spectrum-Table-headRow:last-child .spectrum-Table-headCell:last-child", ".spectrum-Table-main", ".spectrum-Table-row", @@ -93,42 +123,37 @@ ".spectrum-Table-row--sectionHeader:hover", ".spectrum-Table-row--summary", ".spectrum-Table-row--summary .spectrum-Table-cell", + ".spectrum-Table-row--summary:hover", ".spectrum-Table-row.is-drop-target", ".spectrum-Table-row.is-drop-target .spectrum-Table-cell", ".spectrum-Table-row.is-drop-target .spectrum-Table-checkbox .spectrum-Checkbox-box:before", ".spectrum-Table-row.is-focused", - ".spectrum-Table-row.is-focused .spectrum-Table-cell", ".spectrum-Table-row.is-focused .spectrum-Table-cell:first-child", ".spectrum-Table-row.is-focused .spectrum-Table-cell:first-child:before", - ".spectrum-Table-row.is-focused .spectrum-Table-cell:last-child", ".spectrum-Table-row.is-focused .spectrum-Table-checkbox .spectrum-Checkbox-box:before", - ".spectrum-Table-row.is-focused:first-child .spectrum-Table-cell", - ".spectrum-Table-row.is-focused:last-child .spectrum-Table-cell", + ".spectrum-Table-row.is-focused:hover", ".spectrum-Table-row.is-focused:last-child .spectrum-Table-cell:first-child:before", ".spectrum-Table-row.is-selected", + ".spectrum-Table-row.is-selected .spectrum-Table-cell", ".spectrum-Table-row.is-selected .spectrum-Table-checkbox .spectrum-Checkbox-box:before", ".spectrum-Table-row.is-selected.is-focused", + ".spectrum-Table-row.is-selected:active", ".spectrum-Table-row.is-selected:focus-visible", ".spectrum-Table-row.is-selected:hover", + ".spectrum-Table-row.is-selected:not(:has(+ .is-selected)) .spectrum-Table-cell", ".spectrum-Table-row:active", ".spectrum-Table-row:first-child", ".spectrum-Table-row:first-child .spectrum-Table-cell:last-child", ".spectrum-Table-row:focus", - ".spectrum-Table-row:focus .spectrum-Table-cell", ".spectrum-Table-row:focus .spectrum-Table-cell:first-child", ".spectrum-Table-row:focus .spectrum-Table-cell:first-child:before", - ".spectrum-Table-row:focus .spectrum-Table-cell:last-child", ".spectrum-Table-row:focus-visible", - ".spectrum-Table-row:focus-visible .spectrum-Table-cell", ".spectrum-Table-row:focus-visible .spectrum-Table-cell:first-child", ".spectrum-Table-row:focus-visible .spectrum-Table-cell:first-child:before", - ".spectrum-Table-row:focus-visible .spectrum-Table-cell:last-child", ".spectrum-Table-row:focus-visible .spectrum-Table-checkbox .spectrum-Checkbox-box:before", - ".spectrum-Table-row:focus-visible:first-child .spectrum-Table-cell", - ".spectrum-Table-row:focus-visible:last-child .spectrum-Table-cell", + ".spectrum-Table-row:focus-visible:hover", ".spectrum-Table-row:focus-visible:last-child .spectrum-Table-cell:first-child:before", - ".spectrum-Table-row:focus:first-child .spectrum-Table-cell", - ".spectrum-Table-row:focus:last-child .spectrum-Table-cell", + ".spectrum-Table-row:focus:hover", ".spectrum-Table-row:focus:last-child .spectrum-Table-cell:first-child:before", ".spectrum-Table-row:hover", ".spectrum-Table-row:hover .spectrum-Table-cell:first-child:before", @@ -143,12 +168,14 @@ ".spectrum-Table-scroller .spectrum-Table-body .spectrum-Table-row:last-child .spectrum-Table-cell", ".spectrum-Table-scroller .spectrum-Table-head", ".spectrum-Table-scroller .spectrum-Table-headRow:first-child .spectrum-Table-headCell", - ".spectrum-Table-scroller.spectrum-Table--quiet", ".spectrum-Table-visualInner", ".spectrum-Table-visualInner .spectrum-Avatar", ".spectrum-Table-visualInner .spectrum-Icon", ".spectrum-Table-visualInner .spectrum-Thumbnail", ".spectrum-Table:dir(rtl)", + ".spectrum-Table:lang(ja)", + ".spectrum-Table:lang(ko)", + ".spectrum-Table:lang(zh)", ".spectrum-Table:not(.spectrum-Table-scroller)", "[dir=\"rtl\"] .spectrum-Table" ], @@ -177,11 +204,14 @@ "--mod-table-focus-indicator-color", "--mod-table-focus-indicator-thickness", "--mod-table-header-background-color", - "--mod-table-header-background-color-quiet", - "--mod-table-header-background-color-scrollable", "--mod-table-header-font-family", "--mod-table-header-font-size", + "--mod-table-header-font-style", "--mod-table-header-font-weight", + "--mod-table-header-icons-color-active", + "--mod-table-header-icons-color-default", + "--mod-table-header-icons-color-hover", + "--mod-table-header-icons-color-key-focus", "--mod-table-header-line-height", "--mod-table-header-row-bottom-to-text", "--mod-table-header-row-checkbox-block-spacing", @@ -201,18 +231,21 @@ "--mod-table-min-row-height-spacious", "--mod-table-outer-border-inline-width", "--mod-table-outer-border-inline-width-quiet", - "--mod-table-row-active-color", "--mod-table-row-background-color", + "--mod-table-row-background-color-active-color", "--mod-table-row-background-color-hover", - "--mod-table-row-background-color-quiet", "--mod-table-row-bottom-to-text", "--mod-table-row-checkbox-block-spacing", "--mod-table-row-checkbox-block-spacing-compact", "--mod-table-row-checkbox-block-spacing-spacious", + "--mod-table-row-font-family", "--mod-table-row-font-size", + "--mod-table-row-font-style", "--mod-table-row-font-weight", "--mod-table-row-line-height", "--mod-table-row-text-color", + "--mod-table-row-text-color-active", + "--mod-table-row-text-color-hover", "--mod-table-row-top-to-text", "--mod-table-section-header-background-color", "--mod-table-section-header-block-end-spacing", @@ -271,6 +304,10 @@ "--spectrum-table-focused-cell-border-radius", "--spectrum-table-header-background-color", "--spectrum-table-header-font-weight", + "--spectrum-table-header-icons-color-active", + "--spectrum-table-header-icons-color-default", + "--spectrum-table-header-icons-color-hover", + "--spectrum-table-header-icons-color-key-focus", "--spectrum-table-header-row-bottom-to-text", "--spectrum-table-header-row-checkbox-block-spacing", "--spectrum-table-header-row-checkbox-to-top-medium", @@ -279,15 +316,13 @@ "--spectrum-table-icon-color", "--spectrum-table-icon-color-active", "--spectrum-table-icon-color-default", - "--spectrum-table-icon-color-focus", - "--spectrum-table-icon-color-focus-hover", "--spectrum-table-icon-color-hover", "--spectrum-table-icon-color-key-focus", "--spectrum-table-min-header-row-height", "--spectrum-table-min-row-height", "--spectrum-table-outer-border-inline-width", - "--spectrum-table-row-active-color", "--spectrum-table-row-background-color", + "--spectrum-table-row-background-color-active", "--spectrum-table-row-background-color-hover", "--spectrum-table-row-bottom-to-text", "--spectrum-table-row-bottom-to-text-medium", @@ -309,6 +344,9 @@ "--spectrum-table-row-hover-opacity", "--spectrum-table-row-line-height", "--spectrum-table-row-text-color", + "--spectrum-table-row-text-color-active", + "--spectrum-table-row-text-color-hover", + "--spectrum-table-row-text-color-key-focus", "--spectrum-table-row-tier", "--spectrum-table-row-top-to-text", "--spectrum-table-row-top-to-text-medium", @@ -323,9 +361,11 @@ "--spectrum-table-selected-cell-background-color", "--spectrum-table-selected-cell-background-color-focus", "--spectrum-table-selected-row-background-color", - "--spectrum-table-selected-row-background-color-focus", + "--spectrum-table-selected-row-background-color-active", + "--spectrum-table-selected-row-background-color-hover", "--spectrum-table-selected-row-background-color-non-emphasized", "--spectrum-table-selected-row-background-color-non-emphasized-focus", + "--spectrum-table-selected-row-background-color-rgb", "--spectrum-table-selected-row-background-opacity", "--spectrum-table-selected-row-background-opacity-hover", "--spectrum-table-selected-row-background-opacity-non-emphasized", @@ -342,11 +382,10 @@ "--spectrum-avatar-size-100", "--spectrum-avatar-size-50", "--spectrum-avatar-size-75", - "--spectrum-background-layer-1-color", - "--spectrum-blue-900-rgb", "--spectrum-body-color", "--spectrum-bold-font-weight", "--spectrum-checkbox-control-size-small", + "--spectrum-cjk-line-height-100", "--spectrum-component-bottom-to-text-100", "--spectrum-component-height-100", "--spectrum-component-top-to-text-100", @@ -358,7 +397,6 @@ "--spectrum-focus-indicator-color", "--spectrum-focus-indicator-thickness", "--spectrum-font-size-100", - "--spectrum-gray-100", "--spectrum-gray-200", "--spectrum-gray-25", "--spectrum-gray-300", @@ -368,6 +406,9 @@ "--spectrum-line-height-100", "--spectrum-logical-rotation", "--spectrum-neutral-content-color-default", + "--spectrum-neutral-content-color-down", + "--spectrum-neutral-content-color-hover", + "--spectrum-neutral-content-color-key-focus", "--spectrum-neutral-subdued-content-color-default", "--spectrum-neutral-subdued-content-color-down", "--spectrum-neutral-subdued-content-color-hover", @@ -379,9 +420,7 @@ "--spectrum-text-to-visual-300", "--spectrum-thumbnail-size-100", "--spectrum-thumbnail-size-200", - "--spectrum-thumbnail-size-75", - "--spectrum-transparent-white-100", - "--spectrum-transparent-white-25" + "--spectrum-thumbnail-size-75" ], "passthroughs": [ "--mod-avatar-block-size", @@ -390,7 +429,6 @@ "--mod-button-background-color-down", "--mod-button-background-color-focus", "--mod-button-background-color-hover", - "--mod-button-border-radius", "--mod-button-content-color-default", "--mod-button-content-color-down", "--mod-button-content-color-focus", @@ -404,6 +442,7 @@ "--mod-button-line-height", "--mod-button-padding-label-to-icon", "--mod-checkbox-margin-block", + "--mod-icon-color", "--mod-thumbnail-size" ], "high-contrast": [ @@ -416,6 +455,7 @@ "--highcontrast-table-row-background-color", "--highcontrast-table-row-background-color-hover", "--highcontrast-table-row-text-color", + "--highcontrast-table-row-text-color-focus", "--highcontrast-table-row-text-color-hover", "--highcontrast-table-section-header-background-color", "--highcontrast-table-section-header-text-color", From c8e41baef09d0b22be559a72477e2e2d070d32be Mon Sep 17 00:00:00 2001 From: Marissa Huysentruyt Date: Fri, 6 Jun 2025 10:22:24 -0400 Subject: [PATCH 09/17] fix(table): add missing mod from documentation --- components/table/index.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/table/index.css b/components/table/index.css index f09cc3f2815..5cd40dc5cd5 100644 --- a/components/table/index.css +++ b/components/table/index.css @@ -193,6 +193,10 @@ --spectrum-table-outer-border-inline-width: var(--mod-table-outer-border-inline-width-quiet, 0px); } +.spectrum-Table-scroller { + --spectrum-table-header-background-color: var(--mod-table-header-background-color-scrollable, var(--spectrum-gray-75)); +} + .spectrum-Table-row, .spectrum-Table-headRow { &.is-focused, From 9b71b7c6eec8dfe4dbe8c3461e766b88ab913a9b Mon Sep 17 00:00:00 2001 From: Marissa Huysentruyt Date: Fri, 6 Jun 2025 10:22:54 -0400 Subject: [PATCH 10/17] docs(table): correct wording in stories --- components/table/stories/table.stories.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/table/stories/table.stories.js b/components/table/stories/table.stories.js index 15994ffbf7d..bfdf26bbba9 100644 --- a/components/table/stories/table.stories.js +++ b/components/table/stories/table.stories.js @@ -428,7 +428,7 @@ TableStates.parameters = { }; /** - * Quiet tables are for when a table is meant to be supplementary, subtle, or lightweight. The quiet table utilizes the `.spectrum-Table--quiet` class and has a transparent background and no borders on the left and right. + * Quiet tables are for when a table is meant to be supplementary, subtle, or lightweight. The quiet table utilizes the `.spectrum-Table--quiet` class and does not have borders on the left and right. */ export const Quiet = Template.bind({}); Quiet.args = { @@ -542,7 +542,7 @@ WithColumnDividers.parameters = { }; /** - * Tables can have a summary row to show totals, at either the top or the bottom of the table. This example shows both the optional summary row at the bottom, and a row marked as selected. + * Tables can have a summary row to show totals, at either the top or the bottom of the table. This example shows both the optional summary row at the top, and a row marked as selected. */ export const SummaryAndSelected = Template.bind({}); SummaryAndSelected.args = { From 9ff5ef56a848e2a4e662d0a374207ccfe90a32f2 Mon Sep 17 00:00:00 2001 From: Marissa Huysentruyt Date: Fri, 6 Jun 2025 14:25:03 -0400 Subject: [PATCH 11/17] fix(table): correct weird mod naming --- components/table/index.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/table/index.css b/components/table/index.css index 5cd40dc5cd5..fd3e04e7fd3 100644 --- a/components/table/index.css +++ b/components/table/index.css @@ -220,7 +220,7 @@ &:active { --highcontrast-table-row-text-color: var(--highcontrast-table-row-text-color-hover); --highcontrast-table-icon-color: var(--highcontrast-table-row-text-color-hover); - --spectrum-table-cell-background-color: var(--highcontrast-table-row-background-color-hover, var(--mod-table-row-background-color-active-color, var(--spectrum-table-row-background-color-active))); + --spectrum-table-cell-background-color: var(--highcontrast-table-row-background-color-hover, var(--mod-table-row-background-color-active, var(--spectrum-table-row-background-color-active))); --spectrum-table-row-text-color: var(--highcontrast-table-row-text-color-hover, var(--mod-table-row-text-color-active, var(--spectrum-table-row-text-color-active))); } From 7bbd5cb54fd03f8ef5fb76e9595ceaa9af3bf4c8 Mon Sep 17 00:00:00 2001 From: Marissa Huysentruyt Date: Fri, 6 Jun 2025 10:37:16 -0400 Subject: [PATCH 12/17] chore(table): update metadata --- components/table/dist/metadata.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/table/dist/metadata.json b/components/table/dist/metadata.json index 30f8f827b50..96ab647398c 100644 --- a/components/table/dist/metadata.json +++ b/components/table/dist/metadata.json @@ -204,6 +204,7 @@ "--mod-table-focus-indicator-color", "--mod-table-focus-indicator-thickness", "--mod-table-header-background-color", + "--mod-table-header-background-color-scrollable", "--mod-table-header-font-family", "--mod-table-header-font-size", "--mod-table-header-font-style", @@ -232,7 +233,7 @@ "--mod-table-outer-border-inline-width", "--mod-table-outer-border-inline-width-quiet", "--mod-table-row-background-color", - "--mod-table-row-background-color-active-color", + "--mod-table-row-background-color-active", "--mod-table-row-background-color-hover", "--mod-table-row-bottom-to-text", "--mod-table-row-checkbox-block-spacing", From c9229c8a6dc5449e63cacd68547154545273fb43 Mon Sep 17 00:00:00 2001 From: Marissa Huysentruyt Date: Fri, 6 Jun 2025 14:28:28 -0400 Subject: [PATCH 13/17] chore(table): update changeset --- .changeset/petite-toys-greet.md | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/.changeset/petite-toys-greet.md b/.changeset/petite-toys-greet.md index b085079cfa0..2256b606b05 100644 --- a/.changeset/petite-toys-greet.md +++ b/.changeset/petite-toys-greet.md @@ -14,12 +14,15 @@ Compared to the S1 table, this component has updated corner rounding, updated co - For tables with sortable column, there are three new S2 icons used: `Sort` to indicate "general" sorting, `SortUp` for ascending sort direction, `SortDown` for descending sort direction. - Tables support thumbnail, avatar, and icon components as content within a cell. - Focus indicators for entire rows have been updated for rows to include a side focus indicator. +- New sparkline SVGs available for cell content #### Description of other S2 table work T-shirt sizing for tables is not technically supported, so t-shirt size classes (i.e. `.spectrum-Table--sizeS`), have been removed across all density variants. -The `.spectrum-Table-cell--alignRight` class has been renamed to `.spectrum-Table-cell--alignEnd` to reflect the preference for "logical" positioning. The `.spectrum-Table-cell--alignCenter` class has been refactored to `.spectrum-Table-cell--alignStart`. +The `.spectrum-Table-cell--alignRight` class has been renamed to `.spectrum-Table-cell--alignEnd` to reflect the preference for "logical" positioning. The `.spectrum-Table-cell--alignCenter` class has been refactored to `.spectrum-Table-cell--alignStart`. A new `.spectrum-Table-headCell--alignEnd` class was created to correspond to tables that may have end-aligned numerical data so the head cell follows the text alignment correctly. + +Semantically, if a table should enable column sorting, the content of a column's head cell should actually be a button, since it is triggering an action. If the column header cell could trigger a menu, the content of that cell should also be a button. New markup has been included to improve the semantic design of the content of header cells, utilizing button components to signify an action can be triggered, or a menu can be triggered. In S1, the CSS table component only supported thumbnails. Because the S2 table supports thumbnails, as well as avatars and icons, most of the language regarding thumbnails has also changed. For instance, the `showThumbnail` storybook arg was refactored to `visualElement`. The following CSS classes have been removed or refactored to remove the thumbnail language in favor of "visual" instead: @@ -39,7 +42,7 @@ Individual cell focus rings have rounded corners. The outer table border extends all the way around the `thead`/`div` equivalent. -In Storybook, several new stories have been added to the docs page and the testing grid for Chromatic. These stories include `EmptyState`, `LoadingState`, `SingleSelect`, `NumericalData`, `TableStates`, `Sortable`. Documentation has been added for each of these stories, as well as expanded in other stories. +In Storybook, several new stories have been added to the docs page and the testing grid for Chromatic. These stories include `EmptyState`, `LoadingState`, `SingleSelect`, `NumericalData`, `TableStates`, `Sortable`, `WithMenuButton`, `WithChartContent`. Documentation has been added for each of these stories, as well as expanded in other stories. #### Mods @@ -62,6 +65,7 @@ In Storybook, several new stories have been added to the docs page and the testi | `--mod-table-row-checkbox-block-spacing--compact` | `--mod-table-row-checkbox-block-spacing-compact` | | `--mod-table-row-checkbox-block-spacing--spacious` | `--mod-table-row-checkbox-block-spacing-spacious` | | `--mod-table-thumbnail-to-text` | `--mod-table-visual-to-text` | +| `--mod-table-row-active-color` | `--mod-table-row-background-color-active` | ##### New Modifiers @@ -72,6 +76,15 @@ In Storybook, several new stories have been added to the docs page and the testi - `--mod-table-summary-row-bottom-to-text` - `--mod-table-summary-row-min-height` - `--mod-table-summary-row-top-to-text` +- `--mod-table-header-font-style` +- `--mod-table-header-icons-color-active` +- `--mod-table-header-icons-color-default` +- `--mod-table-header-icons-color-hover` +- `--mod-table-header-icons-color-key-focus` +- `--mod-table-row-font-family` +- `--mod-table-row-font-style` +- `--mod-table-row-text-color-active` +- `--mod-table-row-text-color-hover` ##### Removed Modifiers @@ -82,6 +95,8 @@ In Storybook, several new stories have been added to the docs page and the testi - `--mod-table-row-bottom-to-text--spacious` - `--mod-table-row-top-to-text--compact` - `--mod-table-row-top-to-text--spacious` -- `--mod-table-thumbnail-block-spacing"` +- `--mod-table-thumbnail-block-spacing` - `--mod-table-thumbnail-block-spacing-compact` - `--mod-table-thumbnail-block-spacing-spacious` +- `--mod-table-header-background-color-quiet` +- `--mod-table-row-background-color-quiet` From 973bf6ddabe7a86fe3c93103fe22d6f2414ca6c9 Mon Sep 17 00:00:00 2001 From: Marissa Huysentruyt Date: Tue, 10 Jun 2025 18:00:15 -0400 Subject: [PATCH 14/17] chore(table): secondary button variants --- components/table/stories/template.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/table/stories/template.js b/components/table/stories/template.js index 283d2cce67a..967e133b5ae 100644 --- a/components/table/stories/template.js +++ b/components/table/stories/template.js @@ -330,6 +330,7 @@ export const Template = ({ ${when(hasMenu || isSortable, () => html` ${when(isSortable, () => Button({ size: "m", + variant: "secondary", iconName: sortIcon, iconSet: "workflow", label: "Column title", @@ -338,6 +339,7 @@ export const Template = ({ )} ${when(!isSortable, () => Button({ size: "m", + variant: "secondary", iconName: "SortUp", iconSet: "workflow", label: "Column title", From 70dcf8c56bb36e45b9602cdb58342aea8d14b5c7 Mon Sep 17 00:00:00 2001 From: Marissa Huysentruyt Date: Tue, 10 Jun 2025 18:01:15 -0400 Subject: [PATCH 15/17] fix(table): button styles in whcm - fixes background colors, text colors, icon colors, interactive states, and border radius in high contrast mode - removes duplicate quiet styles - adds forced-color-adjust: none to avoid flash of orange button text color in WHCM --- components/table/index.css | 45 +++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/components/table/index.css b/components/table/index.css index fd3e04e7fd3..81dd9f9390c 100644 --- a/components/table/index.css +++ b/components/table/index.css @@ -139,7 +139,7 @@ --mod-button-content-color-down: var(--spectrum-table-header-text-color); --mod-button-edge-to-text: var(--spectrum-table-cell-inline-spacing); --mod-button-padding-label-to-icon: var(--spectrum-table-visual-to-text); - --mod-button-height: var(--spectrum-table-min-header-row-height); + --mod-button-border-radius: calc(var(--mod-table-border-radius, var(--spectrum-table-focused-cell-border-radius)) - var(--mod-table-border-width, var(--spectrum-table-border-width))); --mod-button-focus-ring-border-radius: calc(var(--mod-table-border-radius, var(--spectrum-table-focused-cell-border-radius)) - var(--mod-table-border-width, var(--spectrum-table-border-width))); &:dir(rtl) { @@ -256,7 +256,7 @@ &.is-sortable, &.spectrum-Table-hasMenuButton, .spectrum-Table-sortButton { - --spectrum-table-icon-color: var(--mod-table-header-icons-color-default, var(--spectrum-table-header-icons-color-default)); + --spectrum-table-icon-color: var(--highcontrast-table-icon-color, var(--mod-table-header-icons-color-default, var(--spectrum-table-header-icons-color-default))); &:hover { --spectrum-table-icon-color: var(--highcontrast-table-icon-color-focus, var(--mod-table-header-icons-color-hover, var(--spectrum-table-header-icons-color-hover))); @@ -401,17 +401,6 @@ } } -/* Quiet table header rows do not have inline borders */ -.spectrum-Table--quiet .spectrum-Table-headRow:first-child { - .spectrum-Table-headCell:first-child { - border-inline-start: 0; - } - - .spectrum-Table-headCell:last-child { - border-inline-end: 0; - } -} - /********* ICONS- SORT, DISCLOSURE/MENU *********/ /* Head cell column text */ .spectrum-Table-columnTitle { @@ -423,6 +412,21 @@ .spectrum-Table-headCell.is-sortable { padding: 0; + /* Ensure the button text color is the same as the header text color, particularly in high contrast mode. */ + .spectrum-Table-sortButton { + color: var(--highcontrast-table-header-text-color, var(--mod-table-header-text-color, var(--spectrum-table-header-text-color))); + + /* Avoids flash of a different text color from the button in WHCM. */ + forced-color-adjust: none; + + &:hover, + &:focus, + &:focus-visible, + &:active { + color: var(--highcontrast-table-header-text-color-hover, var(--mod-table-header-text-color, var(--spectrum-table-header-text-color))); + } + } + /* Focus indicator- brings the focus indicator above the border and matches the table cell dimensions. */ .spectrum-Table-sortButton::after { inset: calc(3 * var(--mod-table-border-width, var(--spectrum-table-border-width))); @@ -438,9 +442,16 @@ /* Head cell column text in the button that opens the menu */ .spectrum-Table-headCell.spectrum-Table-hasMenuButton { .spectrum-Table-sortButton { - min-block-size: calc(var(--spectrum-table-min-header-row-height) + var(--mod-table-border-width, var(--spectrum-table-border-width))); min-inline-size: 100%; justify-content: flex-start; + color: var(--highcontrast-table-header-text-color, var(--mod-table-header-text-color, var(--spectrum-table-header-text-color))); + + /* Avoids flash of a different text color from the button in WHCM. */ + forced-color-adjust: none; + + &:hover { + color: var(--highcontrast-table-header-text-color-hover, var(--mod-table-header-text-color, var(--spectrum-table-header-text-color))); + } /* Focus indicator- brings the focus indicator above the cell borders and matches the table cell dimensions. */ &:focus-visible::after, @@ -931,7 +942,7 @@ &:focus-visible, &.is-keyboardFocused { - --spectrum-table-icon-color: var(--highcontrast-table-icon-color, var(--mod-table-icon-color-key-focus, var(--spectrum-table-icon-color-key-focus))); + --spectrum-table-icon-color: var(--highcontrast-table-icon-color-focus, var(--mod-table-icon-color-key-focus, var(--spectrum-table-icon-color-key-focus))); outline-width: var(--mod-table-focus-indicator-thickness, var(--spectrum-table-focus-indicator-thickness)); outline-style: solid; @@ -981,6 +992,10 @@ --highcontrast-table-selected-row-background-color: Highlight; --highcontrast-table-selected-row-text-color: HighlightText; + /* Button text colors */ + --highcontrast-table-header-text-color: CanvasText; + --highcontrast-table-header-text-color-hover: Highlight; + @supports (color: SelectedItem) { --highcontrast-table-selected-row-background-color: SelectedItem; --highcontrast-table-selected-row-text-color: SelectedItemText; From 6f1f7b22b88e406c0ff2d0052dde0ef3e70faf62 Mon Sep 17 00:00:00 2001 From: Marissa Huysentruyt Date: Tue, 10 Jun 2025 18:24:16 -0400 Subject: [PATCH 16/17] fix(table): update borders in whcm --- components/table/index.css | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/components/table/index.css b/components/table/index.css index 81dd9f9390c..c7a68eb6ffd 100644 --- a/components/table/index.css +++ b/components/table/index.css @@ -1018,6 +1018,9 @@ /* Removes unstylable readability backplate. */ forced-color-adjust: none; + /* Make sure border colors are visible in high contrast mode */ + border: var(--spectrum-table-border-width) solid Highlight; + &:focus-visible, &.is-focused { &::after { @@ -1038,11 +1041,6 @@ .spectrum-Table-cell:first-child::before { background-color: Highlight; } - - /* Make sure border colors are visible in high contrast mode */ - /* .spectrum-Table-cell { - border-color: Highlight; - } */ } } From 759487733d57ef655cf535dd4e257c2cca0e8910 Mon Sep 17 00:00:00 2001 From: Marissa Huysentruyt Date: Tue, 10 Jun 2025 18:51:39 -0400 Subject: [PATCH 17/17] fix(table): pr edits - adds table mods to button passthroughs for fallbacks - removes transition on header cells - removes unnecessary commas in some property definitions --- components/table/index.css | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/components/table/index.css b/components/table/index.css index c7a68eb6ffd..97362224f32 100644 --- a/components/table/index.css +++ b/components/table/index.css @@ -133,10 +133,10 @@ --mod-button-background-color-hover: transparent; --mod-button-background-color-focus: transparent; --mod-button-background-color-down: transparent; - --mod-button-content-color-default: var(--spectrum-table-header-text-color); - --mod-button-content-color-hover: var(--spectrum-table-header-text-color); - --mod-button-content-color-focus: var(--spectrum-table-header-text-color); - --mod-button-content-color-down: var(--spectrum-table-header-text-color); + --mod-button-content-color-default: var(--mod-table-header-text-color, var(--spectrum-table-header-text-color)); + --mod-button-content-color-hover: var(--mod-table-header-text-color, var(--spectrum-table-header-text-color)); + --mod-button-content-color-focus: var(--mod-table-header-text-color, var(--spectrum-table-header-text-color)); + --mod-button-content-color-down: var(--mod-table-header-text-color, var(--spectrum-table-header-text-color)); --mod-button-edge-to-text: var(--spectrum-table-cell-inline-spacing); --mod-button-padding-label-to-icon: var(--spectrum-table-visual-to-text); --mod-button-border-radius: calc(var(--mod-table-border-radius, var(--spectrum-table-focused-cell-border-radius)) - var(--mod-table-border-width, var(--spectrum-table-border-width))); @@ -197,8 +197,7 @@ --spectrum-table-header-background-color: var(--mod-table-header-background-color-scrollable, var(--spectrum-gray-75)); } -.spectrum-Table-row, -.spectrum-Table-headRow { +.spectrum-Table-row { &.is-focused, &:focus-visible, &:focus { @@ -349,7 +348,6 @@ background-color: var(--mod-table-header-background-color, var(--spectrum-table-header-background-color)); border-block-start: var(--mod-table-border-width, var(--spectrum-table-border-width)) solid var(--highcontrast-table-border-color, var(--mod-table-border-color, var(--spectrum-table-border-color))); - transition: color var(--highcontrast-table-transition-duration, var(--mod-table-transition-duration, var(--spectrum-table-transition-duration))) ease-in-out; cursor: var(--mod-table-cursor-header-default, initial); outline: 0; @@ -914,10 +912,10 @@ border: 0; color: var(--spectrum-table-icon-color); - transform: var(--spectrum-logical-rotation,); + transform: var(--spectrum-logical-rotation); &[aria-expanded="true"] { - transform: var(--spectrum-logical-rotation,) rotate(90deg); + transform: var(--spectrum-logical-rotation) rotate(90deg); } &::after {