From 421dbc4820cc2aa4b50fe8cc1f687c9fac4e4cd9 Mon Sep 17 00:00:00 2001 From: TJ Egan Date: Thu, 8 Feb 2024 12:37:23 -0500 Subject: [PATCH] feat(DataTable): Update DataTable to phase 2 spec (#15662) * feat(DataTable): start work on updating DataTable to phase 2 spec * style(Table): refactor styles * style(Table): add in selected styles * style(Table): fix edge cases, add dark theme * feat(Table): add in column gradient styles and support * fix(DataTable): conditionally render td className * refactor(DataTable): rework how slug is handled in TableHeader * style(DataTable): adjust column gradient styles * fix(DataTable): fix old class reference * fix(DataTable): adjust sort + slug styles, fix issue with callout mixin * style(DataTable): adjust gradient, move column slug * test(Slug): add more VRT --- e2e/components/Slug/Slug-test.e2e.js | 32 +++++ .../__snapshots__/PublicAPI-test.js.snap | 1 + .../__snapshots__/PublicAPI-test.js.snap | 10 -- .../src/components/DataTable/DataTable.tsx | 21 +++ .../src/components/DataTable/TableCell.tsx | 59 ++++++++- .../components/DataTable/TableExpandRow.tsx | 2 +- .../src/components/DataTable/TableHeader.tsx | 2 +- .../src/components/DataTable/TableRow.tsx | 13 ++ .../stories/DataTable-slug.stories.js | 122 ++++++++++++------ .../__snapshots__/normalize-test.js.snap | 9 ++ .../components/DataTable/tools/normalize.js | 3 +- .../react/src/components/Slug/Slug.stories.js | 4 +- .../react/src/components/Slug/slug-story.scss | 1 - packages/styles/scss/__tests__/theme-test.js | 1 + .../components/data-table/_data-table.scss | 110 +++++++++++++++- .../expandable/_data-table-expandable.scss | 8 +- .../data-table/sort/_data-table-sort.scss | 9 +- .../styles/scss/utilities/_ai-gradient.scss | 31 ++++- packages/themes/src/g10.js | 1 + packages/themes/src/g100.js | 1 + packages/themes/src/g90.js | 1 + .../__tests__/__snapshots__/v11-test.js.snap | 1 + .../src/tokens/__tests__/metadata-test.js | 4 + packages/themes/src/tokens/v11TokenGroup.js | 1 + packages/themes/src/white.js | 1 + 25 files changed, 370 insertions(+), 78 deletions(-) diff --git a/e2e/components/Slug/Slug-test.e2e.js b/e2e/components/Slug/Slug-test.e2e.js index fcafd00203c8..31ada475cb88 100644 --- a/e2e/components/Slug/Slug-test.e2e.js +++ b/e2e/components/Slug/Slug-test.e2e.js @@ -22,6 +22,14 @@ test.describe('Slug', () => { }); }); + test('slug callout @vrt', async ({ page }) => { + await snapshotStory(page, { + component: 'Slug', + id: 'experimental-unstable-slug--callout', + theme, + }); + }); + test('slug inside form @vrt', async ({ page }) => { await snapshotStory(page, { component: 'Slug', @@ -29,6 +37,30 @@ test.describe('Slug', () => { theme, }); }); + + test('slug inside DataTable column @vrt', async ({ page }) => { + await snapshotStory(page, { + component: 'Slug', + id: 'experimental-unstable-slug-datatable--column-slug-sort', + theme, + }); + }); + + test('slug inside DataTable row @vrt', async ({ page }) => { + await snapshotStory(page, { + component: 'Slug', + id: 'experimental-unstable-slug-datatable--slug-with-selection-and-expansion', + theme, + }); + }); + + test('slug inside Tile @vrt', async ({ page }) => { + await snapshotStory(page, { + component: 'Slug', + id: 'experimental-unstable-slug-examples--tile', + theme, + }); + }); }); }); }); diff --git a/packages/elements/src/__tests__/__snapshots__/PublicAPI-test.js.snap b/packages/elements/src/__tests__/__snapshots__/PublicAPI-test.js.snap index 8fff0c0b228f..de34dd015ec2 100644 --- a/packages/elements/src/__tests__/__snapshots__/PublicAPI-test.js.snap +++ b/packages/elements/src/__tests__/__snapshots__/PublicAPI-test.js.snap @@ -7,6 +7,7 @@ Array [ "aiAuraHoverEnd", "aiAuraHoverStart", "aiAuraStart", + "aiAuraStartTable", "aiBorderEnd", "aiBorderStart", "aiBorderStrong", diff --git a/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap b/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap index d589f1f2fde7..f8a2a04f1178 100644 --- a/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap +++ b/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap @@ -1938,11 +1938,6 @@ Map { }, "TableCell": Object { "displayName": "TableCell", - "propTypes": Object { - "className": Object { - "type": "string", - }, - }, }, "TableContainer": Object { "propTypes": Object { @@ -7725,11 +7720,6 @@ Map { }, "TableCell" => Object { "displayName": "TableCell", - "propTypes": Object { - "className": Object { - "type": "string", - }, - }, }, "TableContainer" => Object { "propTypes": Object { diff --git a/packages/react/src/components/DataTable/DataTable.tsx b/packages/react/src/components/DataTable/DataTable.tsx index cc8962e4cb32..2622ff5b801f 100644 --- a/packages/react/src/components/DataTable/DataTable.tsx +++ b/packages/react/src/components/DataTable/DataTable.tsx @@ -91,6 +91,7 @@ export interface DataTableRow { export interface DataTableHeader { key: string; header: React.ReactNode; + slug: React.ReactElement; } export interface DataTableRenderProps { @@ -189,6 +190,10 @@ export interface DataTableRenderProps { stickyHeader?: boolean; useStaticWidth?: boolean; }; + getCellProps: (getCellPropsArgs: { cell: DataTableCell }) => { + [key: string]: unknown; + hasSlugHeader?: boolean; + }; // Custom event handlers onInputChange: ( @@ -456,6 +461,7 @@ class DataTable extends React.Component< sortDirection, isSortable, isSortHeader: sortHeaderKey === header.key, + slug: header.slug, onClick: (event) => { const nextSortState = getNextSortState(this.props, this.state, { key: header.key, @@ -715,6 +721,20 @@ class DataTable extends React.Component< }; }; + /** + * Get the props associated with the given table cell. + * + * @param {object} config + * @param {object} config.cell the cell we want the props for + * @returns {object} + */ + getCellProps = ({ cell, ...rest }) => { + return { + ...rest, + hasSlugHeader: cell.hasSlugHeader, + }; + }; + /** * Helper utility to get all the currently selected rows * @returns {Array} the array of rowIds that are currently selected @@ -966,6 +986,7 @@ class DataTable extends React.Component< getBatchActionProps: this.getBatchActionProps, getTableProps: this.getTableProps, getTableContainerProps: this.getTableContainerProps, + getCellProps: this.getCellProps, // Custom event handlers onInputChange: this.handleOnInputValueChange, diff --git a/packages/react/src/components/DataTable/TableCell.tsx b/packages/react/src/components/DataTable/TableCell.tsx index e314ce2c0013..426e928f542e 100644 --- a/packages/react/src/components/DataTable/TableCell.tsx +++ b/packages/react/src/components/DataTable/TableCell.tsx @@ -5,14 +5,59 @@ * LICENSE file in the root directory of this source tree. */ -import { TdHTMLAttributes } from 'react'; -import wrapComponent from '../../tools/wrapComponent'; +import React from 'react'; +import classNames from 'classnames'; +import { usePrefix } from '../../internal/usePrefix'; +import { ReactAttr } from '../../types/common'; -export type TableCellProps = TdHTMLAttributes; +interface TableCellProps extends ReactAttr { + /** + * Pass in children that will be embedded in the table header label + */ + children?: React.ReactNode; -const TableCell: React.FC = wrapComponent({ - name: 'TableCell', - type: 'td', -}); + /** + * Specify an optional className to be applied to the container node + */ + className?: string; + /** + * The width of the expanded row's internal cell + */ + colSpan?: number; + + /** + * Specify if the table cell is in an AI column + */ + hasSlugHeader?: boolean; + + /** + * The id of the matching th node in the table head. Addresses a11y concerns outlined here: https://www.ibm.com/able/guidelines/ci162/info_and_relationships.html and https://www.w3.org/TR/WCAG20-TECHS/H43 + */ + headers?: string; +} + +const TableCell = ({ + children, + className, + hasSlugHeader, + colSpan, + ...rest +}: TableCellProps) => { + const prefix = usePrefix(); + + const tableCellClassNames = classNames(className, { + [`${prefix}--table-cell--column-slug`]: hasSlugHeader, + }); + return ( + + {children} + + ); +}; + +TableCell.displayName = 'TableCell'; export default TableCell; diff --git a/packages/react/src/components/DataTable/TableExpandRow.tsx b/packages/react/src/components/DataTable/TableExpandRow.tsx index cfc064870a44..949b7231b2da 100644 --- a/packages/react/src/components/DataTable/TableExpandRow.tsx +++ b/packages/react/src/components/DataTable/TableExpandRow.tsx @@ -98,7 +98,7 @@ const TableExpandRow = React.forwardRef( [`${prefix}--parent-row`]: true, [`${prefix}--expandable-row`]: isExpanded, [`${prefix}--data-table--selected`]: isSelected, - [`${prefix}--parent-row--slug`]: rowHasSlug, + [`${prefix}--data-table--slug-row`]: rowHasSlug, }, rowClassName ); diff --git a/packages/react/src/components/DataTable/TableHeader.tsx b/packages/react/src/components/DataTable/TableHeader.tsx index 46a226df283b..3515d7459b88 100644 --- a/packages/react/src/components/DataTable/TableHeader.tsx +++ b/packages/react/src/components/DataTable/TableHeader.tsx @@ -234,12 +234,12 @@ const TableHeader = React.forwardRef(function TableHeader( {...rest}>
{children}
- {normalizedSlug} + {normalizedSlug}
diff --git a/packages/react/src/components/DataTable/TableRow.tsx b/packages/react/src/components/DataTable/TableRow.tsx index c2585c46fcc2..dce1f03ee9ca 100644 --- a/packages/react/src/components/DataTable/TableRow.tsx +++ b/packages/react/src/components/DataTable/TableRow.tsx @@ -25,11 +25,24 @@ export interface TableRowProps extends ReactAttr { const TableRow = (props: TableRowProps) => { const prefix = usePrefix(); + + let rowHasSlug; + if (props?.children) { + React.Children.toArray(props.children).map((child: any) => { + if (child.type?.displayName === 'TableSlugRow') { + if (child.props.slug) { + rowHasSlug = true; + } + } + }); + } // Remove unnecessary props if provided to this component, these are // only useful in `TableExpandRow` const className = cx(props.className, { [`${prefix}--data-table--selected`]: props.isSelected, + [`${prefix}--data-table--slug-row`]: rowHasSlug, }); + const cleanProps = { ...omit(props, [ 'ariaLabel', diff --git a/packages/react/src/components/DataTable/stories/DataTable-slug.stories.js b/packages/react/src/components/DataTable/stories/DataTable-slug.stories.js index dc6779394eb6..db3280ab59ca 100644 --- a/packages/react/src/components/DataTable/stories/DataTable-slug.stories.js +++ b/packages/react/src/components/DataTable/stories/DataTable-slug.stories.js @@ -51,6 +51,64 @@ export default { }, }; +const columnSlugHeaders = [ + { + key: 'name', + header: 'Name', + }, + { + key: 'protocol', + header: 'Protocol', + }, + { + key: 'port', + header: 'Port', + }, + { + key: 'rule', + header: 'Rule', + }, + { + key: 'attached_groups', + header: 'Attached groups', + slug: ( + + +
+

AI Explained

+

84%

+

Confidence score

+

+ Lorem ipsum dolor sit amet, di os consectetur adipiscing elit, sed + do eiusmod tempor incididunt ut fsil labore et dolore magna + aliqua. +

+
+

Model type

+

Foundation model

+
+ + + + + + + + + + + + +
+
+ ), + }, + { + key: 'status', + header: 'Status', + }, +]; + const slug = ( @@ -82,37 +140,6 @@ const slug = ( ); -const columnSlug = ( - - -
-

AI Explained

-

84%

-

Confidence score

-

- Lorem ipsum dolor sit amet, di os consectetur adipiscing elit, sed do - eiusmod tempor incididunt ut fsil labore et dolore magna aliqua. -

-
-

Model type

-

Foundation model

-
- - - - - - - - - - - - -
-
-); - export const SlugWithSelection = () => ( {({ @@ -325,7 +352,7 @@ export const SlugWithExpansion = () => ( ); export const ColumnSlugWithSelectionAndExpansion = () => ( - + {({ rows, headers, @@ -336,6 +363,7 @@ export const ColumnSlugWithSelectionAndExpansion = () => ( getSelectionProps, getTableProps, getTableContainerProps, + getCellProps, }) => ( ( {headers.map((header, i) => ( + {...getHeaderProps({ + header, + })}> {header.header} ))} @@ -367,8 +396,11 @@ export const ColumnSlugWithSelectionAndExpansion = () => ( {row.cells.map((cell) => { - console.log(cell); - return {cell.value}; + return ( + + {cell.value} + + ); })} ( ); export const ColumnSlugSort = () => ( - - {({ rows, headers, getHeaderProps, getRowProps, getTableProps }) => ( + + {({ + rows, + headers, + getHeaderProps, + getRowProps, + getTableProps, + getCellProps, + }) => ( ( - {headers.map((header, i) => ( + {headers.map((header) => ( {header.header} @@ -412,7 +450,9 @@ export const ColumnSlugSort = () => ( {rows.map((row) => ( {row.cells.map((cell) => ( - {cell.value} + + {cell.value} + ))} ))} diff --git a/packages/react/src/components/DataTable/tools/__tests__/__snapshots__/normalize-test.js.snap b/packages/react/src/components/DataTable/tools/__tests__/__snapshots__/normalize-test.js.snap index 9a79e5eac6c1..c7869b02b40f 100644 --- a/packages/react/src/components/DataTable/tools/__tests__/__snapshots__/normalize-test.js.snap +++ b/packages/react/src/components/DataTable/tools/__tests__/__snapshots__/normalize-test.js.snap @@ -4,6 +4,7 @@ exports[`normalize should return a normalized map of cells by id 1`] = ` Object { "a:fieldA": Object { "errors": null, + "hasSlugHeader": false, "id": "a:fieldA", "info": Object { "header": "fieldA", @@ -15,6 +16,7 @@ Object { }, "a:fieldB": Object { "errors": null, + "hasSlugHeader": false, "id": "a:fieldB", "info": Object { "header": "fieldB", @@ -26,6 +28,7 @@ Object { }, "a:fieldC": Object { "errors": null, + "hasSlugHeader": false, "id": "a:fieldC", "info": Object { "header": "fieldC", @@ -37,6 +40,7 @@ Object { }, "b:fieldA": Object { "errors": null, + "hasSlugHeader": false, "id": "b:fieldA", "info": Object { "header": "fieldA", @@ -48,6 +52,7 @@ Object { }, "b:fieldB": Object { "errors": null, + "hasSlugHeader": false, "id": "b:fieldB", "info": Object { "header": "fieldB", @@ -59,6 +64,7 @@ Object { }, "b:fieldC": Object { "errors": null, + "hasSlugHeader": false, "id": "b:fieldC", "info": Object { "header": "fieldC", @@ -70,6 +76,7 @@ Object { }, "c:fieldA": Object { "errors": null, + "hasSlugHeader": false, "id": "c:fieldA", "info": Object { "header": "fieldA", @@ -81,6 +88,7 @@ Object { }, "c:fieldB": Object { "errors": null, + "hasSlugHeader": false, "id": "c:fieldB", "info": Object { "header": "fieldB", @@ -92,6 +100,7 @@ Object { }, "c:fieldC": Object { "errors": null, + "hasSlugHeader": false, "id": "c:fieldC", "info": Object { "header": "fieldC", diff --git a/packages/react/src/components/DataTable/tools/normalize.js b/packages/react/src/components/DataTable/tools/normalize.js index 2fc59f6842f2..3a182e6b3f78 100644 --- a/packages/react/src/components/DataTable/tools/normalize.js +++ b/packages/react/src/components/DataTable/tools/normalize.js @@ -45,7 +45,7 @@ const normalize = (rows, headers, prevState = {}) => { rowsById[row.id].isExpanded = prevRowsByIds[row.id].isExpanded; } - headers.forEach(({ key }, i) => { + headers.forEach(({ key, slug }, i) => { const id = getCellId(row.id, key); // Initialize the cell info and state values, namely for editing cellsById[id] = { @@ -55,6 +55,7 @@ const normalize = (rows, headers, prevState = {}) => { isEditing: false, isValid: true, errors: null, + hasSlugHeader: !!slug, info: { header: key, }, diff --git a/packages/react/src/components/Slug/Slug.stories.js b/packages/react/src/components/Slug/Slug.stories.js index 4f051caca746..239190aaf415 100644 --- a/packages/react/src/components/Slug/Slug.stories.js +++ b/packages/react/src/components/Slug/Slug.stories.js @@ -295,7 +295,7 @@ export const Default = () => ( ); -export const Test = (args) => { +export const Callout = (args) => { const { showSlugActions = true } = args; return ( @@ -336,7 +336,7 @@ export const Test = (args) => { ); }; -Test.argTypes = { +Callout.argTypes = { showSlugActions: { control: { type: 'boolean', diff --git a/packages/react/src/components/Slug/slug-story.scss b/packages/react/src/components/Slug/slug-story.scss index 7ffc21fb4f51..cb5e3973c7ff 100644 --- a/packages/react/src/components/Slug/slug-story.scss +++ b/packages/react/src/components/Slug/slug-story.scss @@ -13,7 +13,6 @@ .slug-container-example.centered { margin: 0; - height: calc(100vh - 84px); width: calc(100vw - 84px); align-items: center; justify-content: center; diff --git a/packages/styles/scss/__tests__/theme-test.js b/packages/styles/scss/__tests__/theme-test.js index 487f1ef05195..579ab1f076ba 100644 --- a/packages/styles/scss/__tests__/theme-test.js +++ b/packages/styles/scss/__tests__/theme-test.js @@ -153,6 +153,7 @@ describe('@carbon/styles/scss/theme', () => { "slug-callout-shadow-outer-02", "ai-inner-shadow", "ai-aura-start", + "ai-aura-start-table", "ai-aura-end", "ai-aura-hover-background", "ai-aura-hover-start", diff --git a/packages/styles/scss/components/data-table/_data-table.scss b/packages/styles/scss/components/data-table/_data-table.scss index 7c964c8f69c5..4db0cbde5e47 100644 --- a/packages/styles/scss/components/data-table/_data-table.scss +++ b/packages/styles/scss/components/data-table/_data-table.scss @@ -945,20 +945,94 @@ margin: convert.to-rem(-3px) 0; } + // ------------------- // Slug styles + // ------------------- .#{$prefix}--data-table .#{$prefix}--table-column-slug { inline-size: $spacing-05; padding-inline-end: 0; } - .#{$prefix}--data-table - tbody - tr:has(> .#{$prefix}--table-column-slug--active) { - @include ai-gradient('left', 50%); + tr.#{$prefix}--data-table--slug-row, + tr.#{$prefix}--data-table--slug-row + .#{$prefix}--expandable-row { + @include ai-table-gradient(); background-attachment: fixed; } + .#{$prefix}--data-table--slug-row { + box-shadow: inset 1px 0 $ai-border-strong; + } + + // Remove table cell backgrounds that are overriding gradient background on row + .#{$prefix}--data-table tbody tr.#{$prefix}--data-table--slug-row:hover td, + tr.#{$prefix}--data-table--slug-row.#{$prefix}--expandable-row:hover + + .#{$prefix}--expandable-row[data-child-row] + td, + tr.#{$prefix}--data-table--slug-row.#{$prefix}--expandable-row--hover + + .#{$prefix}--expandable-row[data-child-row]:hover + > td, + tr.#{$prefix}--data-table--slug-row.#{$prefix}--expandable-row--hover > td, + tr.#{$prefix}--data-table--selected.#{$prefix}--data-table--slug-row.#{$prefix}--expandable-row + + tr.#{$prefix}--expandable-row[data-child-row] + > td, + tr.#{$prefix}--data-table--slug-row.#{$prefix}--parent-row.#{$prefix}--data-table--selected.#{$prefix}--expandable-row:hover + td, + tr.#{$prefix}--data-table--slug-row.#{$prefix}--parent-row.#{$prefix}--data-table--selected.#{$prefix}--expandable-row:hover + td:first-of-type, + tr.#{$prefix}--data-table--slug-row.#{$prefix}--parent-row.#{$prefix}--data-table--selected:not( + .#{$prefix}--expandable-row + ):hover + > td, + tr.#{$prefix}--data-table--slug-row.#{$prefix}--parent-row.#{$prefix}--data-table--selected.#{$prefix}--expandable-row:hover + + tr[data-child-row] + > td, + tr.#{$prefix}--data-table--slug-row.#{$prefix}--parent-row.#{$prefix}--data-table--selected.#{$prefix}--expandable-row--hover + > td, + tr.#{$prefix}--data-table--slug-row.#{$prefix}--parent-row.#{$prefix}--data-table--selected.#{$prefix}--expandable-row--hover + > td:first-of-type { + background-color: transparent; + } + + .#{$prefix}--data-table tbody tr.#{$prefix}--data-table--slug-row:hover, + tr.#{$prefix}--data-table--slug-row:hover + + .#{$prefix}--expandable-row[data-child-row], + tr.#{$prefix}--expandable-row--hover + + .#{$prefix}--expandable-row[data-child-row]:hover, + tr.#{$prefix}--expandable-row--hover.#{$prefix}--data-table--slug-row, + tr.#{$prefix}--data-table--selected.#{$prefix}--parent-row.#{$prefix}--expandable-row--hover.#{$prefix}--data-table--slug-row { + @include ai-table-gradient('hover'); + } + + tr.#{$prefix}--parent-row.cds--data-table--selected.#{$prefix}--data-table--slug-row, + .#{$prefix}--data-table--selected.#{$prefix}--data-table--slug-row, + tr.#{$prefix}--data-table--selected.#{$prefix}--data-table--slug-row + + .#{$prefix}--expandable-row { + @include ai-table-gradient('selected'); + } + + tr.#{$prefix}--data-table--slug-row.#{$prefix}--data-table--selected td, + tr.#{$prefix}--data-table--slug-row.#{$prefix}--data-table--selected:hover td, + tbody tr.#{$prefix}--data-table--slug-row:hover td, + tr.#{$prefix}--data-table--slug-row.#{$prefix}--parent-row.#{$prefix}--data-table--selected.#{$prefix}--expandable-row:hover + td:not(.#{$prefix}--table-expand):not( + .#{$prefix}--table-column-checkbox + ):not(.#{$prefix}--table-column-slug) { + border-block-end-color: $border-subtle; + } + + tr.#{$prefix}--expandable-row.cds--data-table--selected.#{$prefix}--data-table--slug-row[data-parent-row] + > td:not(.#{$prefix}--table-expand):not( + .#{$prefix}--table-column-checkbox + ):not(.#{$prefix}--table-column-slug) { + border-block-end: 1px solid $layer-selected; + } + + tr.#{$prefix}--parent-row.#{$prefix}--data-table--slug-row.#{$prefix}--expandable-row:hover + td:first-of-type { + border-block-end: 1px solid transparent; + } + .#{$prefix}--data-table thead th.#{$prefix}--table-sort__header--slug @@ -966,11 +1040,12 @@ .#{$prefix}--data-table thead th:has(> .#{$prefix}--table-header-label--slug) { - @include ai-gradient('top', 100%); + @include ai-table-gradient(); } .#{$prefix}--table-column-slug .#{$prefix}--slug { position: absolute; + z-index: 2; transform: translateY(-50%); } @@ -987,9 +1062,32 @@ th .#{$prefix}--table-header-label.#{$prefix}--table-header-label--slug .#{$prefix}--slug { - margin-inline-start: $spacing-03; + margin-inline-start: auto; + } + + th.#{$prefix}--table-sort__header--slug, + th:has(.#{$prefix}--table-header-label--slug) { + box-shadow: inset 0 1px $ai-border-strong; } + td.#{$prefix}--table-cell--column-slug { + @include ai-table-gradient(); + } + + tr.#{$prefix}--parent-row:not(.#{$prefix}--expandable-row):not(:first-of-type) + td.#{$prefix}--table-cell--column-slug { + // Same gradient as background + border-block-start: linear-gradient( + to right, + $ai-aura-start-table 0%, + $ai-aura-end 50%, + transparent 50% + ); + } + + tr.#{$prefix}--parent-row:not(.#{$prefix}--expandable-row):not(:first-of-type) + td.#{$prefix}--table-cell--column-slug, + // Windows HCM fix // stylelint-disable-next-line no-duplicate-selectors .#{$prefix}--data-table-content { diff --git a/packages/styles/scss/components/data-table/expandable/_data-table-expandable.scss b/packages/styles/scss/components/data-table/expandable/_data-table-expandable.scss index c1ea28efd901..0dccf847ff1f 100644 --- a/packages/styles/scss/components/data-table/expandable/_data-table-expandable.scss +++ b/packages/styles/scss/components/data-table/expandable/_data-table-expandable.scss @@ -78,7 +78,7 @@ } // Increase padding inside expandable row when only a slug OR checkbox is present in row - tbody:has(> tr.#{$prefix}--parent-row--slug) + tbody:has(> tr.#{$prefix}--data-table--slug-row) > tr.#{$prefix}--expandable-row[data-child-row] td, tbody:has(td.#{$prefix}--table-column-checkbox) @@ -88,7 +88,7 @@ } // Increase padding inside expandable row when slug AND checkbox is present in row - tbody:has(> tr.#{$prefix}--parent-row--slug):has( + tbody:has(> tr.#{$prefix}--data-table--slug-row):has( td.#{$prefix}--table-column-checkbox ) > tr.#{$prefix}--expandable-row[data-child-row] @@ -476,8 +476,8 @@ border-block-end: 1px solid transparent; } - .#{$prefix}--parent-row--slug td, - .#{$prefix}--data-table tr.#{$prefix}--parent-row--slug:hover td { + .#{$prefix}--data-table--slug-row td, + .#{$prefix}--data-table tr.#{$prefix}--data-table--slug-row:hover td { border-block-start: 1px solid transparent; } diff --git a/packages/styles/scss/components/data-table/sort/_data-table-sort.scss b/packages/styles/scss/components/data-table/sort/_data-table-sort.scss index 63730fe3c2f5..0b6e4a190138 100644 --- a/packages/styles/scss/components/data-table/sort/_data-table-sort.scss +++ b/packages/styles/scss/components/data-table/sort/_data-table-sort.scss @@ -249,9 +249,14 @@ } // Slug styles + .#{$prefix}--table-sort__header--slug .#{$prefix}--table-sort__icon, + .#{$prefix}--table-sort__header--slug .#{$prefix}--table-sort__icon-unsorted { + margin-inline-end: convert.to-rem(8px); + margin-inline-start: auto; + } + .#{$prefix}--table-sort__header--slug .#{$prefix}--slug { - margin-inline-end: auto; - margin-inline-start: convert.to-rem(8px); + margin-inline-end: convert.to-rem(8px); } // Windows HCM fix diff --git a/packages/styles/scss/utilities/_ai-gradient.scss b/packages/styles/scss/utilities/_ai-gradient.scss index 011e99a28c04..2d05b8b0d16d 100644 --- a/packages/styles/scss/utilities/_ai-gradient.scss +++ b/packages/styles/scss/utilities/_ai-gradient.scss @@ -38,6 +38,33 @@ border-block-end-color: theme.$ai-border-strong; } +@mixin ai-table-gradient($type: 'default', $span: 50%) { + @if $type == 'hover' { + background: linear-gradient( + to right, + theme.$ai-aura-hover-start 0%, + 15%, + theme.$ai-aura-hover-end 50% + ), + theme.$ai-aura-hover-background; + } @else if $type == 'selected' { + background: linear-gradient( + to right, + theme.$ai-inner-shadow 0%, + theme.$ai-aura-end 50%, + transparent 50% + ), + theme.$layer-selected; + } @else { + background: linear-gradient( + to right, + theme.$ai-aura-start-table 0%, + theme.$ai-aura-end $span, + transparent 50% + ); + } +} + /// Experimental - name and structure subject to change. Use at your own risk! /// Adds callout gradient styles to a component /// @access private @@ -49,14 +76,14 @@ @mixin callout-gradient( $type: 'default', $offset: 0, - $background: theme.$background + $background: 'background' ) { $start: 0%; @if $offset != 0 { $start: calc(0% + #{$offset}); } - $background: custom-property.get-var($background, theme.$background); + $background: custom-property.get-var(#{$background}, theme.$background); @if $type == 'hover' { background: linear-gradient( diff --git a/packages/themes/src/g10.js b/packages/themes/src/g10.js index 6d98d407159c..0830cbf09691 100644 --- a/packages/themes/src/g10.js +++ b/packages/themes/src/g10.js @@ -217,6 +217,7 @@ export const slugHollowHover = gray80Hover; //// Phase 2 - new \\\\ // Shared export const aiInnerShadow = rgba(blue50, 0.2); +export const aiAuraStartTable = rgba(blue50, 0.15); export const aiAuraStart = rgba(blue50, 0.1); export const aiAuraEnd = rgba(white, 0); export const aiBorderStrong = blue50; diff --git a/packages/themes/src/g100.js b/packages/themes/src/g100.js index 943742cb37a9..abf390e880f3 100644 --- a/packages/themes/src/g100.js +++ b/packages/themes/src/g100.js @@ -222,6 +222,7 @@ export const slugHollowHover = gray30Hover; //// Phase 2 - new \\\\ // Shared export const aiInnerShadow = rgba(blue50, 0.2); +export const aiAuraStartTable = rgba(blue50, 0.15); export const aiAuraStart = rgba(blue50, 0.1); export const aiAuraEnd = rgba(black, 0); export const aiBorderStrong = blue40; diff --git a/packages/themes/src/g90.js b/packages/themes/src/g90.js index 99687e1cdfbd..1b4203d03387 100644 --- a/packages/themes/src/g90.js +++ b/packages/themes/src/g90.js @@ -223,6 +223,7 @@ export const slugHollowHover = gray30Hover; //// Phase 2 - new \\\\ // Shared export const aiInnerShadow = rgba(blue50, 0.2); +export const aiAuraStartTable = rgba(blue50, 0.15); export const aiAuraStart = rgba(blue50, 0.1); export const aiAuraEnd = rgba(black, 0); export const aiBorderStrong = blue40; diff --git a/packages/themes/src/tokens/__tests__/__snapshots__/v11-test.js.snap b/packages/themes/src/tokens/__tests__/__snapshots__/v11-test.js.snap index 4a369605c04a..81c969f3e0e8 100644 --- a/packages/themes/src/tokens/__tests__/__snapshots__/v11-test.js.snap +++ b/packages/themes/src/tokens/__tests__/__snapshots__/v11-test.js.snap @@ -264,6 +264,7 @@ Array [ "slug-callout-shadow-outer-02", "ai-inner-shadow", "ai-aura-start", + "ai-aura-start-table", "ai-aura-end", "ai-aura-hover-background", "ai-aura-hover-start", diff --git a/packages/themes/src/tokens/__tests__/metadata-test.js b/packages/themes/src/tokens/__tests__/metadata-test.js index 654f3feeb4e7..ea1e0b007b14 100644 --- a/packages/themes/src/tokens/__tests__/metadata-test.js +++ b/packages/themes/src/tokens/__tests__/metadata-test.js @@ -1029,6 +1029,10 @@ test('metadata', () => { "name": "ai-aura-start", "type": "color", }, + Object { + "name": "ai-aura-start-table", + "type": "color", + }, Object { "name": "ai-aura-end", "type": "color", diff --git a/packages/themes/src/tokens/v11TokenGroup.js b/packages/themes/src/tokens/v11TokenGroup.js index 0783ce9a646c..facd291d30e7 100644 --- a/packages/themes/src/tokens/v11TokenGroup.js +++ b/packages/themes/src/tokens/v11TokenGroup.js @@ -373,6 +373,7 @@ export const ai = TokenGroup.create({ // Linear gradient refactor 'ai-inner-shadow', 'ai-aura-start', + 'ai-aura-start-table', 'ai-aura-end', 'ai-aura-hover-background', 'ai-aura-hover-start', diff --git a/packages/themes/src/white.js b/packages/themes/src/white.js index 4f0ee4e7b8b1..e50c676ec9b4 100644 --- a/packages/themes/src/white.js +++ b/packages/themes/src/white.js @@ -217,6 +217,7 @@ export const slugHollowHover = gray80Hover; //// Phase 2 - new \\\\ // Shared export const aiInnerShadow = rgba(blue50, 0.2); +export const aiAuraStartTable = rgba(blue50, 0.15); export const aiAuraStart = rgba(blue50, 0.1); export const aiAuraEnd = rgba(white, 0); export const aiBorderStrong = blue50;