Skip to content

Commit b9edd3d

Browse files
authored
[TablePagination] Drop component prop (#37059)
1 parent 1d6d7fb commit b9edd3d

File tree

10 files changed

+102
-55
lines changed

10 files changed

+102
-55
lines changed

docs/data/base/components/table-pagination/table-pagination.md

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ It controls two properties of its parent table:
2222
- number of rows per page
2323

2424
Table Pagination renders its internal elements in a `<td>` tag by default so it can be inserted into a table's `<tr>`.
25-
You can use the `component` or `slots.root` prop to render a different root element—for example, if you need to place the pagination controls outside of the table.
25+
You can use the `slots.root` prop to render a different root element—for example, if you need to place the pagination controls outside of the table.
2626
See the [Slot props section](#slot-props) for details.
2727

2828
{{"demo": "UnstyledPaginationIntroduction.js", "defaultCodeOpen": false, "bg": "gradient"}}
@@ -99,27 +99,17 @@ The Table Pagination component is composed of a root `<td>` that houses up to te
9999
</td>
100100
```
101101

102-
### Slot props
102+
### Custom structure
103103

104-
:::info
105-
The following props are available on all non-utility Base components.
106-
See [Usage](/base/getting-started/usage/) for full details.
107-
:::
108-
109-
Use the `component` prop to override the root slot with a custom element:
110-
111-
```jsx
112-
<TablePagination component="div" />
113-
```
114-
115-
Use the `slots` prop to override any interior slots in addition to the root:
104+
Use the `slots` prop to override the root or any other interior slot:
116105

117106
```jsx
118107
<TablePagination slots={{ root: 'div', toolbar: 'nav' }} />
119108
```
120109

121-
:::warning
122-
If the root element is customized with both the `component` and `slots` props, then `component` will take precedence.
110+
:::info
111+
The `slots` prop is available on all non-utility Base components.
112+
See [Overriding component structure](/base/guides/overriding-component-structure/) for full details.
123113
:::
124114

125115
Use the `slotProps` prop to pass custom props to internal slots.
@@ -131,6 +121,23 @@ The following code snippet applies a CSS class called `my-spacer` to the spacer
131121

132122
## Customization
133123

124+
### Usage with TypeScript
125+
126+
In TypeScript, you can specify the custom component type used in the `slots.root` as a generic parameter of the unstyled component. This way, you can safely provide the custom root's props directly on the component:
127+
128+
```tsx
129+
<TablePagination<typeof CustomComponent>
130+
slots={{ root: CustomComponent }}
131+
customProp
132+
/>
133+
```
134+
135+
The same applies for props specific to custom primitive elements:
136+
137+
```tsx
138+
<TablePagination<'button'> slots={{ root: 'button' }} onClick={() => {}} />
139+
```
140+
134141
### Custom pagination options
135142

136143
You can customize the options shown in the **Rows per page** select using the `rowsPerPageOptions` prop.

docs/pages/base/api/table-pagination.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
"onPageChange": { "type": { "name": "func" }, "required": true },
55
"page": { "type": { "name": "custom", "description": "integer" }, "required": true },
66
"rowsPerPage": { "type": { "name": "custom", "description": "integer" }, "required": true },
7-
"component": { "type": { "name": "elementType" } },
87
"getItemAriaLabel": {
98
"type": { "name": "func" },
109
"default": "function defaultGetAriaLabel(type: ItemAriaLabelType) {\n return `Go to ${type} page`;\n}"

docs/translations/api-docs-base/table-pagination/table-pagination.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
{
22
"componentDescription": "A pagination for tables.",
33
"propDescriptions": {
4-
"component": "The component used for the root node. Either a string to use a HTML element or a component.",
54
"count": "The total number of rows.<br>To enable server side pagination for an unknown number of items, provide -1.",
65
"getItemAriaLabel": "Accepts a function which returns a string value that provides a user-friendly name for the current page. This is important for screen reader users.<br>For localization purposes, you can use the provided <a href=\"/material-ui/guides/localization/\">translations</a>.<br><br><strong>Signature:</strong><br><code>function(type: string) =&gt; string</code><br><em>type:</em> The link or button type to format (&#39;first&#39; | &#39;last&#39; | &#39;next&#39; | &#39;previous&#39;).",
76
"labelDisplayedRows": "Customize the displayed rows label. Invoked with a <code>{ from, to, count, page }</code> object.<br>For localization purposes, you can use the provided <a href=\"/material-ui/guides/localization/\">translations</a>.",

packages/mui-base/src/TablePagination/TablePagination.spec.tsx

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as React from 'react';
22
import TablePagination from '@mui/base/TablePagination';
3+
import { expectType } from '@mui/types';
34
import {
45
TablePaginationActionsSlotProps,
56
TablePaginationDisplayedRowsSlotProps,
@@ -75,3 +76,59 @@ const styledTablePagination = (
7576
}}
7677
/>
7778
);
79+
80+
const polymorphicComponentTest = () => {
81+
const CustomComponent: React.FC<{ stringProp: string; numberProp: number }> =
82+
function CustomComponent() {
83+
return <div />;
84+
};
85+
86+
const requiredProps = {
87+
count: 10,
88+
getItemAriaLabel: () => '',
89+
onPageChange: () => {},
90+
page: 0,
91+
rowsPerPage: 10,
92+
showFirstButton: true,
93+
showLastButton: true,
94+
};
95+
96+
return (
97+
<div>
98+
{/* @ts-expect-error */}
99+
<TablePagination {...requiredProps} invalidProp={0} />
100+
101+
<TablePagination<'a'> {...requiredProps} slots={{ root: 'a' }} href="#" />
102+
103+
<TablePagination<typeof CustomComponent>
104+
{...requiredProps}
105+
slots={{ root: CustomComponent }}
106+
stringProp="test"
107+
numberProp={0}
108+
/>
109+
{/* @ts-expect-error */}
110+
<TablePagination<typeof CustomComponent>
111+
{...requiredProps}
112+
slots={{ root: CustomComponent }}
113+
/>
114+
115+
<TablePagination<'button'>
116+
{...requiredProps}
117+
slots={{ root: 'button' }}
118+
onClick={(e: React.MouseEvent<HTMLButtonElement>) => e.currentTarget.checkValidity()}
119+
/>
120+
121+
<TablePagination<'button'>
122+
{...requiredProps}
123+
slots={{ root: 'button' }}
124+
ref={(elem) => {
125+
expectType<HTMLButtonElement | null, typeof elem>(elem);
126+
}}
127+
onMouseDown={(e) => {
128+
expectType<React.MouseEvent<HTMLButtonElement, MouseEvent>, typeof e>(e);
129+
e.currentTarget.checkValidity();
130+
}}
131+
/>
132+
</div>
133+
);
134+
};

packages/mui-base/src/TablePagination/TablePagination.test.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ describe('<TablePagination />', () => {
6262
testWithElement: 'th',
6363
},
6464
},
65+
skip: ['componentProp'],
6566
}),
6667
);
6768

packages/mui-base/src/TablePagination/TablePagination.tsx

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import * as React from 'react';
22
import PropTypes from 'prop-types';
33
import { unstable_useId as useId, chainPropTypes, integerPropType } from '@mui/utils';
4-
import { OverridableComponent } from '@mui/types';
5-
import { useSlotProps, WithOptionalOwnerState } from '../utils';
4+
import { PolymorphicComponent, useSlotProps, WithOptionalOwnerState } from '../utils';
65
import composeClasses from '../composeClasses';
76
import isHostComponent from '../utils/isHostComponent';
87
import TablePaginationActions from './TablePaginationActions';
@@ -63,7 +62,6 @@ const TablePagination = React.forwardRef(function TablePagination<
6362
RootComponentType extends React.ElementType,
6463
>(props: TablePaginationProps<RootComponentType>, forwardedRef: React.ForwardedRef<Element>) {
6564
const {
66-
component,
6765
colSpan: colSpanProp,
6866
count,
6967
getItemAriaLabel = defaultGetAriaLabel,
@@ -85,7 +83,8 @@ const TablePagination = React.forwardRef(function TablePagination<
8583
const classes = useUtilityClasses();
8684

8785
let colSpan;
88-
if (!component || component === 'td' || !isHostComponent(component)) {
86+
const Root = slots.root ?? 'td';
87+
if (Root === 'td' || !isHostComponent(Root)) {
8988
colSpan = colSpanProp || 1000; // col-span over everything
9089
}
9190

@@ -99,7 +98,6 @@ const TablePagination = React.forwardRef(function TablePagination<
9998
const selectId = useId(selectIdProp);
10099
const labelId = useId(labelIdProp);
101100

102-
const Root = component ?? slots.root ?? 'td';
103101
const rootProps: WithOptionalOwnerState<TablePaginationRootSlotProps> = useSlotProps({
104102
elementType: Root,
105103
externalSlotProps: slotProps.root,
@@ -237,26 +235,17 @@ const TablePagination = React.forwardRef(function TablePagination<
237235
</Toolbar>
238236
</Root>
239237
);
240-
}) as OverridableComponent<TablePaginationTypeMap>;
238+
}) as PolymorphicComponent<TablePaginationTypeMap>;
241239

242240
TablePagination.propTypes /* remove-proptypes */ = {
243241
// ----------------------------- Warning --------------------------------
244242
// | These PropTypes are generated from the TypeScript type definitions |
245243
// | To update them edit TypeScript types and run "yarn proptypes" |
246244
// ----------------------------------------------------------------------
247-
/**
248-
* @ignore
249-
*/
250-
children: PropTypes.node,
251245
/**
252246
* @ignore
253247
*/
254248
colSpan: PropTypes.number,
255-
/**
256-
* The component used for the root node.
257-
* Either a string to use a HTML element or a component.
258-
*/
259-
component: PropTypes.elementType,
260249
/**
261250
* The total number of rows.
262251
*
@@ -357,7 +346,7 @@ TablePagination.propTypes /* remove-proptypes */ = {
357346
* The props used for each slot inside the TablePagination.
358347
* @default {}
359348
*/
360-
slotProps: PropTypes.shape({
349+
slotProps: PropTypes /* @typescript-to-proptypes-ignore */.shape({
361350
actions: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
362351
displayedRows: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
363352
menuItem: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),

packages/mui-base/src/TablePagination/TablePagination.types.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import * as React from 'react';
2-
import { OverrideProps } from '@mui/types';
3-
import { SlotComponentProps } from '../utils';
2+
import { PolymorphicProps, SlotComponentProps } from '../utils';
43
import TablePaginationActions from './TablePaginationActions';
54
import { ItemAriaLabelType } from './common.types';
65

@@ -205,9 +204,7 @@ export interface TablePaginationTypeMap<
205204

206205
export type TablePaginationProps<
207206
RootComponentType extends React.ElementType = TablePaginationTypeMap['defaultComponent'],
208-
> = OverrideProps<TablePaginationTypeMap<{}, RootComponentType>, RootComponentType> & {
209-
component?: RootComponentType;
210-
};
207+
> = PolymorphicProps<TablePaginationTypeMap<{}, RootComponentType>, RootComponentType>;
211208

212209
export type TablePaginationOwnerState = TablePaginationOwnProps;
213210

packages/mui-base/src/TablePagination/TablePaginationActions.spec.tsx

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,26 +56,29 @@ const polymorphicComponentTest = () => {
5656
{/* @ts-expect-error */}
5757
<TablePaginationActions {...requiredProps} invalidProp={0} />
5858

59-
<TablePaginationActions {...requiredProps} component="a" href="#" />
59+
<TablePaginationActions<'a'> {...requiredProps} slots={{ root: 'a' }} href="#" />
6060

61-
<TablePaginationActions
61+
<TablePaginationActions<typeof CustomComponent>
6262
{...requiredProps}
63-
component={CustomComponent}
63+
slots={{ root: CustomComponent }}
6464
stringProp="test"
6565
numberProp={0}
6666
/>
6767
{/* @ts-expect-error */}
68-
<TablePaginationActions {...requiredProps} component={CustomComponent} />
68+
<TablePaginationActions<typeof CustomComponent>
69+
{...requiredProps}
70+
slots={{ root: CustomComponent }}
71+
/>
6972

7073
<TablePaginationActions
7174
{...requiredProps}
72-
component="button"
75+
slots={{ root: 'button' }}
7376
onClick={(e: React.MouseEvent<HTMLButtonElement>) => e.currentTarget.checkValidity()}
7477
/>
7578

7679
<TablePaginationActions<'button'>
7780
{...requiredProps}
78-
component="button"
81+
slots={{ root: 'button' }}
7982
ref={(elem) => {
8083
expectType<HTMLButtonElement | null, typeof elem>(elem);
8184
}}

packages/mui-base/src/TablePagination/TablePaginationActions.tsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import * as React from 'react';
2-
import { OverridableComponent } from '@mui/types';
3-
import { useSlotProps, WithOptionalOwnerState } from '../utils';
2+
import { PolymorphicComponent, useSlotProps, WithOptionalOwnerState } from '../utils';
43
import {
54
TablePaginationActionsButtonSlotProps,
65
TablePaginationActionsProps,
@@ -36,7 +35,6 @@ const TablePaginationActions = React.forwardRef(function TablePaginationActions<
3635
forwardedRef: React.ForwardedRef<Element>,
3736
) {
3837
const {
39-
component,
4038
count,
4139
getItemAriaLabel = defaultGetAriaLabel,
4240
onPageChange,
@@ -70,7 +68,7 @@ const TablePaginationActions = React.forwardRef(function TablePaginationActions<
7068
onPageChange(event, Math.max(0, Math.ceil(count / rowsPerPage) - 1));
7169
};
7270

73-
const Root = slots.root ?? component ?? 'div';
71+
const Root = slots.root ?? 'div';
7472
const rootProps: WithOptionalOwnerState<TablePaginationActionsRootSlotProps> = useSlotProps({
7573
elementType: Root,
7674
externalSlotProps: slotProps.root,
@@ -160,6 +158,6 @@ const TablePaginationActions = React.forwardRef(function TablePaginationActions<
160158
)}
161159
</Root>
162160
);
163-
}) as OverridableComponent<TablePaginationActionsTypeMap>;
161+
}) as PolymorphicComponent<TablePaginationActionsTypeMap>;
164162

165163
export default TablePaginationActions;

packages/mui-base/src/TablePagination/TablePaginationActions.types.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import * as React from 'react';
2-
import { OverrideProps } from '@mui/types';
3-
import { SlotComponentProps } from '../utils';
2+
import { PolymorphicProps, SlotComponentProps } from '../utils';
43

54
export interface TablePaginationActionsRootSlotPropsOverrides {}
65
export interface TablePaginationActionsFirstButtonSlotPropsOverrides {}
@@ -118,9 +117,7 @@ export interface TablePaginationActionsSlots {
118117

119118
export type TablePaginationActionsProps<
120119
RootComponentType extends React.ElementType = TablePaginationActionsTypeMap['defaultComponent'],
121-
> = OverrideProps<TablePaginationActionsTypeMap<{}, RootComponentType>, RootComponentType> & {
122-
component?: RootComponentType;
123-
};
120+
> = PolymorphicProps<TablePaginationActionsTypeMap<{}, RootComponentType>, RootComponentType>;
124121

125122
export interface TablePaginationActionsTypeMap<
126123
AdditionalProps = {},

0 commit comments

Comments
 (0)