Skip to content

Commit 9e4c31b

Browse files
sai6855siriwatknp
andauthored
[material-ui][CardActionArea] Add slots and slotProps (#45866)
Signed-off-by: sai chand <60743144+sai6855@users.noreply.github.com> Co-authored-by: Siriwat K <siriwatkunaporn@gmail.com>
1 parent 50e0a70 commit 9e4c31b

File tree

5 files changed

+143
-31
lines changed

5 files changed

+143
-31
lines changed

docs/pages/material-ui/api/card-action-area.json

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@
22
"props": {
33
"children": { "type": { "name": "node" } },
44
"classes": { "type": { "name": "object" }, "additionalInfo": { "cssApi": true } },
5+
"slotProps": {
6+
"type": {
7+
"name": "shape",
8+
"description": "{ focusHighlight?: func<br>&#124;&nbsp;object, root?: func<br>&#124;&nbsp;object }"
9+
},
10+
"default": "{}"
11+
},
12+
"slots": {
13+
"type": {
14+
"name": "shape",
15+
"description": "{ focusHighlight?: elementType, root?: elementType }"
16+
},
17+
"default": "{}"
18+
},
519
"sx": {
620
"type": {
721
"name": "union",
@@ -15,24 +29,26 @@
1529
"import CardActionArea from '@mui/material/CardActionArea';",
1630
"import { CardActionArea } from '@mui/material';"
1731
],
18-
"classes": [
32+
"slots": [
1933
{
20-
"key": "focusHighlight",
21-
"className": "MuiCardActionArea-focusHighlight",
22-
"description": "Styles applied to the overlay that covers the action area when it is keyboard focused.",
23-
"isGlobal": false
34+
"name": "root",
35+
"description": "The component that renders the root.",
36+
"default": "ButtonBase",
37+
"class": "MuiCardActionArea-root"
2438
},
39+
{
40+
"name": "focusHighlight",
41+
"description": "The component that renders the focusHighlight.",
42+
"default": "span",
43+
"class": "MuiCardActionArea-focusHighlight"
44+
}
45+
],
46+
"classes": [
2547
{
2648
"key": "focusVisible",
2749
"className": "Mui-focusVisible",
2850
"description": "State class applied to the ButtonBase root element if the action area is keyboard focused.",
2951
"isGlobal": true
30-
},
31-
{
32-
"key": "root",
33-
"className": "MuiCardActionArea-root",
34-
"description": "Styles applied to the root element.",
35-
"isGlobal": false
3652
}
3753
],
3854
"spread": true,

docs/translations/api-docs/card-action-area/card-action-area.json

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,21 @@
33
"propDescriptions": {
44
"children": { "description": "The content of the component." },
55
"classes": { "description": "Override or extend the styles applied to the component." },
6+
"slotProps": { "description": "The props used for each slot inside." },
7+
"slots": { "description": "The components used for each slot inside." },
68
"sx": {
79
"description": "The system prop that allows defining system overrides as well as additional CSS styles."
810
}
911
},
1012
"classDescriptions": {
11-
"focusHighlight": {
12-
"description": "Styles applied to {{nodeName}} when {{conditions}}.",
13-
"nodeName": "the overlay that covers the action area",
14-
"conditions": "it is keyboard focused"
15-
},
1613
"focusVisible": {
1714
"description": "State class applied to {{nodeName}} if {{conditions}}.",
1815
"nodeName": "the ButtonBase root element",
1916
"conditions": "the action area is keyboard focused"
20-
},
21-
"root": { "description": "Styles applied to the root element." }
17+
}
18+
},
19+
"slotDescriptions": {
20+
"focusHighlight": "The component that renders the focusHighlight.",
21+
"root": "The component that renders the root."
2222
}
2323
}

packages/mui-material/src/CardActionArea/CardActionArea.d.ts

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,47 @@
11
import * as React from 'react';
22
import { SxProps } from '@mui/system';
3-
import { Theme } from '..';
4-
import { ButtonBaseTypeMap, ExtendButtonBase, ExtendButtonBaseTypeMap } from '../ButtonBase';
3+
import { SlotProps, CreateSlotsAndSlotProps, Theme } from '..';
4+
import {
5+
ButtonBaseProps,
6+
ButtonBaseTypeMap,
7+
ExtendButtonBase,
8+
ExtendButtonBaseTypeMap,
9+
} from '../ButtonBase';
510
import { OverrideProps } from '../OverridableComponent';
611
import { CardActionAreaClasses } from './cardActionAreaClasses';
712

13+
export interface CardActionAreaSlots {
14+
/**
15+
* The component that renders the root.
16+
* @default ButtonBase
17+
*/
18+
root: React.ElementType;
19+
/**
20+
* The component that renders the focusHighlight.
21+
* @default span
22+
*/
23+
focusHighlight: React.ElementType;
24+
}
25+
26+
export type CardActionAreaSlotsAndSlotProps = CreateSlotsAndSlotProps<
27+
CardActionAreaSlots,
28+
{
29+
/**
30+
* Props forwarded to the root slot.
31+
* By default, the avaible props are based on the span element.
32+
*/
33+
root: SlotProps<React.ElementType<ButtonBaseProps>, {}, CardActionAreaOwnerState>;
34+
/**
35+
* Props forwarded to the focusHighlight slot.
36+
* By default, the avaible props are based on the span element.
37+
*/
38+
focusHighlight: SlotProps<'span', {}, CardActionAreaOwnerState>;
39+
}
40+
>;
41+
42+
export interface CardActionAreaOwnerState
43+
extends Omit<CardActionAreaProps, 'slots' | 'slotProps'> {}
44+
845
export interface CardActionAreaOwnProps {
946
/**
1047
* Override or extend the styles applied to the component.
@@ -21,7 +58,7 @@ export type CardActionAreaTypeMap<
2158
AdditionalProps,
2259
RootComponent extends React.ElementType,
2360
> = ExtendButtonBaseTypeMap<{
24-
props: AdditionalProps & CardActionAreaOwnProps;
61+
props: AdditionalProps & CardActionAreaOwnProps & CardActionAreaSlotsAndSlotProps;
2562
defaultComponent: RootComponent;
2663
}>;
2764

packages/mui-material/src/CardActionArea/CardActionArea.js

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import memoTheme from '../utils/memoTheme';
88
import { useDefaultProps } from '../DefaultPropsProvider';
99
import cardActionAreaClasses, { getCardActionAreaUtilityClass } from './cardActionAreaClasses';
1010
import ButtonBase from '../ButtonBase';
11+
import useSlot from '../utils/useSlot';
1112

1213
const useUtilityClasses = (ownerState) => {
1314
const { classes } = ownerState;
@@ -66,22 +67,51 @@ const CardActionAreaFocusHighlight = styled('span', {
6667

6768
const CardActionArea = React.forwardRef(function CardActionArea(inProps, ref) {
6869
const props = useDefaultProps({ props: inProps, name: 'MuiCardActionArea' });
69-
const { children, className, focusVisibleClassName, ...other } = props;
70+
const {
71+
children,
72+
className,
73+
focusVisibleClassName,
74+
slots = {},
75+
slotProps = {},
76+
...other
77+
} = props;
7078

7179
const ownerState = props;
7280
const classes = useUtilityClasses(ownerState);
7381

82+
const externalForwardedProps = {
83+
slots,
84+
slotProps,
85+
};
86+
87+
const [RootSlot, rootProps] = useSlot('root', {
88+
elementType: CardActionAreaRoot,
89+
externalForwardedProps: {
90+
...externalForwardedProps,
91+
...other,
92+
},
93+
shouldForwardComponentProp: true,
94+
ownerState,
95+
ref,
96+
className: clsx(classes.root, className),
97+
additionalProps: {
98+
focusVisibleClassName: clsx(focusVisibleClassName, classes.focusVisible),
99+
},
100+
});
101+
102+
const [FocusHighlightSlot, focusHighlightProps] = useSlot('focusHighlight', {
103+
elementType: CardActionAreaFocusHighlight,
104+
externalForwardedProps,
105+
ownerState,
106+
ref,
107+
className: classes.focusHighlight,
108+
});
109+
74110
return (
75-
<CardActionAreaRoot
76-
className={clsx(classes.root, className)}
77-
focusVisibleClassName={clsx(focusVisibleClassName, classes.focusVisible)}
78-
ref={ref}
79-
ownerState={ownerState}
80-
{...other}
81-
>
111+
<RootSlot {...rootProps}>
82112
{children}
83-
<CardActionAreaFocusHighlight className={classes.focusHighlight} ownerState={ownerState} />
84-
</CardActionAreaRoot>
113+
<FocusHighlightSlot {...focusHighlightProps} />
114+
</RootSlot>
85115
);
86116
});
87117

@@ -106,6 +136,22 @@ CardActionArea.propTypes /* remove-proptypes */ = {
106136
* @ignore
107137
*/
108138
focusVisibleClassName: PropTypes.string,
139+
/**
140+
* The props used for each slot inside.
141+
* @default {}
142+
*/
143+
slotProps: PropTypes.shape({
144+
focusHighlight: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
145+
root: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
146+
}),
147+
/**
148+
* The components used for each slot inside.
149+
* @default {}
150+
*/
151+
slots: PropTypes.shape({
152+
focusHighlight: PropTypes.elementType,
153+
root: PropTypes.elementType,
154+
}),
109155
/**
110156
* The system prop that allows defining system overrides as well as additional CSS styles.
111157
*/

packages/mui-material/src/CardActionArea/CardActionArea.test.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ import CardActionArea, { cardActionAreaClasses as classes } from '@mui/material/
44
import ButtonBase from '@mui/material/ButtonBase';
55
import describeConformance from '../../test/describeConformance';
66

7+
const CustomButtonBase = React.forwardRef(({ focusVisibleClassName, ...props }, ref) => {
8+
return <ButtonBase {...props} ref={ref} />;
9+
});
10+
711
describe('<CardActionArea />', () => {
812
const { render } = createRenderer();
913

@@ -16,5 +20,14 @@ describe('<CardActionArea />', () => {
1620
testVariantProps: { variant: 'foo' },
1721
refInstanceof: window.HTMLButtonElement,
1822
skip: ['componentProp', 'componentsProp'],
23+
slots: {
24+
root: {
25+
expectedClassName: classes.root,
26+
testWithElement: CustomButtonBase,
27+
},
28+
focusHighlight: {
29+
expectedClassName: classes.focusHighlight,
30+
},
31+
},
1932
}));
2033
});

0 commit comments

Comments
 (0)