Skip to content
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

chore: add decorator in dataTable #18114

Open
wants to merge 21 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
7a4f19d
chore: add decorator in dataTable
preetibansalui Nov 19, 2024
e5ed412
Merge branch 'main' into 18005-add-decorator-in-dataTable
preetibansalui Nov 21, 2024
7dd3da9
fix: replace slug with ai-lable
preetibansalui Nov 25, 2024
05f0a99
fix: test cases
preetibansalui Nov 25, 2024
e2515e0
Merge branch 'main' into 18005-add-decorator-in-dataTable
preetibansalui Nov 29, 2024
fbe8f25
fix: test case
preetibansalui Dec 1, 2024
aa7e98d
fix: test cases
preetibansalui Dec 2, 2024
9db81fc
Merge branch 'main' into 18005-add-decorator-in-dataTable
preetibansalui Dec 10, 2024
473e0ee
fix: changed const name as per PR suggestions
preetibansalui Dec 10, 2024
6b6179c
Merge branch 'main' into 18005-add-decorator-in-dataTable
tay1orjones Dec 10, 2024
9134a4b
Merge branch 'main' into 18005-add-decorator-in-dataTable
preetibansalui Dec 11, 2024
fd9b843
fix: css issues
preetibansalui Dec 16, 2024
703ab52
fix: css
preetibansalui Dec 16, 2024
4fa7717
fix: test
preetibansalui Dec 16, 2024
3ae6ca9
Merge branch 'main' into 18005-add-decorator-in-dataTable
preetibansalui Dec 16, 2024
d4b9d88
Merge branch 'main' into 18005-add-decorator-in-dataTable
preetibansalui Dec 17, 2024
3a37225
Merge branch 'main' into 18005-add-decorator-in-dataTable
preetibansalui Dec 23, 2024
a646c18
fix: removed decorator stories
preetibansalui Dec 23, 2024
ea1c8c7
fix: test
preetibansalui Dec 24, 2024
adb1186
Merge branch 'main' into 18005-add-decorator-in-dataTable
preetibansalui Dec 24, 2024
ff2e40c
fix: test
preetibansalui Dec 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1973,6 +1973,17 @@ Map {
},
},
},
"TableDecoratorRow": Object {
"displayName": "TableDecoratorRow",
"propTypes": Object {
"className": Object {
"type": "string",
},
"decorator": Object {
"type": "node",
},
},
},
"TableExpandHeader": Object {
"propTypes": Object {
"aria-controls": Object {
Expand Down Expand Up @@ -8003,6 +8014,17 @@ Map {
},
},
},
"TableDecoratorRow" => Object {
"displayName": "TableDecoratorRow",
"propTypes": Object {
"className": Object {
"type": "string",
},
"decorator": Object {
"type": "node",
},
},
},
"TableExpandHeader" => Object {
"propTypes": Object {
"aria-controls": Object {
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/__tests__/index-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ describe('Carbon Components React', () => {
"TableBody",
"TableCell",
"TableContainer",
"TableDecoratorRow",
"TableExpandHeader",
"TableExpandRow",
"TableExpandedRow",
Expand Down
7 changes: 7 additions & 0 deletions packages/react/src/components/DataTable/DataTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import TableBatchActions from './TableBatchActions';
import TableBody from './TableBody';
import TableCell from './TableCell';
import TableContainer from './TableContainer';
import TableDecoratorRow from './TableDecoratorRow';
import TableExpandHeader from './TableExpandHeader';
import TableExpandRow from './TableExpandRow';
import TableExpandedRow from './TableExpandedRow';
Expand Down Expand Up @@ -99,6 +100,7 @@ export interface DataTableHeader {
key: string;
header: React.ReactNode;
slug?: React.ReactElement;
decorator?: React.ReactElement;
}

export interface DataTableRenderProps<RowType, ColTypes extends any[]> {
Expand Down Expand Up @@ -204,6 +206,7 @@ export interface DataTableRenderProps<RowType, ColTypes extends any[]> {
getCellProps: (getCellPropsArgs: { cell: DataTableCell<ColTypes> }) => {
[key: string]: unknown;
hasSlugHeader?: boolean;
hasDecoratorHeader?: boolean;
};

// Custom event handlers
Expand Down Expand Up @@ -390,6 +393,7 @@ class DataTable<RowType, ColTypes extends any[]> extends React.Component<
static TableBody: typeof TableBody;
static TableCell: typeof TableCell;
static TableContainer: typeof TableContainer;
static TableDecoratorRow: typeof TableDecoratorRow;
static TableExpandHeader: typeof TableExpandHeader;
static TableExpandRow: typeof TableExpandRow;
static TableExpandedRow: typeof TableExpandedRow;
Expand Down Expand Up @@ -473,6 +477,7 @@ class DataTable<RowType, ColTypes extends any[]> extends React.Component<
isSortable,
isSortHeader: sortHeaderKey === header.key,
slug: header.slug,
decorator: header.decorator,
onClick: (event) => {
const nextSortState = getNextSortState(this.props, this.state, {
key: header.key,
Expand Down Expand Up @@ -748,6 +753,7 @@ class DataTable<RowType, ColTypes extends any[]> extends React.Component<
return {
...rest,
hasSlugHeader: cell.hasSlugHeader,
hasDecoratorHeader: cell.hasDecoratorHeader,
};
};

Expand Down Expand Up @@ -1035,6 +1041,7 @@ DataTable.TableBatchActions = TableBatchActions;
DataTable.TableBody = TableBody;
DataTable.TableCell = TableCell;
DataTable.TableContainer = TableContainer;
DataTable.TableDecoratorRow = TableDecoratorRow;
DataTable.TableExpandHeader = TableExpandHeader;
DataTable.TableExpandRow = TableExpandRow;
DataTable.TableExpandedRow = TableExpandedRow;
Expand Down
68 changes: 68 additions & 0 deletions packages/react/src/components/DataTable/TableDecoratorRow.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**
* Copyright IBM Corp. 2016, 2023
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/

import PropTypes from 'prop-types';
import React, { ReactNode } from 'react';
import classNames from 'classnames';
import { usePrefix } from '../../internal/usePrefix';
import deprecate from '../../prop-types/deprecate';

export interface TableDecoratorRowProps {
/**
* The CSS class names of the cell that wraps the underlying input control
*/
className?: string;

/**
* **Experimental**: Provide a `decorator` component to be rendered inside the `TableDecoratorRow` component
*/
decorator?: ReactNode;
}

const TableDecoratorRow = ({
className,
decorator,
}: TableDecoratorRowProps) => {
const prefix = usePrefix();
const TableDecoratorRowClasses = classNames({

Check warning on line 31 in packages/react/src/components/DataTable/TableDecoratorRow.tsx

View check run for this annotation

Codecov / codecov/patch

packages/react/src/components/DataTable/TableDecoratorRow.tsx#L29-L31

Added lines #L29 - L31 were not covered by tests
...(className && { [className]: true }),
[`${prefix}--table-column-decorator`]: true,
[`${prefix}--table-column-decorator--active`]: decorator,
});

let normalizedDecorator = React.isValidElement(decorator)
? (decorator as ReactNode)
: null;

Check warning on line 39 in packages/react/src/components/DataTable/TableDecoratorRow.tsx

View check run for this annotation

Codecov / codecov/patch

packages/react/src/components/DataTable/TableDecoratorRow.tsx#L38-L39

Added lines #L38 - L39 were not covered by tests
if (
normalizedDecorator &&
normalizedDecorator['type']?.displayName === 'AILabel'

Check warning on line 42 in packages/react/src/components/DataTable/TableDecoratorRow.tsx

View check run for this annotation

Codecov / codecov/patch

packages/react/src/components/DataTable/TableDecoratorRow.tsx#L42

Added line #L42 was not covered by tests
) {
normalizedDecorator = React.cloneElement(

Check warning on line 44 in packages/react/src/components/DataTable/TableDecoratorRow.tsx

View check run for this annotation

Codecov / codecov/patch

packages/react/src/components/DataTable/TableDecoratorRow.tsx#L44

Added line #L44 was not covered by tests
normalizedDecorator as React.ReactElement<any>,
{
size: 'mini',
}
);
}

return <td className={TableDecoratorRowClasses}>{normalizedDecorator}</td>;

Check warning on line 52 in packages/react/src/components/DataTable/TableDecoratorRow.tsx

View check run for this annotation

Codecov / codecov/patch

packages/react/src/components/DataTable/TableDecoratorRow.tsx#L52

Added line #L52 was not covered by tests
};

TableDecoratorRow.displayName = 'TableDecoratorRow';
TableDecoratorRow.propTypes = {
/**
* The CSS class names of the cell that wraps the underlying input control
*/
className: PropTypes.string,

/**
* **Experimental**: Provide a `decorator` component to be rendered inside the `TableDecoratorRow` component
*/
decorator: PropTypes.node,
};

export default TableDecoratorRow;
27 changes: 18 additions & 9 deletions packages/react/src/components/DataTable/TableExpandRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,18 @@
) => {
const prefix = usePrefix();

// We need to put the slug before the expansion arrow and all other table cells after the arrow.
let rowHasSlug;
const slug = React.Children.toArray(children).map((child: any) => {
if (child.type?.displayName === 'TableSlugRow') {
if (child.props.slug) {
rowHasSlug = true;
// We need to put the AILabel and Decorator before the expansion arrow and all other table cells after the arrow.
let rowHasAILabel;
const decorator = React.Children.toArray(children).map((child: any) => {
if (
child.type?.displayName === 'TableSlugRow' ||
child.type?.displayName === 'TableDecoratorRow'
) {
if (
child.props.slug ||
child.props.decorator?.type.displayName === 'AILabel'

Check warning on line 85 in packages/react/src/components/DataTable/TableExpandRow.tsx

View check run for this annotation

Codecov / codecov/patch

packages/react/src/components/DataTable/TableExpandRow.tsx#L85

Added line #L85 was not covered by tests
) {
rowHasAILabel = true;

Check warning on line 87 in packages/react/src/components/DataTable/TableExpandRow.tsx

View check run for this annotation

Codecov / codecov/patch

packages/react/src/components/DataTable/TableExpandRow.tsx#L87

Added line #L87 was not covered by tests
}

return child;
Expand All @@ -87,7 +93,10 @@

const normalizedChildren = React.Children.toArray(children).map(
(child: any) => {
if (child.type?.displayName !== 'TableSlugRow') {
if (
child.type?.displayName !== 'TableSlugRow' &&
child.type?.displayName !== 'TableDecoratorRow'
) {
return child;
}
}
Expand All @@ -98,15 +107,15 @@
[`${prefix}--parent-row`]: true,
[`${prefix}--expandable-row`]: isExpanded,
[`${prefix}--data-table--selected`]: isSelected,
[`${prefix}--data-table--slug-row`]: rowHasSlug,
[`${prefix}--data-table--ai-label-row`]: rowHasAILabel,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need both untill v12... people could be targetting these classes

Suggested change
[`${prefix}--data-table--ai-label-row`]: rowHasAILabel,
[`${prefix}--data-table--slug-row`]: slug && rowHasAILabel,
[`${prefix}--data-table--ai-label-row`]: rowHasAILabel,

Copy link
Contributor Author

@preetibansalui preetibansalui Dec 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey Ari, here Slug is just a constant name which I have changed to decorator in line no 78 of this file and added condition for both Slug or decorator. However, yes we can add both the classes [${prefix}--data-table--slug-row] and [${prefix}--data-table--ai-label-row] on same condition keeping in mind if any user is using the [${prefix}--data-table--slug-row] class name.

},
rowClassName
);
const previousValue = isExpanded ? 'collapsed' : undefined;

return (
<tr {...rest} ref={ref as never} className={className} data-parent-row>
{slug}
{decorator}
preetibansalui marked this conversation as resolved.
Show resolved Hide resolved
<TableCell
className={`${prefix}--table-expand`}
data-previous-value={previousValue}
Expand Down
56 changes: 42 additions & 14 deletions packages/react/src/components/DataTable/TableHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,16 @@
scope?: string;

/**
* **Experimental**: Provide a `Slug` component to be rendered inside the `TableSlugRow` component
* @deprecated please use decorator instead.
* Provide a `Slug` component to be rendered inside the `TableSlugRow` component
*/
slug?: ReactNode;

/**
* **Experimental**: Provide a `decorator` component to be rendered inside the `TableDecoratorRow` component
*/
decorator?: ReactNode;

/**
* Specify which direction we are currently sorting by, should be one of DESC,
* NONE, or ASC.
Expand All @@ -130,6 +136,7 @@
className: headerClassName,
children,
colSpan,
decorator,
isSortable = false,
isSortHeader,
onClick,
Expand All @@ -145,19 +152,31 @@
const prefix = usePrefix();
const uniqueId = useId('table-sort');

// Slug is always size `mini`
const slugRef = useRef<HTMLInputElement>(null);
let normalizedSlug;
if (slug) {
normalizedSlug = React.cloneElement(slug as React.ReactElement<any>, {
size: 'mini',
ref: slugRef,
});
// AILabel is always size `mini`
const AILableRef = useRef<HTMLInputElement>(null);

let colHasAILabel;
let normalizedDecorator = React.isValidElement(slug ?? decorator)
? (slug ?? decorator)
: null;
if (
normalizedDecorator &&
normalizedDecorator['type']?.displayName === 'AILabel'

Check warning on line 164 in packages/react/src/components/DataTable/TableHeader.tsx

View check run for this annotation

Codecov / codecov/patch

packages/react/src/components/DataTable/TableHeader.tsx#L164

Added line #L164 was not covered by tests
) {
colHasAILabel = true;
normalizedDecorator = React.cloneElement(

Check warning on line 167 in packages/react/src/components/DataTable/TableHeader.tsx

View check run for this annotation

Codecov / codecov/patch

packages/react/src/components/DataTable/TableHeader.tsx#L166-L167

Added lines #L166 - L167 were not covered by tests
normalizedDecorator as React.ReactElement<any>,
{
size: 'mini',
ref: AILableRef,
}
);
}

const headerLabelClassNames = classNames({
[`${prefix}--table-header-label`]: true,
[`${prefix}--table-header-label--slug`]: slug,
[`${prefix}--table-header-label--ai-label`]: colHasAILabel,
preetibansalui marked this conversation as resolved.
Show resolved Hide resolved
[`${prefix}--table-header-label--decorator`]: decorator,
});

if (!isSortable) {
Expand All @@ -172,7 +191,9 @@
{children ? (
<div className={headerLabelClassNames}>
{children}
{normalizedSlug}
<div className={`${prefix}--table-header-label--decorator-inner`}>
{normalizedDecorator}
</div>
</div>
) : null}
</th>
Expand All @@ -198,11 +219,16 @@
});

const headerClasses = cx(headerClassName, `${prefix}--table-sort__header`, {
[`${prefix}--table-sort__header--slug`]: slug,
[`${prefix}--table-sort__header--ai-label`]: colHasAILabel,
[`${prefix}--table-sort__header--decorator`]: decorator,
});

const handleClick = (evt) => {
if (slug && slugRef.current && slugRef.current.contains(evt.target)) {
if (
colHasAILabel &&
AILableRef.current &&
AILableRef.current.contains(evt.target)

Check warning on line 230 in packages/react/src/components/DataTable/TableHeader.tsx

View check run for this annotation

Codecov / codecov/patch

packages/react/src/components/DataTable/TableHeader.tsx#L229-L230

Added lines #L229 - L230 were not covered by tests
) {
return;
} else if (onClick) {
return onClick(evt);
Expand Down Expand Up @@ -233,7 +259,9 @@
size={20}
className={`${prefix}--table-sort__icon-unsorted`}
/>
{normalizedSlug}
<div className={`${prefix}--table-header-label--decorator-inner`}>
{normalizedDecorator}
</div>
</span>
</button>
</th>
Expand Down
16 changes: 11 additions & 5 deletions packages/react/src/components/DataTable/TableRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,18 @@
const TableRow = (props: TableRowProps) => {
const prefix = usePrefix();

let rowHasSlug;
let rowHasAILabel;
if (props?.children) {
React.Children.toArray(props.children).map((child: any) => {
if (child.type?.displayName === 'TableSlugRow') {
if (child.props.slug) {
rowHasSlug = true;
if (
child.type?.displayName === 'TableSlugRow' ||
child.type?.displayName === 'TableDecoratorRow'
) {
if (
child.props.slug ||
child.props.decorator?.type.displayName === 'AILabel'

Check warning on line 38 in packages/react/src/components/DataTable/TableRow.tsx

View check run for this annotation

Codecov / codecov/patch

packages/react/src/components/DataTable/TableRow.tsx#L38

Added line #L38 was not covered by tests
) {
rowHasAILabel = true;

Check warning on line 40 in packages/react/src/components/DataTable/TableRow.tsx

View check run for this annotation

Codecov / codecov/patch

packages/react/src/components/DataTable/TableRow.tsx#L40

Added line #L40 was not covered by tests
}
}
});
Expand All @@ -40,7 +46,7 @@
// only useful in `TableExpandRow`
const className = cx(props.className, {
[`${prefix}--data-table--selected`]: props.isSelected,
[`${prefix}--data-table--slug-row`]: rowHasSlug,
[`${prefix}--data-table--ai-label-row`]: rowHasAILabel,
preetibansalui marked this conversation as resolved.
Show resolved Hide resolved
});

const cleanProps = {
Expand Down
10 changes: 9 additions & 1 deletion packages/react/src/components/DataTable/TableSlugRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
*/

import PropTypes from 'prop-types';
import React, { ReactNode } from 'react';
import React, { ReactNode, useEffect } from 'react';
import classNames from 'classnames';
import { usePrefix } from '../../internal/usePrefix';
import deprecateComponent from '../../prop-types/deprecateComponent';

export interface TableSlugRowProps {
/**
Expand All @@ -23,6 +24,13 @@
}

const TableSlugRow = ({ className, slug }: TableSlugRowProps) => {
useEffect(() => {
deprecateComponent(

Check warning on line 28 in packages/react/src/components/DataTable/TableSlugRow.tsx

View check run for this annotation

Codecov / codecov/patch

packages/react/src/components/DataTable/TableSlugRow.tsx#L27-L28

Added lines #L27 - L28 were not covered by tests
'TableSlugRow',
'The `TableSlugRow` component has been deprecated and will be removed in the next major version. Use the TableDecoratorRow component instead.'
);
}, []);

const prefix = usePrefix();
const TableSlugRowClasses = classNames({
...(className && { [className]: true }),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ describe('Table', () => {
<Table experimentalAutoAlign>
<TableHead>
<TableRow>
<TableHeader>Header1</TableHeader>
<TableHeader isSortable={true}>Header1</TableHeader>
</TableRow>
</TableHead>
<TableBody>
Expand Down
Loading
Loading