Skip to content

Commit 4a26a50

Browse files
authored
feat(table): Wrap table components with forwardRef (#1239)
* feat(table): wrap table components with forwardRef * fix(table): use ComponentPropsWithRef instead of ComponentProps
1 parent ee3749f commit 4a26a50

File tree

6 files changed

+97
-91
lines changed

6 files changed

+97
-91
lines changed

src/components/Table/Table.tsx

Lines changed: 18 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client';
22

3-
import type { ComponentProps, FC } from 'react';
3+
import { forwardRef, type ComponentPropsWithRef } from 'react';
44
import { twMerge } from 'tailwind-merge';
55
import { mergeDeep } from '../../helpers/merge-deep';
66
import { getTheme } from '../../theme-store';
@@ -25,40 +25,30 @@ export interface FlowbiteTableRootTheme {
2525
wrapper: string;
2626
}
2727

28-
export interface TableProps extends ComponentProps<'table'> {
28+
export interface TableProps extends ComponentPropsWithRef<'table'> {
2929
striped?: boolean;
3030
hoverable?: boolean;
3131
theme?: DeepPartial<FlowbiteTableTheme>;
3232
}
3333

34-
const TableComponent: FC<TableProps> = ({
35-
children,
36-
className,
37-
striped,
38-
hoverable,
39-
theme: customTheme = {},
40-
...props
41-
}) => {
42-
const theme = mergeDeep(getTheme().table, customTheme);
43-
44-
return (
45-
<div data-testid="table-element" className={twMerge(theme.root.wrapper)}>
46-
<TableContext.Provider value={{ theme, striped, hoverable }}>
47-
<div className={twMerge(theme.root.shadow, className)}></div>
48-
<table className={twMerge(theme.root.base, className)} {...props}>
49-
{children}
50-
</table>
51-
</TableContext.Provider>
52-
</div>
53-
);
54-
};
34+
const TableComponent = forwardRef<HTMLTableElement, TableProps>(
35+
({ children, className, striped, hoverable, theme: customTheme = {}, ...props }, ref) => {
36+
const theme = mergeDeep(getTheme().table, customTheme);
37+
38+
return (
39+
<div data-testid="table-element" className={twMerge(theme.root.wrapper)}>
40+
<TableContext.Provider value={{ theme, striped, hoverable }}>
41+
<div className={twMerge(theme.root.shadow, className)}></div>
42+
<table className={twMerge(theme.root.base, className)} {...props} ref={ref}>
43+
{children}
44+
</table>
45+
</TableContext.Provider>
46+
</div>
47+
);
48+
},
49+
);
5550

5651
TableComponent.displayName = 'Table';
57-
TableHead.displayName = 'Table.Head';
58-
TableBody.displayName = 'Table.Body';
59-
TableRow.displayName = 'Table.Row';
60-
TableCell.displayName = 'Table.Cell';
61-
TableHeadCell.displayName = 'Table.HeadCell';
6252

6353
export const Table = Object.assign(TableComponent, {
6454
Head: TableHead,

src/components/Table/TableBody.tsx

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client';
22

3-
import type { ComponentProps, FC } from 'react';
3+
import { forwardRef, type ComponentPropsWithRef } from 'react';
44
import { twMerge } from 'tailwind-merge';
55
import { mergeDeep } from '../../helpers/merge-deep';
66
import type { DeepPartial } from '../../types';
@@ -13,20 +13,23 @@ export interface FlowbiteTableBodyTheme {
1313
cell: FlowbiteTableCellTheme;
1414
}
1515

16-
export interface TableBodyProps extends ComponentProps<'tbody'> {
16+
export interface TableBodyProps extends ComponentPropsWithRef<'tbody'> {
1717
theme?: DeepPartial<FlowbiteTableBodyTheme>;
1818
}
1919

20-
export const TableBody: FC<TableBodyProps> = ({ children, className, theme: customTheme = {}, ...props }) => {
21-
const { theme: rootTheme } = useTableContext();
20+
export const TableBody = forwardRef<HTMLTableSectionElement, TableBodyProps>(
21+
({ children, className, theme: customTheme = {}, ...props }, ref) => {
22+
const { theme: rootTheme } = useTableContext();
2223

23-
const theme = mergeDeep(rootTheme.body, customTheme);
24+
const theme = mergeDeep(rootTheme.body, customTheme);
2425

25-
return (
26-
<TableBodyContext.Provider value={{ theme }}>
27-
<tbody className={twMerge(theme.base, className)} {...props}>
28-
{children}
29-
</tbody>
30-
</TableBodyContext.Provider>
31-
);
32-
};
26+
return (
27+
<TableBodyContext.Provider value={{ theme }}>
28+
<tbody className={twMerge(theme.base, className)} ref={ref} {...props}>
29+
{children}
30+
</tbody>
31+
</TableBodyContext.Provider>
32+
);
33+
},
34+
);
35+
TableBody.displayName = 'Table.Body';

src/components/Table/TableCell.tsx

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client';
22

3-
import type { ComponentProps, FC } from 'react';
3+
import { forwardRef, type ComponentPropsWithRef } from 'react';
44
import { twMerge } from 'tailwind-merge';
55
import { mergeDeep } from '../../helpers/merge-deep';
66
import type { DeepPartial } from '../../types';
@@ -10,18 +10,21 @@ export interface FlowbiteTableCellTheme {
1010
base: string;
1111
}
1212

13-
export interface TableCellProps extends ComponentProps<'td'> {
13+
export interface TableCellProps extends ComponentPropsWithRef<'td'> {
1414
theme?: DeepPartial<FlowbiteTableCellTheme>;
1515
}
1616

17-
export const TableCell: FC<TableCellProps> = ({ children, className, theme: customTheme = {}, ...props }) => {
18-
const { theme: bodyTheme } = useTableBodyContext();
17+
export const TableCell = forwardRef<HTMLTableCellElement, TableCellProps>(
18+
({ children, className, theme: customTheme = {}, ...props }, ref) => {
19+
const { theme: bodyTheme } = useTableBodyContext();
1920

20-
const theme = mergeDeep(bodyTheme.cell, customTheme);
21+
const theme = mergeDeep(bodyTheme.cell, customTheme);
2122

22-
return (
23-
<td className={twMerge(theme.base, className)} {...props}>
24-
{children}
25-
</td>
26-
);
27-
};
23+
return (
24+
<td className={twMerge(theme.base, className)} ref={ref} {...props}>
25+
{children}
26+
</td>
27+
);
28+
},
29+
);
30+
TableCell.displayName = 'Table.Cell';

src/components/Table/TableHead.tsx

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client';
22

3-
import type { ComponentProps, FC } from 'react';
3+
import { forwardRef, type ComponentPropsWithRef } from 'react';
44
import { twMerge } from 'tailwind-merge';
55
import { mergeDeep } from '../../helpers/merge-deep';
66
import type { DeepPartial } from '../../types';
@@ -13,20 +13,23 @@ export interface FlowbiteTableHeadTheme {
1313
cell: FlowbiteTableHeadCellTheme;
1414
}
1515

16-
export interface TableHeadProps extends ComponentProps<'thead'> {
16+
export interface TableHeadProps extends ComponentPropsWithRef<'thead'> {
1717
theme?: DeepPartial<FlowbiteTableHeadTheme>;
1818
}
1919

20-
export const TableHead: FC<TableHeadProps> = ({ children, className, theme: customTheme = {}, ...props }) => {
21-
const { theme: rootTheme } = useTableContext();
20+
export const TableHead = forwardRef<HTMLTableSectionElement, TableHeadProps>(
21+
({ children, className, theme: customTheme = {}, ...props }, ref) => {
22+
const { theme: rootTheme } = useTableContext();
2223

23-
const theme = mergeDeep(rootTheme.head, customTheme);
24+
const theme = mergeDeep(rootTheme.head, customTheme);
2425

25-
return (
26-
<TableHeadContext.Provider value={{ theme }}>
27-
<thead className={twMerge(theme.base, className)} {...props}>
28-
<tr>{children}</tr>
29-
</thead>
30-
</TableHeadContext.Provider>
31-
);
32-
};
26+
return (
27+
<TableHeadContext.Provider value={{ theme }}>
28+
<thead className={twMerge(theme.base, className)} ref={ref} {...props}>
29+
<tr>{children}</tr>
30+
</thead>
31+
</TableHeadContext.Provider>
32+
);
33+
},
34+
);
35+
TableHead.displayName = 'Table.Head';
Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client';
22

3-
import type { ComponentProps, FC } from 'react';
3+
import { forwardRef, type ComponentPropsWithRef } from 'react';
44
import { twMerge } from 'tailwind-merge';
55
import { mergeDeep } from '../../helpers/merge-deep';
66
import type { DeepPartial } from '../../types';
@@ -10,18 +10,21 @@ export interface FlowbiteTableHeadCellTheme {
1010
base: string;
1111
}
1212

13-
export interface TableHeadCellProps extends ComponentProps<'th'> {
13+
export interface TableHeadCellProps extends ComponentPropsWithRef<'th'> {
1414
theme?: DeepPartial<FlowbiteTableHeadCellTheme>;
1515
}
1616

17-
export const TableHeadCell: FC<TableHeadCellProps> = ({ children, className, theme: customTheme = {}, ...props }) => {
18-
const { theme: headTheme } = useTableHeadContext();
17+
export const TableHeadCell = forwardRef<HTMLTableCellElement, TableHeadCellProps>(
18+
({ children, className, theme: customTheme = {}, ...props }, ref) => {
19+
const { theme: headTheme } = useTableHeadContext();
1920

20-
const theme = mergeDeep(headTheme.cell, customTheme);
21+
const theme = mergeDeep(headTheme.cell, customTheme);
2122

22-
return (
23-
<th className={twMerge(theme.base, className)} {...props}>
24-
{children}
25-
</th>
26-
);
27-
};
23+
return (
24+
<th className={twMerge(theme.base, className)} ref={ref} {...props}>
25+
{children}
26+
</th>
27+
);
28+
},
29+
);
30+
TableHeadCell.displayName = 'Table.HeadCell';

src/components/Table/TableRow.tsx

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client';
22

3-
import type { ComponentProps, FC } from 'react';
3+
import { forwardRef, type ComponentPropsWithRef } from 'react';
44
import { twMerge } from 'tailwind-merge';
55
import { mergeDeep } from '../../helpers/merge-deep';
66
import type { DeepPartial } from '../../types';
@@ -12,22 +12,26 @@ export interface FlowbiteTableRowTheme {
1212
striped: string;
1313
}
1414

15-
export interface TableRowProps extends ComponentProps<'tr'> {
15+
export interface TableRowProps extends ComponentPropsWithRef<'tr'> {
1616
theme?: DeepPartial<FlowbiteTableRowTheme>;
1717
}
1818

19-
export const TableRow: FC<TableRowProps> = ({ children, className, theme: customTheme = {}, ...props }) => {
20-
const { theme: rootTheme, hoverable, striped } = useTableContext();
19+
export const TableRow = forwardRef<HTMLTableRowElement, TableRowProps>(
20+
({ children, className, theme: customTheme = {}, ...props }, ref) => {
21+
const { theme: rootTheme, hoverable, striped } = useTableContext();
2122

22-
const theme = mergeDeep(rootTheme.row, customTheme);
23+
const theme = mergeDeep(rootTheme.row, customTheme);
2324

24-
return (
25-
<tr
26-
data-testid="table-row-element"
27-
className={twMerge(theme.base, striped && theme.striped, hoverable && theme.hovered, className)}
28-
{...props}
29-
>
30-
{children}
31-
</tr>
32-
);
33-
};
25+
return (
26+
<tr
27+
ref={ref}
28+
data-testid="table-row-element"
29+
className={twMerge(theme.base, striped && theme.striped, hoverable && theme.hovered, className)}
30+
{...props}
31+
>
32+
{children}
33+
</tr>
34+
);
35+
},
36+
);
37+
TableRow.displayName = 'Table.Row';

0 commit comments

Comments
 (0)