diff --git a/.changeset/strong-pants-invite.md b/.changeset/strong-pants-invite.md new file mode 100644 index 0000000000..325d889086 --- /dev/null +++ b/.changeset/strong-pants-invite.md @@ -0,0 +1,5 @@ +--- +"@ultraviolet/icons": patch +--- + +Fix `sort` system icon to follow correct view box diff --git a/.changeset/twelve-chairs-film.md b/.changeset/twelve-chairs-film.md new file mode 100644 index 0000000000..cd6596f2f6 --- /dev/null +++ b/.changeset/twelve-chairs-film.md @@ -0,0 +1,12 @@ +--- +"@ultraviolet/ui": minor +--- + +Refactoring on ``: + - Update of sort icons + - Added `expandable` on `
` and `` + - Refactoring of grid system + - Added `align` and `sentiment` prop on `` + +Refactoring on ``: + - Update of sort icons diff --git a/packages/icons/src/components/Icon/__generatedIcons__/SortIcon.tsx b/packages/icons/src/components/Icon/__generatedIcons__/SortIcon.tsx index 42a0c97173..cca857df4d 100644 --- a/packages/icons/src/components/Icon/__generatedIcons__/SortIcon.tsx +++ b/packages/icons/src/components/Icon/__generatedIcons__/SortIcon.tsx @@ -11,8 +11,13 @@ export const SortIcon = ({ ...props }: Omit) => ( + ) diff --git a/packages/icons/src/components/Icon/assets/default/sort.svg b/packages/icons/src/components/Icon/assets/default/sort.svg index 1962b1bc25..c236d3a786 100644 --- a/packages/icons/src/components/Icon/assets/default/sort.svg +++ b/packages/icons/src/components/Icon/assets/default/sort.svg @@ -1,3 +1,3 @@ - - + + diff --git a/packages/icons/src/components/Icon/assets/small/sort.svg b/packages/icons/src/components/Icon/assets/small/sort.svg index 33743b68ba..00c9558c0a 100644 --- a/packages/icons/src/components/Icon/assets/small/sort.svg +++ b/packages/icons/src/components/Icon/assets/small/sort.svg @@ -1,3 +1,3 @@ - - + + diff --git a/packages/ui/src/components/List/HeaderCell.tsx b/packages/ui/src/components/List/HeaderCell.tsx index ad3dd7838e..2a2ba7afec 100644 --- a/packages/ui/src/components/List/HeaderCell.tsx +++ b/packages/ui/src/components/List/HeaderCell.tsx @@ -1,26 +1,25 @@ import styled from '@emotion/styled' -import { Icon } from '@ultraviolet/icons/legacy' +import { + InformationIcon, + SortIcon as SortIconUV, + SouthShortIcon, +} from '@ultraviolet/icons' import type { ReactNode } from 'react' -import { Stack } from '../Stack' import { Tooltip } from '../Tooltip' -const ArrowDownIcon = styled(Icon)`` -const ArrowUpIcon = styled(Icon)`` - -const StyledIconContainer = styled(Stack)` - color: ${({ theme }) => theme.colors.neutral.text}; - - &[aria-disabled='true'] { - cursor: not-allowed; - } +const StyledSortIcon = styled(SouthShortIcon, { + shouldForwardProp: prop => !['order'].includes(prop), +})<{ order: 'ascending' | 'descending' }>` + transform: ${({ order }) => (order === 'ascending' ? 'rotate(-180deg)' : 'none')}; + transition: transform 0.2s ease-in-out; ` -const SortIcon = () => ( - - - - -) +const SortIcon = ({ order }: { order?: 'ascending' | 'descending' }) => + order ? ( + + ) : ( + + ) const StyledHeaderCell = styled.div` display: flex; @@ -41,14 +40,6 @@ const StyledHeaderCell = styled.div` &[aria-sort] { color: ${({ theme }) => theme.colors.primary.text}; } - - &[aria-sort='ascending'] ${ArrowUpIcon} { - color: ${({ theme }) => theme.colors.primary.text}; - } - - &[aria-sort='descending'] ${ArrowDownIcon} { - color: ${({ theme }) => theme.colors.primary.text}; - } ` type HeaderCellProps = { @@ -103,16 +94,11 @@ export const HeaderCell = ({ {children} {info ? ( - + ) : null} {orderDirection !== undefined && isOrdered !== undefined ? ( - + ) : null} ) diff --git a/packages/ui/src/components/List/__tests__/__snapshots__/index.test.tsx.snap b/packages/ui/src/components/List/__tests__/__snapshots__/index.test.tsx.snap index 86420ff782..74e866248d 100644 --- a/packages/ui/src/components/List/__tests__/__snapshots__/index.test.tsx.snap +++ b/packages/ui/src/components/List/__tests__/__snapshots__/index.test.tsx.snap @@ -94,14 +94,6 @@ exports[`List > Should expand a row by pressing Space 1`] = ` color: #641cb3; } -.emotion-4[aria-sort='ascending'] .e1q5cnom2 { - color: #641cb3; -} - -.emotion-4[aria-sort='descending'] .e1q5cnom3 { - color: #641cb3; -} - .emotion-4 { display: -webkit-box; display: -webkit-flex; @@ -134,14 +126,6 @@ exports[`List > Should expand a row by pressing Space 1`] = ` color: #641cb3; } -.emotion-4[aria-sort='ascending'] .e1q5cnom2 { - color: #641cb3; -} - -.emotion-4[aria-sort='descending'] .e1q5cnom3 { - color: #641cb3; -} - .emotion-14 { display: -webkit-box; display: -webkit-flex; @@ -795,14 +779,6 @@ exports[`List > Should not collapse a row by clicking on expandable content 1`] color: #641cb3; } -.emotion-4[aria-sort='ascending'] .e1q5cnom2 { - color: #641cb3; -} - -.emotion-4[aria-sort='descending'] .e1q5cnom3 { - color: #641cb3; -} - .emotion-4 { display: -webkit-box; display: -webkit-flex; @@ -835,14 +811,6 @@ exports[`List > Should not collapse a row by clicking on expandable content 1`] color: #641cb3; } -.emotion-4[aria-sort='ascending'] .e1q5cnom2 { - color: #641cb3; -} - -.emotion-4[aria-sort='descending'] .e1q5cnom3 { - color: #641cb3; -} - .emotion-14 { display: -webkit-box; display: -webkit-flex; @@ -1483,14 +1451,6 @@ exports[`List > Should render correctly 1`] = ` color: #641cb3; } -.emotion-4[aria-sort='ascending'] .e1q5cnom2 { - color: #641cb3; -} - -.emotion-4[aria-sort='descending'] .e1q5cnom3 { - color: #641cb3; -} - .emotion-14 { display: -webkit-box; display: -webkit-flex; @@ -2075,14 +2035,6 @@ exports[`List > Should render correctly with bad sort value 1`] = ` color: #641cb3; } -.emotion-4[aria-sort='ascending'] .e1q5cnom2 { - color: #641cb3; -} - -.emotion-4[aria-sort='descending'] .e1q5cnom3 { - color: #641cb3; -} - .emotion-4 { display: -webkit-box; display: -webkit-flex; @@ -2115,14 +2067,6 @@ exports[`List > Should render correctly with bad sort value 1`] = ` color: #641cb3; } -.emotion-4[aria-sort='ascending'] .e1q5cnom2 { - color: #641cb3; -} - -.emotion-4[aria-sort='descending'] .e1q5cnom3 { - color: #641cb3; -} - .emotion-14 { display: -webkit-box; display: -webkit-flex; @@ -2745,14 +2689,6 @@ exports[`List > Should render correctly with disabled rows 1`] = ` color: #641cb3; } -.emotion-4[aria-sort='ascending'] .e1q5cnom2 { - color: #641cb3; -} - -.emotion-4[aria-sort='descending'] .e1q5cnom3 { - color: #641cb3; -} - .emotion-14 { display: -webkit-box; display: -webkit-flex; @@ -3317,14 +3253,6 @@ exports[`List > Should render correctly with expandable rows 1`] = ` color: #641cb3; } -.emotion-4[aria-sort='ascending'] .e1q5cnom2 { - color: #641cb3; -} - -.emotion-4[aria-sort='descending'] .e1q5cnom3 { - color: #641cb3; -} - .emotion-14 { display: -webkit-box; display: -webkit-flex; @@ -3919,14 +3847,6 @@ exports[`List > Should render correctly with info 1`] = ` color: #641cb3; } -.emotion-4[aria-sort='ascending'] .e1q5cnom2 { - color: #641cb3; -} - -.emotion-4[aria-sort='descending'] .e1q5cnom3 { - color: #641cb3; -} - .emotion-4 { display: -webkit-box; display: -webkit-flex; @@ -3959,14 +3879,6 @@ exports[`List > Should render correctly with info 1`] = ` color: #641cb3; } -.emotion-4[aria-sort='ascending'] .e1q5cnom2 { - color: #641cb3; -} - -.emotion-4[aria-sort='descending'] .e1q5cnom3 { - color: #641cb3; -} - .emotion-6 { display: inherit; } @@ -4150,7 +4062,6 @@ exports[`List > Should render correctly with info 1`] = ` Should render correctly with info 1`] = ` Should render correctly with info 1`] = ` Should render correctly with info 1`] = ` Should render correctly with info 1`] = ` Should render correctly with isExpandable and autoClose rows the color: #641cb3; } -.emotion-4[aria-sort='ascending'] .e1q5cnom2 { - color: #641cb3; -} - -.emotion-4[aria-sort='descending'] .e1q5cnom3 { - color: #641cb3; -} - .emotion-4 { display: -webkit-box; display: -webkit-flex; @@ -4771,14 +4670,6 @@ exports[`List > Should render correctly with isExpandable and autoClose rows the color: #641cb3; } -.emotion-4[aria-sort='ascending'] .e1q5cnom2 { - color: #641cb3; -} - -.emotion-4[aria-sort='descending'] .e1q5cnom3 { - color: #641cb3; -} - .emotion-14 { display: -webkit-box; display: -webkit-flex; @@ -5449,14 +5340,6 @@ exports[`List > Should render correctly with isExpandable rows then click 1`] = color: #641cb3; } -.emotion-4[aria-sort='ascending'] .e1q5cnom2 { - color: #641cb3; -} - -.emotion-4[aria-sort='descending'] .e1q5cnom3 { - color: #641cb3; -} - .emotion-4 { display: -webkit-box; display: -webkit-flex; @@ -5489,14 +5372,6 @@ exports[`List > Should render correctly with isExpandable rows then click 1`] = color: #641cb3; } -.emotion-4[aria-sort='ascending'] .e1q5cnom2 { - color: #641cb3; -} - -.emotion-4[aria-sort='descending'] .e1q5cnom3 { - color: #641cb3; -} - .emotion-14 { display: -webkit-box; display: -webkit-flex; @@ -6139,14 +6014,6 @@ exports[`List > Should render correctly with loading 1`] = ` color: #641cb3; } -.emotion-4[aria-sort='ascending'] .e1q5cnom2 { - color: #641cb3; -} - -.emotion-4[aria-sort='descending'] .e1q5cnom3 { - color: #641cb3; -} - .emotion-14 { display: -webkit-box; display: -webkit-flex; @@ -6850,14 +6717,6 @@ exports[`List > Should render correctly with loading with selectable 1`] = ` color: #641cb3; } -.emotion-4[aria-sort='ascending'] .e1q5cnom2 { - color: #641cb3; -} - -.emotion-4[aria-sort='descending'] .e1q5cnom3 { - color: #641cb3; -} - .emotion-6 { position: relative; display: -webkit-inline-box; @@ -7918,14 +7777,6 @@ exports[`List > Should render correctly with preventClick cell then click but ev color: #641cb3; } -.emotion-4[aria-sort='ascending'] .e1q5cnom2 { - color: #641cb3; -} - -.emotion-4[aria-sort='descending'] .e1q5cnom3 { - color: #641cb3; -} - .emotion-4 { display: -webkit-box; display: -webkit-flex; @@ -7958,14 +7809,6 @@ exports[`List > Should render correctly with preventClick cell then click but ev color: #641cb3; } -.emotion-4[aria-sort='ascending'] .e1q5cnom2 { - color: #641cb3; -} - -.emotion-4[aria-sort='descending'] .e1q5cnom3 { - color: #641cb3; -} - .emotion-14 { display: -webkit-box; display: -webkit-flex; @@ -8588,14 +8431,6 @@ exports[`List > Should render correctly with row expanded 1`] = ` color: #641cb3; } -.emotion-4[aria-sort='ascending'] .e1q5cnom2 { - color: #641cb3; -} - -.emotion-4[aria-sort='descending'] .e1q5cnom3 { - color: #641cb3; -} - .emotion-14 { display: -webkit-box; display: -webkit-flex; @@ -9150,14 +8985,6 @@ exports[`List > Should render correctly with selectable 1`] = ` color: #641cb3; } -.emotion-4[aria-sort='ascending'] .e1q5cnom2 { - color: #641cb3; -} - -.emotion-4[aria-sort='descending'] .e1q5cnom3 { - color: #641cb3; -} - .emotion-6 { position: relative; display: -webkit-inline-box; @@ -10690,14 +10517,6 @@ exports[`List > Should render correctly with selectable then click on first row color: #641cb3; } -.emotion-4[aria-sort='ascending'] .e1q5cnom2 { - color: #641cb3; -} - -.emotion-4[aria-sort='descending'] .e1q5cnom3 { - color: #641cb3; -} - .emotion-4 { display: -webkit-box; display: -webkit-flex; @@ -10730,14 +10549,6 @@ exports[`List > Should render correctly with selectable then click on first row color: #641cb3; } -.emotion-4[aria-sort='ascending'] .e1q5cnom2 { - color: #641cb3; -} - -.emotion-4[aria-sort='descending'] .e1q5cnom3 { - color: #641cb3; -} - .emotion-6 { position: relative; display: -webkit-inline-box; @@ -12589,14 +12400,6 @@ exports[`List > Should render correctly with sentiment rows 1`] = ` color: #641cb3; } -.emotion-4[aria-sort='ascending'] .e1q5cnom2 { - color: #641cb3; -} - -.emotion-4[aria-sort='descending'] .e1q5cnom3 { - color: #641cb3; -} - .emotion-14 { display: -webkit-box; display: -webkit-flex; @@ -13156,14 +12959,6 @@ exports[`List > Should render correctly with sort 1`] = ` color: #641cb3; } -.emotion-4[aria-sort='ascending'] .e1q5cnom2 { - color: #641cb3; -} - -.emotion-4[aria-sort='descending'] .e1q5cnom3 { - color: #641cb3; -} - .emotion-14 { display: -webkit-box; display: -webkit-flex; @@ -13748,14 +13543,6 @@ exports[`List > Should render correctly with sort then click 1`] = ` color: #641cb3; } -.emotion-4[aria-sort='ascending'] .emotion-8 { - color: #641cb3; -} - -.emotion-4[aria-sort='descending'] .emotion-11 { - color: #641cb3; -} - .emotion-4 { display: -webkit-box; display: -webkit-flex; @@ -13788,71 +13575,41 @@ exports[`List > Should render correctly with sort then click 1`] = ` color: #641cb3; } -.emotion-4[aria-sort='ascending'] .emotion-8 { - color: #641cb3; -} - -.emotion-4[aria-sort='descending'] .emotion-11 { - color: #641cb3; -} - .emotion-6 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - gap: 0; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-align-items: normal; - -webkit-box-align: normal; - -ms-flex-align: normal; - align-items: normal; - -webkit-box-pack: normal; - -ms-flex-pack: normal; - -webkit-justify-content: normal; - justify-content: normal; - -webkit-box-flex-wrap: nowrap; - -webkit-flex-wrap: nowrap; - -ms-flex-wrap: nowrap; - flex-wrap: nowrap; - color: #3f4250; -} - -.emotion-6[aria-disabled='true'] { - cursor: not-allowed; -} - -.emotion-9 { vertical-align: middle; - fill: currentColor; - height: 10px; - width: 10px; - min-width: 10px; - min-height: 10px; + fill: #3f4250; + height: 1em; + width: 1em; + min-width: 1em; + min-height: 1em; } -.emotion-9 .fillStroke { - stroke: currentColor; +.emotion-6 .fillStroke { + stroke: #3f4250; fill: none; } -.emotion-12 { +.emotion-11 { vertical-align: middle; - fill: currentColor; - height: 10px; - width: 10px; - min-width: 10px; - min-height: 10px; -} - -.emotion-12 .fillStroke { - stroke: currentColor; + fill: #641cb3; + height: 1em; + width: 1em; + min-width: 1em; + min-height: 1em; + -webkit-transform: rotate(-180deg); + -moz-transform: rotate(-180deg); + -ms-transform: rotate(-180deg); + transform: rotate(-180deg); + -webkit-transition: -webkit-transform 0.2s ease-in-out; + transition: transform 0.2s ease-in-out; +} + +.emotion-11 .fillStroke { + stroke: #641cb3; fill: none; } -.emotion-54 { +.emotion-25 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -13863,7 +13620,7 @@ exports[`List > Should render correctly with sort then click 1`] = ` gap: 16px; } -.emotion-54 { +.emotion-25 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -13874,7 +13631,7 @@ exports[`List > Should render correctly with sort then click 1`] = ` gap: 16px; } -.emotion-56 { +.emotion-27 { position: relative; border: 1px solid #d9dadd; border-radius: 4px; @@ -13891,32 +13648,32 @@ exports[`List > Should render correctly with sort then click 1`] = ` background-color: #ffffff; } -.emotion-56[role='button row'] { +.emotion-27[role='button row'] { cursor: pointer; } -.emotion-56 [data-expandable-content] { +.emotion-27 [data-expandable-content] { border-color: #d9dadd; } -.emotion-56:hover { +.emotion-27:hover { border-color: #8c40ef; box-shadow: 0px 4px 16px 4px #f6f3ffcc; } -.emotion-56[data-highlight='true'] { +.emotion-27[data-highlight='true'] { border-color: #8c40ef; box-shadow: 0px 4px 16px 4px #f6f3ffcc; } -.emotion-56[aria-disabled='true'] { +.emotion-27[aria-disabled='true'] { border: 1px solid #e9eaeb; background-color: #f3f3f4; color: #b5b7bd; cursor: not-allowed; } -.emotion-56 { +.emotion-27 { position: relative; border: 1px solid #d9dadd; border-radius: 4px; @@ -13933,32 +13690,32 @@ exports[`List > Should render correctly with sort then click 1`] = ` background-color: #ffffff; } -.emotion-56[role='button row'] { +.emotion-27[role='button row'] { cursor: pointer; } -.emotion-56 [data-expandable-content] { +.emotion-27 [data-expandable-content] { border-color: #d9dadd; } -.emotion-56:hover { +.emotion-27:hover { border-color: #8c40ef; box-shadow: 0px 4px 16px 4px #f6f3ffcc; } -.emotion-56[data-highlight='true'] { +.emotion-27[data-highlight='true'] { border-color: #8c40ef; box-shadow: 0px 4px 16px 4px #f6f3ffcc; } -.emotion-56[aria-disabled='true'] { +.emotion-27[aria-disabled='true'] { border: 1px solid #e9eaeb; background-color: #f3f3f4; color: #b5b7bd; cursor: not-allowed; } -.emotion-58 { +.emotion-29 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -13973,7 +13730,7 @@ exports[`List > Should render correctly with sort then click 1`] = ` min-height: 60px; } -.emotion-58 { +.emotion-29 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -14006,32 +13763,21 @@ exports[`List > Should render correctly with sort then click 1`] = ` tabindex="0" > Column 1 -
- - - - - - -
+ + +
Should render correctly with sort then click 1`] = ` tabindex="0" > Column 2 -
- - - - - - -
+ +
Should render correctly with sort then click 1`] = ` tabindex="0" > Column 3 -
- - - - - - -
+ + +
Should render correctly with sort then click 1`] = ` tabindex="0" > Column 4 -
- - - - - - -
+ + +
Should render correctly with sort then click 1`] = ` tabindex="0" > Column 5 -
- - - - - - -
+ + +
Row 1 Column 1
Row 1 Column 2
Row 1 Column 3
Row 1 Column 4
Row 1 Column 5
Row 2 Column 1
Row 2 Column 2
Row 2 Column 3
Row 2 Column 4
Row 2 Column 5
Row 3 Column 1
Row 3 Column 2
Row 3 Column 3
Row 3 Column 4
Row 3 Column 5
Row 4 Column 1
Row 4 Column 2
Row 4 Column 3
Row 4 Column 4
Row 4 Column 5
Row 5 Column 1
Row 5 Column 2
Row 5 Column 3
Row 5 Column 4
Row 5 Column 5
Row 6 Column 1
Row 6 Column 2
Row 6 Column 3
Row 6 Column 4
Row 6 Column 5
Row 7 Column 1
Row 7 Column 2
Row 7 Column 3
Row 7 Column 4
Row 7 Column 5
Row 8 Column 1
Row 8 Column 2
Row 8 Column 3
Row 8 Column 4
Row 8 Column 5
Row 9 Column 1
Row 9 Column 2
Row 9 Column 3
Row 9 Column 4
Row 9 Column 5
Row 10 Column 1
Row 10 Column 2
Row 10 Column 3
Row 10 Column 4
Row 10 Column 5 diff --git a/packages/ui/src/components/Table/Cell.tsx b/packages/ui/src/components/Table/Cell.tsx index 6027255375..ef240a1029 100644 --- a/packages/ui/src/components/Table/Cell.tsx +++ b/packages/ui/src/components/Table/Cell.tsx @@ -1,9 +1,20 @@ import styled from '@emotion/styled' import type { ReactNode } from 'react' +import { AlignementFlex } from './constants' -const StyledCell = styled('td')` +type Sentiment = 'success' | 'info' | 'warning' | 'danger' | 'neutral' + +type Align = 'left' | 'center' | 'right' + +const StyledCell = styled('td', { + shouldForwardProp: prop => !['sentiment', 'align'].includes(prop), +})<{ sentiment?: Sentiment; align: Align }>` + display: flex; + align-items: center; padding: ${({ theme }) => theme.space['1']}; font-size: 14px; + background-color: ${({ sentiment, theme }) => (sentiment ? theme.colors[sentiment].background : null)}; + justify-content: ${({ align }) => AlignementFlex[align]}; ` type CellProps = { @@ -11,10 +22,25 @@ type CellProps = { className?: string colSpan?: number rowSpan?: number + sentiment?: Sentiment + align?: Align } -export const Cell = ({ children, className, colSpan, rowSpan }: CellProps) => ( - +export const Cell = ({ + children, + className, + colSpan, + rowSpan, + sentiment, + align = 'left', +}: CellProps) => ( + {children} ) diff --git a/packages/ui/src/components/Table/HeaderCell.tsx b/packages/ui/src/components/Table/HeaderCell.tsx index 2f577ceccf..64c7939d51 100644 --- a/packages/ui/src/components/Table/HeaderCell.tsx +++ b/packages/ui/src/components/Table/HeaderCell.tsx @@ -1,52 +1,47 @@ import styled from '@emotion/styled' -import { Icon } from '@ultraviolet/icons/legacy' +import { + InformationIcon, + SortIcon as SortIconUV, + SouthShortIcon, +} from '@ultraviolet/icons' import type { ReactNode } from 'react' -import { Stack } from '../Stack' import { Text } from '../Text' import { Tooltip } from '../Tooltip' +import { AlignementFlex } from './constants' -const StyledIconContainer = styled(Stack)` - color: ${({ theme }) => theme.colors.neutral.textWeak}; - - &[aria-disabled='true'] { - cursor: not-allowed; - } - - &[role*='button'] { - cursor: pointer; - user-select: none; - } +const StyledSortIcon = styled(SouthShortIcon, { + shouldForwardProp: prop => !['order'].includes(prop), +})<{ order: 'ascending' | 'descending' }>` + transform: ${({ order }) => (order === 'ascending' ? 'rotate(-180deg)' : 'none')}; + transition: transform 0.2s; ` -const SortIcon = ({ order }: { order?: 'ascending' | 'descending' }) => ( - - - - -) +const SortIcon = ({ order }: { order?: 'ascending' | 'descending' }) => + order ? ( + + ) : ( + + ) type StyledHeaderCellProps = Pick< HeaderCellProps, 'width' | 'maxWidth' | 'minWidth' -> +> & { + align?: 'left' | 'center' | 'right' +} + const StyledHeaderCell = styled('th', { - shouldForwardProp: prop => !['width', 'maxWidth', 'minWidth'].includes(prop), + shouldForwardProp: prop => + !['align', 'width', 'maxWidth', 'minWidth'].includes(prop), })` - ${({ width, maxWidth, minWidth }) => ` +${({ width, maxWidth, minWidth }) => ` ${width ? `width: ${width};` : ''} ${maxWidth ? `max-width: ${maxWidth};` : ''} ${minWidth ? `min-width: ${minWidth};` : ''} `} + display: flex; + align-items: center; + justify-content: ${({ align }) => (align ? AlignementFlex[align] : null)}; padding: ${({ theme }) => theme.space['1']}; &[role*='button'] { @@ -68,10 +63,11 @@ type HeaderCellProps = { isOrdered?: boolean orderDirection?: 'asc' | 'desc' | 'none' onOrder?: (newOrder: 'asc' | 'desc') => void + info?: string + align?: 'left' | 'center' | 'right' width?: string - minWidth?: string maxWidth?: string - info?: string + minWidth?: string } export const HeaderCell = ({ @@ -80,10 +76,11 @@ export const HeaderCell = ({ isOrdered, onOrder, orderDirection, + info, + align, width, maxWidth, minWidth, - info, }: HeaderCellProps) => { let order: undefined | 'ascending' | 'descending' if (isOrdered && orderDirection === 'asc') { @@ -114,11 +111,12 @@ export const HeaderCell = ({ : undefined } role={onOrder ? 'button columnheader' : undefined} + tabIndex={handleOrder ? 0 : -1} + aria-sort={order} + align={align} width={width} maxWidth={maxWidth} minWidth={minWidth} - tabIndex={handleOrder ? 0 : -1} - aria-sort={order} > - ) : null} diff --git a/packages/ui/src/components/Table/HeaderRow.tsx b/packages/ui/src/components/Table/HeaderRow.tsx index 3fbc48e85a..5f7378727a 100644 --- a/packages/ui/src/components/Table/HeaderRow.tsx +++ b/packages/ui/src/components/Table/HeaderRow.tsx @@ -9,15 +9,20 @@ type HeaderRowProps = { } export const HeaderRow = ({ children, hasSelectAllColumn }: HeaderRowProps) => { - const { allRowSelectValue, selectAll, unselectAll, selectedRowIds } = - useTableContext() + const { + allRowSelectValue, + selectAll, + unselectAll, + selectedRowIds, + expandButton, + } = useTableContext() const selectableRowCount = Object.keys(selectedRowIds).length return ( -
+ {hasSelectAllColumn ? ( - + { /> ) : null} + {expandButton ? {null} : null} {children} ) diff --git a/packages/ui/src/components/Table/Row.tsx b/packages/ui/src/components/Table/Row.tsx index 68a7cbf068..29a1c6d881 100644 --- a/packages/ui/src/components/Table/Row.tsx +++ b/packages/ui/src/components/Table/Row.tsx @@ -2,14 +2,28 @@ import type { Theme } from '@emotion/react' import { keyframes } from '@emotion/react' import styled from '@emotion/styled' import type { ReactNode } from 'react' -import { useEffect } from 'react' +import { useCallback, useEffect } from 'react' +import { Button } from '../Button' import { Checkbox } from '../Checkbox' import { Tooltip } from '../Tooltip' import { Cell } from './Cell' import { useTableContext } from './TableContext' +import { SELECTABLE_CHECKBOX_SIZE } from './constants' + +const ExpandableWrapper = styled.div` + grid-column: 1 / -1; + grid-column-start: 1; + border-top: 1px solid ${({ theme }) => theme.colors.neutral.border}; + padding: ${({ theme }) => theme.space['1']}; + cursor: auto; + background: ${({ theme }) => theme.colors.neutral.backgroundWeak}; + border-radius: 0 0 ${({ theme }) => theme.radii.default} + ${({ theme }) => theme.radii.default}; +` const StyledCheckboxContainer = styled.div` display: flex; + width: ${SELECTABLE_CHECKBOX_SIZE}px; ` // We start at 5% and finish at 80% to leave the original background color @@ -33,6 +47,7 @@ const StyledTr = styled('tr', { type RowProps = { children: ReactNode + expandable?: ReactNode className?: string id: string 'data-testid'?: string @@ -41,6 +56,7 @@ type RowProps = { * */ selectDisabled?: boolean | string highlightAnimation?: boolean + expanded?: boolean } export const Row = ({ @@ -49,16 +65,34 @@ export const Row = ({ id, selectDisabled, highlightAnimation, + expandable, + expanded, 'data-testid': dataTestid, }: RowProps) => { const { selectable, + registerExpandableRow, + expandedRowIds, + expandRow, + collapseRow, registerSelectableRow, selectedRowIds, selectRow, unselectRow, + expandButton, } = useTableContext() + const hasExpandable = !!expandable + useEffect(() => { + if (hasExpandable) { + const unregisterCallback = registerExpandableRow(id, expanded) + + return unregisterCallback + } + + return undefined + }, [id, hasExpandable, registerExpandableRow, expanded, expandRow]) + useEffect(() => { if (!selectDisabled) { const unregisterCallback = registerSelectableRow(id) @@ -69,11 +103,22 @@ export const Row = ({ return undefined }, [id, registerSelectableRow, selectDisabled]) + const toggleRowExpand = useCallback(() => { + if (expandedRowIds[id]) { + collapseRow(id) + } else { + expandRow(id) + } + }, [collapseRow, expandRow, expandedRowIds, id]) + + const canClickRowToExpand = hasExpandable && !expandButton + return ( {selectable ? ( @@ -101,7 +146,42 @@ export const Row = ({ ) : null} + {expandButton ? ( + +
+) + +Align.args = { + columns: [ + columns[0], + { ...columns[1], width: '150px' }, + { ...columns[2], maxWidth: '20%' }, + { ...columns[3], minWidth: '150px', align: 'right' }, + ], + children: ( + + {data.map(movie => ( + + {movie.name} (auto) + {movie.releaseYear} (150px) + {movie.trilogy} (max 20%) + {movie.director} (min 150px) + + ))} + + ), +} + +Align.parameters = { + docs: { + description: { + story: + 'Using `align` prop on `columns` or on `` you can easily align the content as you need.', + }, + }, +} diff --git a/packages/ui/src/components/Table/__stories__/ColumnInfo.stories.tsx b/packages/ui/src/components/Table/__stories__/ColumnInfo.stories.tsx index 7576967225..9425aae5b8 100644 --- a/packages/ui/src/components/Table/__stories__/ColumnInfo.stories.tsx +++ b/packages/ui/src/components/Table/__stories__/ColumnInfo.stories.tsx @@ -9,7 +9,7 @@ export const ColumnInfo: StoryFn = ({ ...props }) => ( ColumnInfo.args = { columns: [ { label: 'Name', info: 'This column is important' }, - ...columns.slice(1, 3), + ...columns.slice(1, 4), ], children: ( diff --git a/packages/ui/src/components/Table/__stories__/Expandable.stories.tsx b/packages/ui/src/components/Table/__stories__/Expandable.stories.tsx new file mode 100644 index 0000000000..69aba54cae --- /dev/null +++ b/packages/ui/src/components/Table/__stories__/Expandable.stories.tsx @@ -0,0 +1,41 @@ +import { Table } from '..' +import { Text } from '../../Text' +import { Template } from './Template.stories' +import { data } from './resources' + +export const Expandable = Template.bind({}) + +Expandable.args = { + ...Template.args, + expandable: true, + selectable: true, + children: ( + + {data.map(movie => ( + + A movie to watch + + } + > + {movie.name} + {movie.releaseYear} + {movie.trilogy} + {movie.director} + + ))} + + ), +} + +Expandable.parameters = { + docs: { + description: { + story: + "A table can also be expandable. To do so set prop `expandable` on
to `true`. You can then pass any content in each ``'s `expandable` prop. This content will be displayed when the row is expanded.", + }, + }, +} diff --git a/packages/ui/src/components/Table/__stories__/Spanning.stories.tsx b/packages/ui/src/components/Table/__stories__/Spanning.stories.tsx index a57c6b7394..b6a037449e 100644 --- a/packages/ui/src/components/Table/__stories__/Spanning.stories.tsx +++ b/packages/ui/src/components/Table/__stories__/Spanning.stories.tsx @@ -1,20 +1,7 @@ -import styled from '@emotion/styled' import type { StoryFn } from '@storybook/react' import { Table } from '..' import { columns, data } from './resources' -const StyledTrilogyCell = styled(Table.Cell)` - background: ${({ theme }) => theme.colors.warning.background}; -` - -const StyledDirectorCell = styled(Table.Cell)` - background: ${({ theme }) => theme.colors.success.background}; -` - -const StyledStoryByCell = styled(Table.Cell)` - background: ${({ theme }) => theme.colors.info.background}; -` - export const Spanning: StoryFn = args => (
( {movie.name}{movie.releaseYear} {index % 3 === 0 ? ( - {movie.trilogy} + + {movie.trilogy} + ) : null} - {movie.director} - + {movie.director !== movie.storyBy ? ( - {movie.storyBy} + {movie.storyBy} ) : null} ))} diff --git a/packages/ui/src/components/Table/__stories__/Style.stories.tsx b/packages/ui/src/components/Table/__stories__/Style.stories.tsx index 4824f6ecef..403921b8ae 100644 --- a/packages/ui/src/components/Table/__stories__/Style.stories.tsx +++ b/packages/ui/src/components/Table/__stories__/Style.stories.tsx @@ -24,10 +24,19 @@ export const Style: StoryFn = args => ( columns={columns} bordered={combo.bordered} stripped={combo.stripped} + expandable > {data.slice(0, 3).map(movie => ( - + + A movie to watch + + } + > {movie.name} {movie.releaseYear} {movie.trilogy} diff --git a/packages/ui/src/components/Table/__stories__/WithMenu.stories.tsx b/packages/ui/src/components/Table/__stories__/WithMenu.stories.tsx index d7aa2a1099..38b367234a 100644 --- a/packages/ui/src/components/Table/__stories__/WithMenu.stories.tsx +++ b/packages/ui/src/components/Table/__stories__/WithMenu.stories.tsx @@ -11,8 +11,8 @@ export const WithMenu: StoryFn = ({ ...props }) => ( WithMenu.args = { columns: [ { label: 'Name', info: 'This column is important' }, - ...columns.slice(1, 3), - { label: '', width: '32px' }, + ...columns.slice(1, 4), + { label: '', width: '42px' }, ], children: ( diff --git a/packages/ui/src/components/Table/__stories__/index.stories.tsx b/packages/ui/src/components/Table/__stories__/index.stories.tsx index fe82b1a873..8a53222ecf 100644 --- a/packages/ui/src/components/Table/__stories__/index.stories.tsx +++ b/packages/ui/src/components/Table/__stories__/index.stories.tsx @@ -10,8 +10,10 @@ export default { export { Playground } from './Playground.stories' export { Ordering } from './Ordering.stories' export { Selectable } from './Selectable.stories' +export { Expandable } from './Expandable.stories' export { Style } from './Style.stories' export { ColumnWidth } from './ColumnWidth.stories' +export { Align } from './Align.stories' export { Spanning } from './Spanning.stories' export { Loading } from './Loading.stories' export { ColumnInfo } from './ColumnInfo.stories' diff --git a/packages/ui/src/components/Table/__tests__/__snapshots__/index.test.tsx.snap b/packages/ui/src/components/Table/__tests__/__snapshots__/index.test.tsx.snap index 608a07b78d..6edc9c0a34 100644 --- a/packages/ui/src/components/Table/__tests__/__snapshots__/index.test.tsx.snap +++ b/packages/ui/src/components/Table/__tests__/__snapshots__/index.test.tsx.snap @@ -8,6 +8,17 @@ exports[`Table > Should render correctly 1`] = ` border-collapse: collapse; } +.emotion-0 [role="row"], +.emotion-0 [role="button row"] { + display: grid; + width: 100%; + grid-template-columns: 100px 100px 100px 100px 100px; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + .emotion-2 { border-bottom: 1px solid #d9dadd; } @@ -16,6 +27,14 @@ exports[`Table > Should render correctly 1`] = ` width: 100px; max-width: 200px; min-width: 100px; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; } @@ -57,8 +76,20 @@ exports[`Table > Should render correctly 1`] = ` } .emotion-31 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; font-size: 14px; + -webkit-box-pack: start; + -ms-flex-pack: start; + -webkit-justify-content: start; + justify-content: start; }
Should render correctly 1`] = `
- + - + - + - + - + - + - + @@ -5176,6 +5622,17 @@ exports[`Table > Should render correctly with stipped 1`] = ` border-collapse: collapse; } +.emotion-0 [role="row"], +.emotion-0 [role="button row"] { + display: grid; + width: 100%; + grid-template-columns: 100px 100px 100px 100px 100px; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + .emotion-0 tbody tr:nth-of-type(even) { background: #f9f9fa; } @@ -5196,6 +5653,14 @@ exports[`Table > Should render correctly with stipped 1`] = ` width: 100px; max-width: 200px; min-width: 100px; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; } @@ -5211,6 +5676,14 @@ exports[`Table > Should render correctly with stipped 1`] = ` width: 100px; max-width: 200px; min-width: 100px; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; } @@ -5281,13 +5754,37 @@ exports[`Table > Should render correctly with stipped 1`] = ` } .emotion-31 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; font-size: 14px; + -webkit-box-pack: start; + -ms-flex-pack: start; + -webkit-justify-content: start; + justify-content: start; } .emotion-31 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; font-size: 14px; + -webkit-box-pack: start; + -ms-flex-pack: start; + -webkit-justify-content: start; + justify-content: start; }
Should render correctly with stipped 1`] = `
- +
Should render correctly 1`] = `
Should render correctly 1`] = `
Should render correctly 1`] = `
Should render correctly 1`] = `
Should render correctly 1`] = `
Should render correctly 1`] = `
Should render correctly 1`] = `
Should render correctly 1`] = `
Should render correctly 1`] = `
Should render correctly 1`] = `
Should render correctly with bad sort value 1`] = ` border-collapse: collapse; } +.emotion-0 [role="row"], +.emotion-0 [role="button row"] { + display: grid; + width: 100%; + grid-template-columns: 100px 100px 100px 100px 100px; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + .emotion-0 { width: 100%; box-sizing: content-box; border-collapse: collapse; } +.emotion-0 [role="row"], +.emotion-0 [role="button row"] { + display: grid; + width: 100%; + grid-template-columns: 100px 100px 100px 100px 100px; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + .emotion-2 { border-bottom: 1px solid #d9dadd; } @@ -446,6 +511,14 @@ exports[`Table > Should render correctly with bad sort value 1`] = ` width: 100px; max-width: 200px; min-width: 100px; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; } @@ -461,6 +534,14 @@ exports[`Table > Should render correctly with bad sort value 1`] = ` width: 100px; max-width: 200px; min-width: 100px; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; } @@ -531,13 +612,37 @@ exports[`Table > Should render correctly with bad sort value 1`] = ` } .emotion-31 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; font-size: 14px; + -webkit-box-pack: start; + -ms-flex-pack: start; + -webkit-justify-content: start; + justify-content: start; } .emotion-31 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; font-size: 14px; + -webkit-box-pack: start; + -ms-flex-pack: start; + -webkit-justify-content: start; + justify-content: start; }
Should render correctly with bad sort value 1`] = `
Should render correctly with bad sort value 1`] = `
Should render correctly with bad sort value 1`] = `
Should render correctly with bad sort value 1`] = `
Should render correctly with bad sort value 1`] = `
Should render correctly with bad sort value 1`] = `
Should render correctly with bad sort value 1`] = `
Should render correctly with bad sort value 1`] = `
Should render correctly with bad sort value 1`] = `
Should render correctly with bad sort value 1`] = `
Should render correctly with bad sort value 1`] = `
Should render correctly with highlight animation on Table.Row 1 border-collapse: collapse; } -.emotion-0 { +.emotion-0 [role="row"], +.emotion-0 [role="button row"] { + display: grid; width: 100%; - box-sizing: content-box; - border-collapse: collapse; + grid-template-columns: minmax(0, 1fr) 100px 100px; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; } .emotion-2 { @@ -932,6 +1054,34 @@ exports[`Table > Should render correctly with highlight animation on Table.Row 1 } .emotion-4 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + padding: 8px; +} + +.emotion-4[role*='button'] { + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.emotion-4 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; } @@ -1017,6 +1167,14 @@ exports[`Table > Should render correctly with highlight animation on Table.Row 1 width: 100px; max-width: 200px; min-width: 100px; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; } @@ -1032,6 +1190,14 @@ exports[`Table > Should render correctly with highlight animation on Table.Row 1 width: 100px; max-width: 200px; min-width: 100px; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; } @@ -1049,13 +1215,37 @@ exports[`Table > Should render correctly with highlight animation on Table.Row 1 } .emotion-25 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; font-size: 14px; + -webkit-box-pack: start; + -ms-flex-pack: start; + -webkit-justify-content: start; + justify-content: start; } .emotion-25 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; font-size: 14px; + -webkit-box-pack: start; + -ms-flex-pack: start; + -webkit-justify-content: start; + justify-content: start; }
Should render correctly with highlight animation on Table.Row 1
Should render correctly with highlight animation on Table.Row 1 Should render correctly with highlight animation on Table.Row 1
Should render correctly with highlight animation on Table.Row 1
Should render correctly with highlight animation on Table.Row 1
Should render correctly with highlight animation on Table.Row 1
Should render correctly with highlight animation on Table.Row 1
Should render correctly with highlight animation on Table.Row 1
Should render correctly with highlight animation on Table.Row 1
Should render correctly with highlight animation on Table.Row 1
Should render correctly with highlight animation on Table.Row 1
Should render correctly with highlight animation on Table.Row 1
Should render correctly with info 1`] = ` border-collapse: collapse; } +.emotion-0 [role="row"], +.emotion-0 [role="button row"] { + display: grid; + width: 100%; + grid-template-columns: minmax(0, 1fr) 100px 100px; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + .emotion-0 tbody tr:nth-of-type(even) { background: #f9f9fa; } @@ -1440,6 +1652,34 @@ exports[`Table > Should render correctly with info 1`] = ` } .emotion-4 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + padding: 8px; +} + +.emotion-4[role*='button'] { + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.emotion-4 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; } @@ -1525,6 +1765,14 @@ exports[`Table > Should render correctly with info 1`] = ` width: 100px; max-width: 200px; min-width: 100px; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; } @@ -1540,6 +1788,14 @@ exports[`Table > Should render correctly with info 1`] = ` width: 100px; max-width: 200px; min-width: 100px; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; } @@ -1562,13 +1818,37 @@ exports[`Table > Should render correctly with info 1`] = ` } .emotion-25 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; font-size: 14px; + -webkit-box-pack: start; + -ms-flex-pack: start; + -webkit-justify-content: start; + justify-content: start; } .emotion-25 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; font-size: 14px; + -webkit-box-pack: start; + -ms-flex-pack: start; + -webkit-justify-content: start; + justify-content: start; }
Should render correctly with info 1`] = `
Should render correctly with info 1`] = ` Should render correctly with info 1`] = `
Should render correctly with info 1`] = `
Should render correctly with info 1`] = `
Should render correctly with info 1`] = `
Should render correctly with info 1`] = `
Should render correctly with info 1`] = `
Should render correctly with info 1`] = `
Should render correctly with info 1`] = `
Should render correctly with info 1`] = `
Should render correctly with info 1`] = `
Should render correctly with loading 1`] = ` border-collapse: collapse; } +.emotion-0 [role="row"], +.emotion-0 [role="button row"] { + display: grid; + width: 100%; + grid-template-columns: 100px 100px 100px 100px 100px; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + .emotion-2 { border-bottom: 1px solid #d9dadd; } @@ -1954,6 +2256,14 @@ exports[`Table > Should render correctly with loading 1`] = ` width: 100px; max-width: 200px; min-width: 100px; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; } @@ -1994,8 +2304,20 @@ exports[`Table > Should render correctly with loading 1`] = ` } .emotion-31 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; font-size: 14px; + -webkit-box-pack: start; + -ms-flex-pack: start; + -webkit-justify-content: start; + justify-content: start; } .emotion-34 { @@ -2060,7 +2382,9 @@ exports[`Table > Should render correctly with loading 1`] = ` -
+
Should render correctly with selectDisabled as a string 1`] = ` border-collapse: collapse; } +.emotion-0 [role="row"], +.emotion-0 [role="button row"] { + display: grid; + width: 100%; + grid-template-columns: 100px 100px 100px 100px 100px; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + .emotion-0 { width: 100%; box-sizing: content-box; border-collapse: collapse; } +.emotion-0 [role="row"], +.emotion-0 [role="button row"] { + display: grid; + width: 100%; + grid-template-columns: 100px 100px 100px 100px 100px; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + .emotion-2 { border-bottom: 1px solid #d9dadd; } @@ -2576,6 +2922,14 @@ exports[`Table > Should render correctly with selectDisabled as a string 1`] = ` width: 100px; max-width: 200px; min-width: 100px; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; } @@ -2591,6 +2945,14 @@ exports[`Table > Should render correctly with selectDisabled as a string 1`] = ` width: 100px; max-width: 200px; min-width: 100px; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; } @@ -2661,13 +3023,37 @@ exports[`Table > Should render correctly with selectDisabled as a string 1`] = ` } .emotion-31 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; font-size: 14px; + -webkit-box-pack: start; + -ms-flex-pack: start; + -webkit-justify-content: start; + justify-content: start; } .emotion-31 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; font-size: 14px; + -webkit-box-pack: start; + -ms-flex-pack: start; + -webkit-justify-content: start; + justify-content: start; }
Should render correctly with selectDisabled as a string 1`] = `
Should render correctly with selectDisabled as a string 1`] = `
Should render correctly with selectDisabled as a string 1`] = `
Should render correctly with selectDisabled as a string 1`] = `
Should render correctly with selectDisabled as a string 1`] = `
Should render correctly with selectDisabled as a string 1`] = `
Should render correctly with selectDisabled as a string 1`] = `
Should render correctly with selectDisabled as a string 1`] = `
Should render correctly with selectDisabled as a string 1`] = `
Should render correctly with selectDisabled as a string 1`] = `
Should render correctly with selectDisabled as a string 1`] = `
Should render correctly with selectable then click on first row border-collapse: collapse; } -.emotion-0 { +.emotion-0 [role="row"], +.emotion-0 [role="button row"] { + display: grid; width: 100%; - box-sizing: content-box; - border-collapse: collapse; + grid-template-columns: 40px 100px 100px 100px 100px 100px; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; } .emotion-2 { @@ -3052,7 +3455,14 @@ exports[`Table > Should render correctly with selectable then click on first row } .emotion-4 { - width: 24px; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; } @@ -3390,6 +3800,14 @@ exports[`Table > Should render correctly with selectable then click on first row width: 100px; max-width: 200px; min-width: 100px; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; } @@ -3405,6 +3823,14 @@ exports[`Table > Should render correctly with selectable then click on first row width: 100px; max-width: 200px; min-width: 100px; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; } @@ -3427,13 +3853,37 @@ exports[`Table > Should render correctly with selectable then click on first row } .emotion-48 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; font-size: 14px; + -webkit-box-pack: start; + -ms-flex-pack: start; + -webkit-justify-content: start; + justify-content: start; } .emotion-48 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; font-size: 14px; + -webkit-box-pack: start; + -ms-flex-pack: start; + -webkit-justify-content: start; + justify-content: start; } .emotion-50 { @@ -3441,6 +3891,7 @@ exports[`Table > Should render correctly with selectable then click on first row display: -webkit-flex; display: -ms-flexbox; display: flex; + width: 40px; }
Should render correctly with selectable then click on first row
Should render correctly with selectable then click on first row
Should render correctly with selectable then click on first row
Should render correctly with selectable then click on first row
Should render correctly with selectable then click on first row
Should render correctly with selectable then click on first row
Should render correctly with selectable then click on first row
Should render correctly with selectable then click on first row
Should render correctly with selectable then click on first row
Should render correctly with selectable then click on first row
Should render correctly with selectable then click on first row
Should render correctly with sort then click 1`] = ` border-collapse: collapse; } +.emotion-0 [role="row"], +.emotion-0 [role="button row"] { + display: grid; + width: 100%; + grid-template-columns: 100px 100px 100px 100px 100px; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + .emotion-0 { width: 100%; box-sizing: content-box; border-collapse: collapse; } +.emotion-0 [role="row"], +.emotion-0 [role="button row"] { + display: grid; + width: 100%; + grid-template-columns: 100px 100px 100px 100px 100px; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + .emotion-2 { border-bottom: 1px solid #d9dadd; } @@ -4489,6 +4974,14 @@ exports[`Table > Should render correctly with sort then click 1`] = ` width: 100px; max-width: 200px; min-width: 100px; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; } @@ -4504,6 +4997,14 @@ exports[`Table > Should render correctly with sort then click 1`] = ` width: 100px; max-width: 200px; min-width: 100px; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; } @@ -4564,56 +5065,20 @@ exports[`Table > Should render correctly with sort then click 1`] = ` } .emotion-9 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - gap: 0; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-align-items: normal; - -webkit-box-align: normal; - -ms-flex-align: normal; - align-items: normal; - -webkit-box-pack: normal; - -ms-flex-pack: normal; - -webkit-justify-content: normal; - justify-content: normal; - -webkit-box-flex-wrap: nowrap; - -webkit-flex-wrap: nowrap; - -ms-flex-wrap: nowrap; - flex-wrap: nowrap; - color: #727683; -} - -.emotion-9[aria-disabled='true'] { - cursor: not-allowed; -} - -.emotion-9[role*='button'] { - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -.emotion-11 { vertical-align: middle; - fill: #727683; - height: 10px; - width: 10px; - min-width: 10px; - min-height: 10px; + fill: #3f4250; + height: 1em; + width: 1em; + min-width: 1em; + min-height: 1em; } -.emotion-11 .fillStroke { - stroke: #727683; +.emotion-9 .fillStroke { + stroke: #3f4250; fill: none; } -.emotion-18 { +.emotion-14 { color: #641cb3; font-size: 14px; font-family: Inter,Asap,sans-serif; @@ -4637,38 +5102,68 @@ exports[`Table > Should render correctly with sort then click 1`] = ` gap: 8px; } -.emotion-22 { +.emotion-17 { vertical-align: middle; - fill: #521094; - height: 10px; - width: 10px; - min-width: 10px; - min-height: 10px; -} - -.emotion-22 .fillStroke { - stroke: #521094; + fill: #641cb3; + height: 1em; + width: 1em; + min-width: 1em; + min-height: 1em; + -webkit-transform: rotate(-180deg); + -moz-transform: rotate(-180deg); + -ms-transform: rotate(-180deg); + transform: rotate(-180deg); + -webkit-transition: -webkit-transform 0.2s; + transition: transform 0.2s; +} + +.emotion-17 .fillStroke { + stroke: #641cb3; fill: none; } -.emotion-59 { +.emotion-40 { -webkit-animation: 3s linear; animation: 3s linear; } -.emotion-59 { +.emotion-40 { -webkit-animation: 3s linear; animation: 3s linear; } -.emotion-61 { +.emotion-42 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; font-size: 14px; + -webkit-box-pack: start; + -ms-flex-pack: start; + -webkit-justify-content: start; + justify-content: start; } -.emotion-61 { +.emotion-42 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; padding: 8px; font-size: 14px; + -webkit-box-pack: start; + -ms-flex-pack: start; + -webkit-justify-content: start; + justify-content: start; }
Should render correctly with sort then click 1`] = `
Should render correctly with sort then click 1`] = ` class="emotion-6 emotion-7 emotion-8" > Column 1 -
- - - - - - -
+ + +
Should render correctly with sort then click 1`] = ` tabindex="0" >
Column 2 -
- - - - - - -
+ +
Should render correctly with sort then click 1`] = ` class="emotion-6 emotion-7 emotion-8" > Column 3 -
- - - - - - -
+ + +
Should render correctly with sort then click 1`] = ` class="emotion-6 emotion-7 emotion-8" > Column 4 -
- - - - - - -
+ + +
Should render correctly with sort then click 1`] = ` class="emotion-6 emotion-7 emotion-8" > Column 5 -
- - - - - - -
+ + +
Row 1 Column 1 Row 1 Column 2 Row 1 Column 3 Row 1 Column 4 Row 1 Column 5
Row 2 Column 1 Row 2 Column 2 Row 2 Column 3 Row 2 Column 4 Row 2 Column 5
Row 3 Column 1 Row 3 Column 2 Row 3 Column 3 Row 3 Column 4 Row 3 Column 5
Row 4 Column 1 Row 4 Column 2 Row 4 Column 3 Row 4 Column 4 Row 4 Column 5
Row 5 Column 1 Row 5 Column 2 Row 5 Column 3 Row 5 Column 4 Row 5 Column 5
Row 6 Column 1 Row 6 Column 2 Row 6 Column 3 Row 6 Column 4 Row 6 Column 5
Row 7 Column 1 Row 7 Column 2 Row 7 Column 3 Row 7 Column 4 Row 7 Column 5
Row 8 Column 1 Row 8 Column 2 Row 8 Column 3 Row 8 Column 4 Row 8 Column 5
Row 9 Column 1 Row 9 Column 2 Row 9 Column 3 Row 9 Column 4 Row 9 Column 5
Row 10 Column 1 Row 10 Column 2 Row 10 Column 3 Row 10 Column 4 Row 10 Column 5
Should render correctly with stipped 1`] = `
Should render correctly with stipped 1`] = `
Should render correctly with stipped 1`] = `
Should render correctly with stipped 1`] = `
Should render correctly with stipped 1`] = `
Should render correctly with stipped 1`] = `
Should render correctly with stipped 1`] = `
Should render correctly with stipped 1`] = `
Should render correctly with stipped 1`] = `
Should render correctly with stipped 1`] = `
!['bordered', 'stripped'].includes(prop), + shouldForwardProp: prop => + !['bordered', 'stripped', 'template'].includes(prop), })` width: 100%; box-sizing: content-box; border-collapse: collapse; + [role="row"], + [role="button row"] { + display: grid; + width: 100%; + grid-template-columns: ${({ template }) => template}; + align-items: center; + } + ${({ theme, stripped, bordered }) => ` ${ stripped @@ -50,6 +61,7 @@ type ColumnProps = Pick< minWidth?: string maxWidth?: string info?: string + align?: 'left' | 'center' | 'right' } type TableProps = { @@ -62,59 +74,82 @@ type TableProps = { loading?: boolean bordered?: boolean stripped?: boolean + expandable?: boolean + /** + * Auto collapse is collapsing expandable row when another is expanding + * */ + autoCollapse?: boolean } export const BaseTable = forwardRef( ( { selectable = false, + expandable = false, children, columns, loading, bordered = false, stripped = false, + autoCollapse = false, }, ref, - ) => ( - - -
- - {columns.map((column, index) => ( - - {column.label} - - ))} - -
- {loading ? ( - - - - ) : ( - children - )} -
-
- ), + ) => { + const computeTemplate = `${ + selectable ? `${SELECTABLE_CHECKBOX_SIZE}px ` : '' + }${expandable ? `${EXPANDABLE_COLUMN_SIZE}px ` : ''}${columns + .map(({ width }) => width ?? 'minmax(0, 1fr)') + .join(' ')}` + + return ( + + +
+ + {columns.map((column, index) => ( + + {column.label} + + ))} + +
+ {loading ? ( + + + + ) : ( + children + )} +
+
+ ) + }, ) /**