diff --git a/.changeset/selfish-flowers-approve.md b/.changeset/selfish-flowers-approve.md new file mode 100644 index 00000000000..4bdba41d241 --- /dev/null +++ b/.changeset/selfish-flowers-approve.md @@ -0,0 +1,5 @@ +--- +"@primer/react": minor +--- + +Update Table to use CSS Modules behind feature flag diff --git a/.changeset/short-fireants-jog.md b/.changeset/short-fireants-jog.md new file mode 100644 index 00000000000..da0b60ece71 --- /dev/null +++ b/.changeset/short-fireants-jog.md @@ -0,0 +1,5 @@ +--- +"@primer/react": patch +--- + +Add `flex-shrink` to IconButton diff --git a/.changeset/violet-tables-eat.md b/.changeset/violet-tables-eat.md new file mode 100644 index 00000000000..ac644ed6b67 --- /dev/null +++ b/.changeset/violet-tables-eat.md @@ -0,0 +1,5 @@ +--- +"@primer/react": minor +--- + +Remove CSS modules feature flag from Select diff --git a/packages/react/src/DataTable/Table.module.css b/packages/react/src/DataTable/Table.module.css new file mode 100644 index 00000000000..3320808e167 --- /dev/null +++ b/packages/react/src/DataTable/Table.module.css @@ -0,0 +1,287 @@ +/* Container ---------------------------------------------------------------- */ +.TableContainer { + display: grid; + grid-template-columns: 1fr 1fr; + grid-template-areas: + 'title actions' + 'divider divider' + 'subtitle subtitle' + 'filter filter' + 'table table' + 'footer footer'; + column-gap: var(--base-size-8); +} + +/* TableTitle */ +.TableTitle { + margin: 0; + font-size: var(--text-body-size-medium); + font-weight: var(--base-text-weight-semibold); + /* stylelint-disable-next-line primer/typography */ + line-height: 20px; + color: var(--fgColor-default); + grid-area: title; + align-self: center; +} + +/* TableSubtitle */ +.TableSubtitle { + margin: 0; + font-size: var(--text-body-size-small); + font-weight: var(--base-text-weight-normal); + line-height: var(--text-title-lineHeight-small); + color: var(--fgColor-default); + grid-area: subtitle; +} + +/* TableActions */ +.TableActions { + display: flex; + column-gap: var(--base-size-8); + align-items: center; + grid-area: actions; + justify-self: end; +} + +/* TableDivider */ +.TableDivider { + width: 100%; + height: 1px; + /* stylelint-disable-next-line primer/colors */ + background-color: var(--borderColor-default); + grid-area: divider; + margin-block-start: var(--base-size-16); + margin-block-end: var(--base-size-8); +} + +/* Spacing before the table */ +.TableTitle + .TableOverflowWrapper, +.TableSubtitle + .TableOverflowWrapper, +.TableActions + .TableOverflowWrapper { + margin-block-start: var(--base-size-8); +} + +.TableOverflowWrapper { + grid-area: table; +} + +/* Table -------------------------------------------------------------------- */ +.Table { + /* Default table styles */ + --table-border-radius: 0.375rem; + --table-cell-padding: var(--cell-padding-block, 0.5rem) var(--cell-padding-inline, 0.75rem); + --table-font-size: 0.75rem; + + display: grid; + width: 100%; + /* stylelint-disable-next-line primer/typography */ + font-size: var(--table-font-size); + /* stylelint-disable-next-line primer/typography */ + line-height: calc(20 / 12); + border-spacing: 0; + /* stylelint-disable-next-line primer/borders */ + border-collapse: separate; + background-color: var(--bgColor-default); + grid-area: table; + grid-template-columns: var(--grid-template-columns); + + /* Density modes: condensed, normal, spacious */ + &:where([data-cell-padding='condensed']) { + --cell-padding-block: 0.25rem; + --cell-padding-inline: 0.5rem; + } + + &:where([data-cell-padding='normal']) { + --cell-padding-block: 0.5rem; + --cell-padding-inline: 0.75rem; + } + + &:where([data-cell-padding='spacious']) { + --cell-padding-block: 0.75rem; + --cell-padding-inline: 1rem; + } +} + +/* Borders */ +.TableCell:first-child, +.TableHeader:first-child { + border-inline-start: var(--borderWidth-thin) solid var(--borderColor-default); +} + +.TableCell:last-child, +.TableHeader:last-child { + border-inline-end: var(--borderWidth-thin) solid var(--borderColor-default); +} + +.TableHeader, +.TableCell { + display: flex; + /* stylelint-disable-next-line primer/spacing */ + padding: var(--table-cell-padding); + text-align: start; + align-items: center; + border-block-end: var(--borderWidth-thin) solid var(--borderColor-default); +} + +.TableHeader:where([data-cell-align='end']), +.TableCell:where([data-cell-align='end']) { + display: flex; + text-align: end; + justify-content: flex-end; +} + +.TableHeader[data-cell-align='end'] .TableSortButton { + display: flex; + flex-direction: row-reverse; +} + +.TableHead .TableRow:first-of-type .TableHeader { + border-block-start: var(--borderWidth-thin) solid var(--borderColor-default); +} + +/* Border radius */ +/* stylelint-disable-next-line selector-max-specificity */ +.TableHead .TableRow:first-of-type .TableHeader:first-child { + /* stylelint-disable-next-line primer/borders */ + border-top-left-radius: var(--table-border-radius); +} + +/* stylelint-disable-next-line selector-max-specificity */ +.TableHead .TableRow:first-of-type .TableHeader:last-child { + /* stylelint-disable-next-line primer/borders */ + border-top-right-radius: var(--table-border-radius); +} + +/* stylelint-disable-next-line selector-max-compound-selectors,selector-max-specificity */ +.TableOverflowWrapper:last-child .Table .TableBody .TableRow:last-of-type .TableCell:first-child { + /* stylelint-disable-next-line primer/borders */ + border-bottom-left-radius: var(--table-border-radius); +} + +/* stylelint-disable-next-line selector-max-compound-selectors,selector-max-specificity */ +.TableOverflowWrapper:last-child .Table .TableBody .TableRow:last-of-type .TableCell:last-child { + /* stylelint-disable-next-line primer/borders */ + border-bottom-right-radius: var(--table-border-radius); +} + +/** + * Offset padding to make sure type aligns regardless of cell padding + * selection + */ +.TableRow > *:first-child:not(.TableCellSkeleton), +.TableRow > *:first-child .TableCellSkeletonItem { + padding-inline-start: var(--base-size-16); +} + +.TableRow > *:last-child:not(.TableCellSkeleton), +.TableRow > *:last-child .TableCellSkeletonItem { + padding-inline-end: var(--base-size-16); +} + +/* TableHeader */ +.TableHeader { + font-weight: var(--base-text-weight-semibold); + color: var(--fgColor-muted); + background-color: var(--bgColor-muted); + border-block-start: var(--borderWidth-thin) solid var(--borderColor-default); +} + +.TableHeader:where([aria-sort='descending']), +.TableHeader:where([aria-sort='ascending']) { + color: var(--fgColor-default); +} + +/* Control visibility of sort icons */ +.TableSortIcon { + visibility: hidden; +} + +/* The ASC icon is visible if the header is sortable and is hovered or focused */ +.TableHeader:hover .TableSortIcon--ascending, +.TableHeader .TableSortButton:focus .TableSortIcon--ascending { + visibility: visible; +} + +/* Each sort icon is visible if the TableHeader is currently in the corresponding sort state */ +.TableHeader[aria-sort='ascending'] .TableSortIcon--ascending, +.TableHeader[aria-sort='descending'] .TableSortIcon--descending { + visibility: visible; +} + +/* TableRow */ +.TableRow:hover .TableCell:not(.TableCellSkeleton) { + background-color: var(--control-transparent-bgColor-hover); +} + +/* TableCell */ +.TableCell:where([scope='row']) { + display: flex; + font-weight: var(--base-text-weight-semibold); + color: var(--fgColor-default); + align-items: center; +} + +/* TableCellSkeleton */ +.TableCellSkeleton { + padding: 0; +} + +.TableCellSkeletonItems { + display: flex; + width: 100%; + flex-direction: column; +} + +.TableCellSkeletonItem { + /* stylelint-disable-next-line primer/spacing */ + padding: var(--table-cell-padding); + + &:nth-of-type(5n + 1) { + --skeleton-item-width: 85%; + } + + &:nth-of-type(5n + 2) { + --skeleton-item-width: 67.5%; + } + + &:nth-of-type(5n + 3) { + --skeleton-item-width: 80%; + } + + &:nth-of-type(5n + 4) { + --skeleton-item-width: 60%; + } + + &:nth-of-type(5n + 5) { + --skeleton-item-width: 75%; + } +} + +.TableCellSkeletonItem [data-component='SkeletonText'] { + width: var(--skeleton-item-width); +} + +.TableCellSkeletonItem:not(:last-of-type) { + border-block-end: var(--borderWidth-thin) solid var(--borderColor-default); +} + +.TableSortButton { + column-gap: 0.5rem; +} + +/* Grid layout */ +.TableHead, +.TableBody, +.TableRow { + display: contents; +} + +@supports (grid-template-columns: subgrid) { + .TableHead, + .TableBody, + .TableRow { + display: grid; + grid-template-columns: subgrid; + grid-column: -1 /1; + } +} diff --git a/packages/react/src/DataTable/Table.tsx b/packages/react/src/DataTable/Table.tsx index b4bf6796eb7..67b78e33648 100644 --- a/packages/react/src/DataTable/Table.tsx +++ b/packages/react/src/DataTable/Table.tsx @@ -2,7 +2,6 @@ import {SortAscIcon, SortDescIcon} from '@primer/octicons-react' import {clsx} from 'clsx' import React from 'react' import styled from 'styled-components' -import Box from '../Box' import Text from '../Text' import {get} from '../constants' import type {SxProp} from '../sx' @@ -14,213 +13,227 @@ import {SortDirection} from './sorting' import {useTableLayout} from './useTable' import {SkeletonText} from '../experimental/Skeleton/SkeletonText' import {ScrollableRegion} from '../ScrollableRegion' +import {useFeatureFlag} from '../FeatureFlags' +import {toggleStyledComponent} from '../internal/utils/toggleStyledComponent' +import {Button} from '../internal/components/ButtonReset' +import classes from './Table.module.css' + +const cssModulesFlag = 'primer_react_css_modules_team' // ---------------------------------------------------------------------------- // Table // ---------------------------------------------------------------------------- -const StyledTable = styled.table>` - /* Default table styles */ - --table-border-radius: 0.375rem; - --table-cell-padding: var(--cell-padding-block, 0.5rem) var(--cell-padding-inline, 0.75rem); - --table-font-size: 0.75rem; - - background-color: ${get('colors.canvas.default')}; - border-spacing: 0; - border-collapse: separate; - display: grid; - font-size: var(--table-font-size); - grid-template-columns: var(--grid-template-columns); - line-height: calc(20 / 12); - width: 100%; - - /* Density modes: condensed, normal, spacious */ - &[data-cell-padding='condensed'] { - --cell-padding-block: 0.25rem; - --cell-padding-inline: 0.5rem; - } - - &[data-cell-padding='normal'] { - --cell-padding-block: 0.5rem; - --cell-padding-inline: 0.75rem; - } - - &[data-cell-padding='spacious'] { - --cell-padding-block: 0.75rem; - --cell-padding-inline: 1rem; - } - - /* Borders */ - .TableCell:first-child, - .TableHeader:first-child { - border-left: 1px solid ${get('colors.border.default')}; - } - - .TableCell:last-child, - .TableHeader:last-child { - border-right: 1px solid ${get('colors.border.default')}; - } - - .TableHeader, - .TableCell { - text-align: start; - display: flex; - align-items: center; - border-bottom: 1px solid ${get('colors.border.default')}; - padding: var(--table-cell-padding); - } - - .TableHeader[data-cell-align='end'], - .TableCell[data-cell-align='end'] { - text-align: end; - display: flex; - justify-content: flex-end; - } - - .TableHeader[data-cell-align='end'] .TableSortButton { - display: flex; - flex-direction: row-reverse; - } - - .TableHead .TableRow:first-of-type .TableHeader { - border-top: 1px solid ${get('colors.border.default')}; - } - - /* Border radius */ - .TableHead .TableRow:first-of-type .TableHeader:first-child { - border-top-left-radius: var(--table-border-radius); - } - - .TableHead .TableRow:first-of-type .TableHeader:last-child { - border-top-right-radius: var(--table-border-radius); - } - - .TableOverflowWrapper:last-child & .TableBody .TableRow:last-of-type .TableCell:first-child { - border-bottom-left-radius: var(--table-border-radius); - } - - .TableOverflowWrapper:last-child & .TableBody .TableRow:last-of-type .TableCell:last-child { - border-bottom-right-radius: var(--table-border-radius); - } +const StyledTable = toggleStyledComponent( + cssModulesFlag, + 'table', + styled.table>` + /* Default table styles */ + --table-border-radius: 0.375rem; + --table-cell-padding: var(--cell-padding-block, 0.5rem) var(--cell-padding-inline, 0.75rem); + --table-font-size: 0.75rem; + + background-color: ${get('colors.canvas.default')}; + border-spacing: 0; + border-collapse: separate; + display: grid; + font-size: var(--table-font-size); + grid-template-columns: var(--grid-template-columns); + line-height: calc(20 / 12); + width: 100%; - /** + /* Density modes: condensed, normal, spacious */ + &[data-cell-padding='condensed'] { + --cell-padding-block: 0.25rem; + --cell-padding-inline: 0.5rem; + } + + &[data-cell-padding='normal'] { + --cell-padding-block: 0.5rem; + --cell-padding-inline: 0.75rem; + } + + &[data-cell-padding='spacious'] { + --cell-padding-block: 0.75rem; + --cell-padding-inline: 1rem; + } + + /* Borders */ + .TableCell:first-child, + .TableHeader:first-child { + border-left: 1px solid ${get('colors.border.default')}; + } + + .TableCell:last-child, + .TableHeader:last-child { + border-right: 1px solid ${get('colors.border.default')}; + } + + .TableHeader, + .TableCell { + text-align: start; + display: flex; + align-items: center; + border-bottom: 1px solid ${get('colors.border.default')}; + padding: var(--table-cell-padding); + } + + .TableHeader[data-cell-align='end'], + .TableCell[data-cell-align='end'] { + text-align: end; + display: flex; + justify-content: flex-end; + } + + .TableHeader[data-cell-align='end'] .TableSortButton { + display: flex; + flex-direction: row-reverse; + } + + .TableHead .TableRow:first-of-type .TableHeader { + border-top: 1px solid ${get('colors.border.default')}; + } + + /* Border radius */ + .TableHead .TableRow:first-of-type .TableHeader:first-child { + border-top-left-radius: var(--table-border-radius); + } + + .TableHead .TableRow:first-of-type .TableHeader:last-child { + border-top-right-radius: var(--table-border-radius); + } + + .TableOverflowWrapper:last-child & .TableBody .TableRow:last-of-type .TableCell:first-child { + border-bottom-left-radius: var(--table-border-radius); + } + + .TableOverflowWrapper:last-child & .TableBody .TableRow:last-of-type .TableCell:last-child { + border-bottom-right-radius: var(--table-border-radius); + } + + /** * Offset padding to make sure type aligns regardless of cell padding * selection */ - .TableRow > *:first-child:not(.TableCellSkeleton), - .TableRow > *:first-child .TableCellSkeletonItem { - padding-inline-start: 1rem; - } - - .TableRow > *:last-child:not(.TableCellSkeleton), - .TableRow > *:last-child .TableCellSkeletonItem { - padding-inline-end: 1rem; - } - - /* TableHeader */ - .TableHeader { - background-color: ${get('colors.canvas.subtle')}; - color: ${get('colors.fg.muted')}; - font-weight: 600; - border-top: 1px solid ${get('colors.border.default')}; - } - - .TableHeader[aria-sort='descending'], - .TableHeader[aria-sort='ascending'] { - color: ${get('colors.fg.default')}; - } - - /* Control visibility of sort icons */ - .TableSortIcon { - visibility: hidden; - } - - /* The ASC icon is visible if the header is sortable and is hovered or focused */ - .TableHeader:hover .TableSortIcon--ascending, - .TableHeader .TableSortButton:focus .TableSortIcon--ascending { - visibility: visible; - } - - /* Each sort icon is visible if the TableHeader is currently in the corresponding sort state */ - .TableHeader[aria-sort='ascending'] .TableSortIcon--ascending, - .TableHeader[aria-sort='descending'] .TableSortIcon--descending { - visibility: visible; - } - - /* TableRow */ - .TableRow:hover .TableCell:not(.TableCellSkeleton) { - /* TODO: update this token when the new primitive tokens are released */ - background-color: ${get('colors.actionListItem.default.hoverBg')}; - } - - /* TableCell */ - .TableCell[scope='row'] { - align-items: center; - display: flex; - color: ${get('colors.fg.default')}; - font-weight: 600; - } - - /* TableCellSkeleton */ - .TableCellSkeleton { - padding: 0; - } - - .TableCellSkeletonItems { - display: flex; - flex-direction: column; - width: 100%; - } + .TableRow > *:first-child:not(.TableCellSkeleton), + .TableRow > *:first-child .TableCellSkeletonItem { + padding-inline-start: 1rem; + } + + .TableRow > *:last-child:not(.TableCellSkeleton), + .TableRow > *:last-child .TableCellSkeletonItem { + padding-inline-end: 1rem; + } - .TableCellSkeletonItem { - padding: var(--table-cell-padding); + /* TableHeader */ + .TableHeader { + background-color: ${get('colors.canvas.subtle')}; + color: ${get('colors.fg.muted')}; + font-weight: 600; + border-top: 1px solid ${get('colors.border.default')}; + } - &:nth-of-type(5n + 1) { - --skeleton-item-width: 85%; + .TableHeader[aria-sort='descending'], + .TableHeader[aria-sort='ascending'] { + color: ${get('colors.fg.default')}; } - &:nth-of-type(5n + 2) { - --skeleton-item-width: 67.5%; + /* Control visibility of sort icons */ + .TableSortIcon { + visibility: hidden; } - &:nth-of-type(5n + 3) { - --skeleton-item-width: 80%; + /* The ASC icon is visible if the header is sortable and is hovered or focused */ + .TableHeader:hover .TableSortIcon--ascending, + .TableHeader .TableSortButton:focus .TableSortIcon--ascending { + visibility: visible; } - &:nth-of-type(5n + 4) { - --skeleton-item-width: 60%; + /* Each sort icon is visible if the TableHeader is currently in the corresponding sort state */ + .TableHeader[aria-sort='ascending'] .TableSortIcon--ascending, + .TableHeader[aria-sort='descending'] .TableSortIcon--descending { + visibility: visible; } - &:nth-of-type(5n + 5) { - --skeleton-item-width: 75%; + /* TableRow */ + .TableRow:hover .TableCell:not(.TableCellSkeleton) { + /* TODO: update this token when the new primitive tokens are released */ + background-color: ${get('colors.actionListItem.default.hoverBg')}; } - } - .TableCellSkeletonItem [data-component='SkeletonText'] { - width: var(--skeleton-item-width); - } + /* TableCell */ + .TableCell[scope='row'] { + align-items: center; + display: flex; + color: ${get('colors.fg.default')}; + font-weight: 600; + } + + /* TableCellSkeleton */ + .TableCellSkeleton { + padding: 0; + } + + .TableCellSkeletonItems { + display: flex; + flex-direction: column; + width: 100%; + } + + .TableCellSkeletonItem { + padding: var(--table-cell-padding); + + &:nth-of-type(5n + 1) { + --skeleton-item-width: 85%; + } + + &:nth-of-type(5n + 2) { + --skeleton-item-width: 67.5%; + } + + &:nth-of-type(5n + 3) { + --skeleton-item-width: 80%; + } + + &:nth-of-type(5n + 4) { + --skeleton-item-width: 60%; + } + + &:nth-of-type(5n + 5) { + --skeleton-item-width: 75%; + } + } - .TableCellSkeletonItem:not(:last-of-type) { - border-bottom: 1px solid ${get('colors.border.default')}; - } + .TableCellSkeletonItem [data-component='SkeletonText'] { + width: var(--skeleton-item-width); + } - /* Grid layout */ - .TableHead, - .TableBody, - .TableRow { - display: contents; - } + .TableCellSkeletonItem:not(:last-of-type) { + border-bottom: 1px solid ${get('colors.border.default')}; + } - @supports (grid-template-columns: subgrid) { + /* Grid layout */ .TableHead, .TableBody, .TableRow { - display: grid; - grid-template-columns: subgrid; - grid-column: -1 /1; + display: contents; + } + + @supports (grid-template-columns: subgrid) { + .TableHead, + .TableBody, + .TableRow { + display: grid; + grid-template-columns: subgrid; + grid-column: -1 /1; + } + } + + .TableSortButton { + column-gap: 0.5rem; } - } -` + `, +) export type TableProps = React.ComponentPropsWithoutRef<'table'> & { /** @@ -249,15 +262,25 @@ const Table = React.forwardRef(function Table( {'aria-labelledby': labelledby, cellPadding = 'normal', className, gridTemplateColumns, ...rest}, ref, ) { + const enabled = useFeatureFlag(cssModulesFlag) + return ( // TODO update type to be non-optional in next major release // @ts-expect-error this type should be required in the next major version - + (function Table( export type TableHeadProps = React.ComponentPropsWithoutRef<'thead'> function TableHead({children}: TableHeadProps) { + const enabled = useFeatureFlag(cssModulesFlag) return ( // We need to explicitly pass this role because some ATs and browsers drop table semantics // when we use `display: contents` or `display: grid` in the table - + {children} ) @@ -289,10 +318,16 @@ function TableHead({children}: TableHeadProps) { export type TableBodyProps = React.ComponentPropsWithoutRef<'tbody'> function TableBody({children}: TableBodyProps) { + const enabled = useFeatureFlag(cssModulesFlag) return ( // We need to explicitly pass this role because some ATs and browsers drop table semantics // when we use `display: contents` or `display: grid` in the table - + {children} ) @@ -310,8 +345,17 @@ export type TableHeaderProps = Omit, 'align } function TableHeader({align, children, ...rest}: TableHeaderProps) { + const enabled = useFeatureFlag(cssModulesFlag) return ( - + {children} ) @@ -331,22 +375,37 @@ type TableSortHeaderProps = TableHeaderProps & { } function TableSortHeader({align, children, direction, onToggleSort, ...rest}: TableSortHeaderProps) { + const enabled = useFeatureFlag(cssModulesFlag) const ariaSort = direction === 'DESC' ? 'descending' : direction === 'ASC' ? 'ascending' : undefined return ( ) @@ -359,8 +418,15 @@ function TableSortHeader({align, children, direction, onToggleSort, ...rest}: Ta export type TableRowProps = React.ComponentPropsWithoutRef<'tr'> function TableRow({children, ...rest}: TableRowProps) { + const enabled = useFeatureFlag(cssModulesFlag) return ( - + {children} ) @@ -384,11 +450,20 @@ export type TableCellProps = Omit, 'align'> } function TableCell({align, className, children, scope, ...rest}: TableCellProps) { + const enabled = useFeatureFlag(cssModulesFlag) const BaseComponent = scope ? 'th' : 'td' const role = scope ? 'rowheader' : 'cell' return ( - + {children} ) @@ -403,68 +478,82 @@ function TableCellPlaceholder({children}: TableCellPlaceholderProps) { // ---------------------------------------------------------------------------- // TableContainer // ---------------------------------------------------------------------------- -const StyledTableContainer = styled.div` - display: grid; - grid-template-columns: 1fr 1fr; - grid-template-areas: - 'title actions' - 'divider divider' - 'subtitle subtitle' - 'filter filter' - 'table table' - 'footer footer'; - column-gap: ${get('space.2')}; - - ${sx} - - /* TableTitle */ - .TableTitle { - grid-area: title; - align-self: center; - } - - /* TableSubtitle */ - .TableSubtitle { - grid-area: subtitle; - } - - /* TableActions */ - .TableActions { - display: flex; +const StyledTableContainer = toggleStyledComponent( + cssModulesFlag, + 'div', + styled.div` + display: grid; + grid-template-columns: 1fr 1fr; + grid-template-areas: + 'title actions' + 'divider divider' + 'subtitle subtitle' + 'filter filter' + 'table table' + 'footer footer'; column-gap: ${get('space.2')}; - align-items: center; - grid-area: actions; - justify-self: end; - } - - /* TableDivider */ - .TableDivider { - grid-area: divider; - margin-top: ${get('space.3')}; - margin-bottom: ${get('space.2')}; - } - - /* Table */ - .Table { - grid-area: table; - } - - /* Spacing before the table */ - .TableTitle + .TableOverflowWrapper, - .TableSubtitle + .TableOverflowWrapper, - .TableActions + .TableOverflowWrapper { - margin-top: ${get('space.2')}; - } - - .TableOverflowWrapper { - grid-area: table; - } -` + + ${sx} + + /* TableTitle */ + .TableTitle { + grid-area: title; + align-self: center; + } + + /* TableSubtitle */ + .TableSubtitle { + grid-area: subtitle; + } + + /* TableActions */ + .TableActions { + display: flex; + column-gap: ${get('space.2')}; + align-items: center; + grid-area: actions; + justify-self: end; + } + + /* TableDivider */ + .TableDivider { + grid-area: divider; + margin-top: ${get('space.3')}; + margin-bottom: ${get('space.2')}; + } + + /* Table */ + .Table { + grid-area: table; + } + + /* Spacing before the table */ + .TableTitle + .TableOverflowWrapper, + .TableSubtitle + .TableOverflowWrapper, + .TableActions + .TableOverflowWrapper { + margin-top: ${get('space.2')}; + } + + .TableOverflowWrapper { + grid-area: table; + } + `, +) export type TableContainerProps = React.PropsWithChildren function TableContainer({children, sx}: TableContainerProps) { - return {children} + const enabled = useFeatureFlag(cssModulesFlag) + return ( + + {children} + + ) } export type TableTitleProps = React.PropsWithChildren<{ @@ -483,25 +572,33 @@ export type TableTitleProps = React.PropsWithChildren<{ }> const TableTitle = React.forwardRef(function TableTitle({as = 'h2', children, id}, ref) { + const enabled = useFeatureFlag(cssModulesFlag) return ( - {children} - + ) }) +const StyledTableTitle = toggleStyledComponent( + cssModulesFlag, + 'h2', + styled.h2` + color: var(--fgColor-default); + font-size: var(--text-body-size-medium); + font-weight: var(--base-text-weight-semibold); + line-height: calc(20 / 14); + margin: 0; + `, +) + export type TableSubtitleProps = React.PropsWithChildren<{ /** * Provide an alternate element or component to use as the container for @@ -518,42 +615,67 @@ export type TableSubtitleProps = React.PropsWithChildren<{ }> function TableSubtitle({as, children, id}: TableSubtitleProps) { + const enabled = useFeatureFlag(cssModulesFlag) return ( - {children} - + ) } +const StyledTableSubtitle = toggleStyledComponent( + cssModulesFlag, + 'div', + styled.div` + color: var(--fgColor-default); + font-weight: var(--base-text-weight-normal); + font-size: var(--text-body-size-small); + line-height: var(--text-title-lineHeight-small); + margin: 0; + `, +) + function TableDivider() { + const enabled = useFeatureFlag(cssModulesFlag) return ( - ) } +const StyledTableDivider = toggleStyledComponent( + cssModulesFlag, + 'div', + styled.div` + background-color: var(--borderColor-default); + width: 100%; + height: 1px; + `, +) + export type TableActionsProps = React.PropsWithChildren function TableActions({children}: TableActionsProps) { - return
{children}
+ const enabled = useFeatureFlag(cssModulesFlag) + return ( +
+ {children} +
+ ) } // ---------------------------------------------------------------------------- @@ -580,6 +702,7 @@ export type TableSkeletonProps = React.ComponentPropsWit } function TableSkeleton({cellPadding, columns, rows = 10, ...rest}: TableSkeletonProps) { + const enabled = useFeatureFlag(cssModulesFlag) const {gridTemplateColumns} = useTableLayout(columns) return ( @@ -600,12 +723,26 @@ function TableSkeleton({cellPadding, columns, rows = 10, {Array.from({length: columns.length}).map((_, i) => { return ( - + Loading -
+
{Array.from({length: rows}).map((_, i) => { return ( -
+
) @@ -620,32 +757,6 @@ function TableSkeleton({cellPadding, columns, rows = 10, ) } -// ---------------------------------------------------------------------------- -// Utilities -// ---------------------------------------------------------------------------- - -// Button "reset" component that provides an unstyled