-
Notifications
You must be signed in to change notification settings - Fork 486
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(@clayui/core): adds the implementation of the new data-oriented composition for Table #5679
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
/** | ||
* SPDX-FileCopyrightText: © 2023 Liferay, Inc. <https://liferay.com> | ||
* SPDX-License-Identifier: BSD-3-Clause | ||
*/ | ||
|
||
import React from 'react'; | ||
|
||
import {ChildrenFunction, Collection} from '../collection'; | ||
import {Scope, ScopeContext} from './ScopeContext'; | ||
|
||
type Props<T> = { | ||
/** | ||
* Children content to render a dynamic or static content. | ||
*/ | ||
children: React.ReactNode | ChildrenFunction<T, unknown>; | ||
|
||
/** | ||
* Property to render content with dynamic data. | ||
*/ | ||
items?: Array<T>; | ||
} & React.TableHTMLAttributes<HTMLTableSectionElement>; | ||
|
||
function BodyInner<T extends Record<string, any>>( | ||
{children, items, ...otherProps}: Props<T>, | ||
ref: React.Ref<HTMLTableSectionElement> | ||
) { | ||
return ( | ||
<tbody {...otherProps} ref={ref}> | ||
<ScopeContext.Provider value={Scope.Body}> | ||
<Collection items={items} passthroughKey={false}> | ||
{children} | ||
</Collection> | ||
</ScopeContext.Provider> | ||
</tbody> | ||
); | ||
} | ||
|
||
type ForwardRef = { | ||
displayName: string; | ||
<T>( | ||
props: Props<T> & {ref?: React.Ref<HTMLTableSectionElement>} | ||
): JSX.Element; | ||
}; | ||
|
||
export const Body = React.forwardRef(BodyInner) as ForwardRef; | ||
|
||
Body.displayName = 'TableBody'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
/** | ||
* SPDX-FileCopyrightText: © 2023 Liferay, Inc. <https://liferay.com> | ||
* SPDX-License-Identifier: BSD-3-Clause | ||
*/ | ||
|
||
import classNames from 'classnames'; | ||
import React from 'react'; | ||
|
||
import {Scope, useScope} from './ScopeContext'; | ||
|
||
type Props = { | ||
/** | ||
* Aligns the text inside the Cell. | ||
*/ | ||
align?: 'center' | 'left' | 'right'; | ||
|
||
/** | ||
* Children content to render content. | ||
*/ | ||
children: React.ReactNode; | ||
|
||
/** | ||
* Sometimes we are unable to remove specific table columns from the DOM | ||
* and need to hide it using CSS. This property can be added to the "new" | ||
* first or last cell to maintain table styles on the left and right side. | ||
*/ | ||
delimiter?: 'start' | 'end'; | ||
|
||
/** | ||
* Fills out the remaining space inside a Cell. | ||
*/ | ||
expanded?: boolean; | ||
|
||
/** | ||
* Aligns horizontally contents inside the Cell. | ||
*/ | ||
textAlign?: 'center' | 'end' | 'start'; | ||
|
||
/** | ||
* Truncates the text inside a Cell. | ||
*/ | ||
truncate?: boolean; | ||
|
||
/* | ||
* Break the text into lines when necessary. | ||
*/ | ||
wrap?: boolean; | ||
} & React.ThHTMLAttributes<HTMLTableCellElement> & | ||
React.TdHTMLAttributes<HTMLTableCellElement>; | ||
|
||
export const Column = React.forwardRef<HTMLTableCellElement, Props>( | ||
function ColumnInner( | ||
{ | ||
align, | ||
children, | ||
className, | ||
delimiter, | ||
expanded, | ||
textAlign, | ||
truncate, | ||
wrap = true, | ||
...otherProps | ||
}, | ||
ref | ||
) { | ||
const scope = useScope(); | ||
const As = scope === Scope.Head ? 'th' : 'td'; | ||
|
||
return ( | ||
<As | ||
{...otherProps} | ||
className={classNames(className, { | ||
'table-cell-expand': truncate || expanded, | ||
[`table-cell-${delimiter}`]: delimiter, | ||
[`table-column-text-${textAlign}`]: textAlign, | ||
[`text-${align}`]: align, | ||
'table-cell-ws-nowrap': !wrap, | ||
})} | ||
ref={ref} | ||
> | ||
{truncate ? ( | ||
<span className="text-truncate-inline"> | ||
<span className="text-truncate">{children}</span> | ||
</span> | ||
) : ( | ||
children | ||
)} | ||
</As> | ||
); | ||
} | ||
); | ||
|
||
Column.displayName = 'Item'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/** | ||
* SPDX-FileCopyrightText: © 2023 Liferay, Inc. <https://liferay.com> | ||
* SPDX-License-Identifier: BSD-3-Clause | ||
*/ | ||
|
||
import React from 'react'; | ||
|
||
import {ChildrenFunction, Collection} from '../collection'; | ||
import {Scope, ScopeContext} from './ScopeContext'; | ||
|
||
type Props<T> = { | ||
/** | ||
* Children content to render a dynamic or static content. | ||
*/ | ||
children: React.ReactNode | ChildrenFunction<T, unknown>; | ||
|
||
/** | ||
* Property to render content with dynamic data. | ||
*/ | ||
items?: Array<T>; | ||
} & React.TableHTMLAttributes<HTMLTableSectionElement>; | ||
|
||
function HeadInner<T extends Record<string, any>>( | ||
{children, items, ...otherProps}: Props<T>, | ||
ref: React.Ref<HTMLTableSectionElement> | ||
) { | ||
return ( | ||
<thead {...otherProps} ref={ref}> | ||
<ScopeContext.Provider value={Scope.Head}> | ||
<tr> | ||
<Collection items={items} passthroughKey={false}> | ||
{children} | ||
</Collection> | ||
</tr> | ||
</ScopeContext.Provider> | ||
</thead> | ||
); | ||
} | ||
|
||
type ForwardRef = { | ||
displayName: string; | ||
<T>( | ||
props: Props<T> & {ref?: React.Ref<HTMLTableSectionElement>} | ||
): JSX.Element; | ||
}; | ||
|
||
export const Head = React.forwardRef(HeadInner) as ForwardRef; | ||
|
||
Head.displayName = 'TableHead'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/** | ||
* SPDX-FileCopyrightText: © 2023 Liferay, Inc. <https://liferay.com> | ||
* SPDX-License-Identifier: BSD-3-Clause | ||
*/ | ||
|
||
import classNames from 'classnames'; | ||
import React from 'react'; | ||
|
||
import {ChildrenFunction, Collection} from '../collection'; | ||
|
||
type Props<T> = { | ||
/** | ||
* Children content to render a dynamic or static content. | ||
*/ | ||
children: React.ReactNode | ChildrenFunction<T, unknown>; | ||
|
||
/** | ||
* This property can be added to the "new" first | ||
* or last ClayTable.Row to maintain table styles on the top and bottom sides. | ||
*/ | ||
delimiter?: 'start' | 'end'; | ||
|
||
/** | ||
* Applies a divider style inside the row. | ||
*/ | ||
divider?: boolean; | ||
|
||
/** | ||
* Property to render content with dynamic data. | ||
*/ | ||
items?: Array<T>; | ||
} & React.HTMLAttributes<HTMLTableRowElement>; | ||
|
||
function RowInner<T extends Record<string, any>>( | ||
{children, className, delimiter, divider, items, ...otherProps}: Props<T>, | ||
ref: React.Ref<HTMLTableRowElement> | ||
) { | ||
return ( | ||
<tr | ||
{...otherProps} | ||
className={classNames(className, { | ||
'table-divider': divider, | ||
[`table-row-${delimiter}`]: delimiter, | ||
})} | ||
ref={ref} | ||
> | ||
<Collection items={items} passthroughKey={false}> | ||
{children} | ||
</Collection> | ||
</tr> | ||
); | ||
} | ||
|
||
type ForwardRef = { | ||
displayName: string; | ||
<T>(props: Props<T> & {ref?: React.Ref<HTMLTableRowElement>}): JSX.Element; | ||
}; | ||
|
||
export const Row = React.forwardRef(RowInner) as ForwardRef; | ||
|
||
Row.displayName = 'TableRow'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
/** | ||
* SPDX-FileCopyrightText: © 2023 Liferay, Inc. <https://liferay.com> | ||
* SPDX-License-Identifier: BSD-3-Clause | ||
*/ | ||
|
||
import React, {useContext} from 'react'; | ||
|
||
export enum Scope { | ||
Head = 'head', | ||
Body = 'body', | ||
} | ||
|
||
export const ScopeContext = React.createContext<Scope>(Scope.Head); | ||
|
||
export function useScope() { | ||
return useContext(ScopeContext); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
/** | ||
* SPDX-FileCopyrightText: © 2023 Liferay, Inc. <https://liferay.com> | ||
* SPDX-License-Identifier: BSD-3-Clause | ||
*/ | ||
|
||
import RootTable from '@clayui/table'; | ||
|
||
export const Table = RootTable; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/** | ||
* SPDX-FileCopyrightText: © 2023 Liferay, Inc. <https://liferay.com> | ||
* SPDX-License-Identifier: BSD-3-Clause | ||
*/ | ||
|
||
export * from './Body'; | ||
export * from './Column'; | ||
export * from './Head'; | ||
export * from './Row'; | ||
export * from './Table'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
/** | ||
* SPDX-FileCopyrightText: © 2023 Liferay, Inc. <https://liferay.com> | ||
* SPDX-License-Identifier: BSD-3-Clause | ||
*/ | ||
|
||
import React from 'react'; | ||
|
||
import {Body, Column, Head, Row, Table} from '../src/table'; | ||
|
||
export default { | ||
title: 'Design System/Components/Table', | ||
}; | ||
|
||
const columns = [ | ||
{ | ||
id: '1', | ||
name: 'Name', | ||
}, | ||
{ | ||
id: '2', | ||
name: 'Type', | ||
}, | ||
]; | ||
|
||
const rows = [ | ||
{id: 1, name: 'Games', type: 'File folder'}, | ||
{id: 2, name: 'Program Files', type: 'File folder'}, | ||
]; | ||
|
||
export const Dynamic = () => { | ||
return ( | ||
<Table> | ||
<Head items={columns}> | ||
{(column) => <Column key={column.id}>{column.name}</Column>} | ||
</Head> | ||
|
||
<Body items={rows}> | ||
{(row) => ( | ||
<Row> | ||
<Column>{row.name}</Column> | ||
<Column>{row.type}</Column> | ||
</Row> | ||
)} | ||
</Body> | ||
</Table> | ||
); | ||
}; | ||
|
||
const columns2 = [ | ||
{ | ||
id: 'name', | ||
name: 'Name', | ||
}, | ||
{ | ||
id: 'type', | ||
name: 'Type', | ||
}, | ||
]; | ||
|
||
const rows2 = [ | ||
{id: 1, name: 'Games', type: 'File folder'}, | ||
{id: 2, name: 'Program Files', type: 'File folder'}, | ||
]; | ||
|
||
export const DynamicCells = () => { | ||
return ( | ||
<Table> | ||
<Head items={columns2}> | ||
{(column) => <Column key={column.id}>{column.name}</Column>} | ||
</Head> | ||
|
||
<Body items={rows2}> | ||
{(row) => ( | ||
<Row items={columns2}> | ||
{(column) => <Column>{row[column.id]}</Column>} | ||
</Row> | ||
)} | ||
</Body> | ||
</Table> | ||
); | ||
}; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason why we use 'Column' instead of 'Cell' as the name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In fact, there isn't much of a reason, just using a slightly more "popular/common" nomenclature.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @matuzalemsteles can you point me towards where you've seen
column
used? If we were to think about this like google sheets, this component renders a single cell such asA1
, right? In the context of google sheets a column would refer toA:A
or all the cells in a column.Checking a few other libraries, MaterialUI uses
TableCell
, NextUI usesTableColumn
only for cells in the header andTableCell
for cells in the body.Additionally, FDS uses
TableCell
andTableHeadCell
. Also, most of the classnames being applied to this component are prefixedtable-cell-*
.So what do you think, does
Cell
make more sense, or do you still see more reasons forColumn
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ethib137 These are good points, I hadn't thought about this side of Google Sheets. I really think that the case of Google sheets makes sense mainly because you deal with cells specifically although you call a column like
A
which groups several cells I would say that this is different for Table where sheets have the concept of cells much stronger because the cell can have a relationship between different cells, not necessarily related only to the specific column but can, for example, be diagonal and column is only used as a reference, which is different in a table where the cell has to be associated with a column to have context, which is not true in Google Sheets since the nature of the cell can have its own context and it is a more flexible term we can say like this.But yes, calling cells for body elements makes sense, I don't like it particularly because the cell seems to not necessarily be "associated" with a column directly... For example Column is also a common name for components not necessarily related to a table , for example a group of elements to be rendered horizontally or vertically. For example:
I don't really like the idea of creating a Column component to be used only in the Head and a Cell for only the body, I want to reduce the number of components for the composition and make the component more intelligent, which is also one of the reasons because I went with Column instead of just Cell for naming.
Anyway, we can go with Cell because we are already using this term in several places, so it will be simpler for current developers to associate this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good. Thanks @matuzalemsteles . Can you create a ticket for making this change?