Skip to content

Commit

Permalink
[material-ui][Alert] complete slots and slotProps (#44971)
Browse files Browse the repository at this point in the history
  • Loading branch information
siriwatknp authored Jan 10, 2025
1 parent 11b3889 commit 60106b3
Show file tree
Hide file tree
Showing 8 changed files with 217 additions and 69 deletions.
52 changes: 26 additions & 26 deletions docs/pages/material-ui/api/alert.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@
"slotProps": {
"type": {
"name": "shape",
"description": "{ closeButton?: func<br>&#124;&nbsp;object, closeIcon?: func<br>&#124;&nbsp;object }"
"description": "{ action?: func<br>&#124;&nbsp;object, closeButton?: func<br>&#124;&nbsp;object, closeIcon?: func<br>&#124;&nbsp;object, icon?: func<br>&#124;&nbsp;object, message?: func<br>&#124;&nbsp;object, root?: func<br>&#124;&nbsp;object }"
},
"default": "{}"
},
"slots": {
"type": {
"name": "shape",
"description": "{ closeButton?: elementType, closeIcon?: elementType }"
"description": "{ action?: elementType, closeButton?: elementType, closeIcon?: elementType, icon?: elementType, message?: elementType, root?: elementType }"
},
"default": "{}"
},
Expand All @@ -79,6 +79,30 @@
"name": "Alert",
"imports": ["import Alert from '@mui/material/Alert';", "import { Alert } from '@mui/material';"],
"slots": [
{
"name": "root",
"description": "The component that renders the root slot.",
"default": "Paper",
"class": "MuiAlert-root"
},
{
"name": "icon",
"description": "The component that renders the icon slot.",
"default": "div",
"class": "MuiAlert-icon"
},
{
"name": "message",
"description": "The component that renders the message slot.",
"default": "div",
"class": "MuiAlert-message"
},
{
"name": "action",
"description": "The component that renders the action slot.",
"default": "div",
"class": "MuiAlert-action"
},
{
"name": "closeButton",
"description": "The component that renders the close button.",
Expand All @@ -93,12 +117,6 @@
}
],
"classes": [
{
"key": "action",
"className": "MuiAlert-action",
"description": "Styles applied to the action wrapper element if `action` is provided.",
"isGlobal": false
},
{
"key": "colorError",
"className": "MuiAlert-colorError",
Expand Down Expand Up @@ -157,18 +175,6 @@
"isGlobal": false,
"isDeprecated": true
},
{
"key": "icon",
"className": "MuiAlert-icon",
"description": "Styles applied to the icon wrapper element.",
"isGlobal": false
},
{
"key": "message",
"className": "MuiAlert-message",
"description": "Styles applied to the message wrapper element.",
"isGlobal": false
},
{
"key": "outlined",
"className": "MuiAlert-outlined",
Expand Down Expand Up @@ -203,12 +209,6 @@
"isGlobal": false,
"isDeprecated": true
},
{
"key": "root",
"className": "MuiAlert-root",
"description": "Styles applied to the root element.",
"isGlobal": false
},
{
"key": "standard",
"className": "MuiAlert-standard",
Expand Down
20 changes: 5 additions & 15 deletions docs/translations/api-docs/alert/alert.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,6 @@
"variant": { "description": "The variant to use." }
},
"classDescriptions": {
"action": {
"description": "Styles applied to {{nodeName}} if {{conditions}}.",
"nodeName": "the action wrapper element",
"conditions": "<code>action</code> is provided"
},
"colorError": {
"description": "Styles applied to {{nodeName}} if {{conditions}}.",
"nodeName": "the root element",
Expand Down Expand Up @@ -90,14 +85,6 @@
"description": "Styles applied to the root element if <code>variant=&quot;filled&quot;</code> and <code>color=&quot;warning&quot;</code>",
"deprecationInfo": "Combine the <a href=\"/material-ui/api/alert/#alert-classes-filled\">.MuiAlert-filled</a> and <a href=\"/material-ui/api/alert/#alert-classes-colorWarning\">.MuiAlert-colorWarning</a> classes instead. See <a href=\"/material-ui/migration/migrating-from-deprecated-apis/\">Migrating from deprecated APIs</a> for more details."
},
"icon": {
"description": "Styles applied to {{nodeName}}.",
"nodeName": "the icon wrapper element"
},
"message": {
"description": "Styles applied to {{nodeName}}.",
"nodeName": "the message wrapper element"
},
"outlined": {
"description": "Styles applied to {{nodeName}} if {{conditions}}.",
"nodeName": "the root element",
Expand Down Expand Up @@ -127,7 +114,6 @@
"conditions": "<code>variant=\"outlined\"</code> and <code>color=\"warning\"</code>",
"deprecationInfo": "Combine the <a href=\"/material-ui/api/alert/#alert-classes-outlined\">.MuiAlert-outlined</a> and <a href=\"/material-ui/api/alert/#alert-classes-colorWarning\">.MuiAlert-colorWarning</a> classes instead. See <a href=\"/material-ui/migration/migrating-from-deprecated-apis/\">Migrating from deprecated APIs</a> for more details."
},
"root": { "description": "Styles applied to the root element." },
"standard": {
"description": "Styles applied to {{nodeName}} if {{conditions}}.",
"nodeName": "the root element",
Expand Down Expand Up @@ -159,7 +145,11 @@
}
},
"slotDescriptions": {
"action": "The component that renders the action slot.",
"closeButton": "The component that renders the close button.",
"closeIcon": "The component that renders the close icon."
"closeIcon": "The component that renders the close icon.",
"icon": "The component that renders the icon slot.",
"message": "The component that renders the message slot.",
"root": "The component that renders the root slot."
}
}
12 changes: 9 additions & 3 deletions packages-internal/test-utils/src/describeConformance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export interface ConformanceOptions {
testStateOverrides?: { prop?: string; value?: any; styleKey: string };
testCustomVariant?: boolean;
testVariantProps?: object;
testLegacyComponentsProp?: boolean;
testLegacyComponentsProp?: boolean | string[];
slots?: Record<string, SlotTestingOptions>;
ThemeProvider?: React.ElementType;
/**
Expand Down Expand Up @@ -387,7 +387,10 @@ function testSlotsProp(
}

// For testing Material UI components v5, and v6. Likely to be removed in v7.
if (testLegacyComponentsProp) {
if (
testLegacyComponentsProp === true ||
(Array.isArray(testLegacyComponentsProp) && testLegacyComponentsProp.includes(slotName))
) {
it(`allows overriding the ${slotName} slot with a component using the components.${capitalize(
slotName,
)} prop`, async () => {
Expand Down Expand Up @@ -541,7 +544,10 @@ function testSlotPropsProp(
});
}

if (testLegacyComponentsProp) {
if (
testLegacyComponentsProp === true ||
(Array.isArray(testLegacyComponentsProp) && testLegacyComponentsProp.includes(slotName))
) {
it(`sets custom properties on the ${slotName} slot's element with the componentsProps.${slotName} prop`, async () => {
const componentsProps = {
[slotName]: {
Expand Down
69 changes: 69 additions & 0 deletions packages/mui-material/src/Alert/Alert.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,39 @@ export type AlertColor = 'success' | 'info' | 'warning' | 'error';

export interface AlertPropsVariantOverrides {}
export interface AlertPropsColorOverrides {}

export interface AlertRootSlotPropsOverrides {}

export interface AlertIconSlotPropsOverrides {}

export interface AlertMessageSlotPropsOverrides {}

export interface AlertActionSlotPropsOverrides {}

export interface AlertCloseButtonSlotPropsOverrides {}
export interface AlertCloseIconSlotPropsOverrides {}

export interface AlertSlots {
/**
* The component that renders the root slot.
* @default Paper
*/
root: React.ElementType;
/**
* The component that renders the icon slot.
* @default div
*/
icon: React.ElementType;
/**
* The component that renders the message slot.
* @default div
*/
message: React.ElementType;
/**
* The component that renders the action slot.
* @default div
*/
action: React.ElementType;
/**
* The component that renders the close button.
* @default IconButton
Expand All @@ -29,11 +58,51 @@ export interface AlertSlots {
export type AlertSlotsAndSlotProps = CreateSlotsAndSlotProps<
AlertSlots,
{
/**
* Props forwarded to the root slot.
* By default, the avaible props are based on the [Paper](https://mui.com/material-ui/api/paper/#props) component.
*/
root: SlotProps<React.ElementType<PaperProps>, AlertRootSlotPropsOverrides, AlertOwnerState>;
/**
* Props forwarded to the icon slot.
* By default, the avaible props are based on a div element.
*/
icon: SlotProps<
React.ElementType<React.DetailsHTMLAttributes<HTMLDivElement>>,
AlertIconSlotPropsOverrides,
AlertOwnerState
>;
/**
* Props forwarded to the message slot.
* By default, the avaible props are based on a div element.
*/
message: SlotProps<
React.ElementType<React.DetailsHTMLAttributes<HTMLDivElement>>,
AlertMessageSlotPropsOverrides,
AlertOwnerState
>;
/**
* Props forwarded to the action slot.
* By default, the avaible props are based on a div element.
*/
action: SlotProps<
React.ElementType<React.DetailsHTMLAttributes<HTMLDivElement>>,
AlertActionSlotPropsOverrides,
AlertOwnerState
>;
/**
* Props forwarded to the closeButton slot.
* By default, the avaible props are based on the [IconButton](https://mui.com/material-ui/api/icon-button/#props) component.
*/
closeButton: SlotProps<
React.ElementType<IconButtonProps>,
AlertCloseButtonSlotPropsOverrides,
AlertOwnerState
>;
/**
* Props forwarded to the closeIcon slot.
* By default, the avaible props are based on the [SvgIcon](https://mui.com/material-ui/api/svg-icon/#props) component.
*/
closeIcon: SlotProps<
React.ElementType<SvgIconProps>,
AlertCloseIconSlotPropsOverrides,
Expand Down
74 changes: 53 additions & 21 deletions packages/mui-material/src/Alert/Alert.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,43 @@ const Alert = React.forwardRef(function Alert(inProps, ref) {
},
};

const [RootSlot, rootSlotProps] = useSlot('root', {
ref,
shouldForwardComponentProp: true,
className: clsx(classes.root, className),
elementType: AlertRoot,
externalForwardedProps: {
...externalForwardedProps,
...other,
},
ownerState,
additionalProps: {
role,
elevation: 0,
},
});

const [IconSlot, iconSlotProps] = useSlot('icon', {
className: classes.icon,
elementType: AlertIcon,
externalForwardedProps,
ownerState,
});

const [MessageSlot, messageSlotProps] = useSlot('message', {
className: classes.message,
elementType: AlertMessage,
externalForwardedProps,
ownerState,
});

const [ActionSlot, actionSlotProps] = useSlot('action', {
className: classes.action,
elementType: AlertAction,
externalForwardedProps,
ownerState,
});

const [CloseButtonSlot, closeButtonProps] = useSlot('closeButton', {
elementType: IconButton,
externalForwardedProps,
Expand All @@ -215,29 +252,16 @@ const Alert = React.forwardRef(function Alert(inProps, ref) {
});

return (
<AlertRoot
role={role}
elevation={0}
ownerState={ownerState}
className={clsx(classes.root, className)}
ref={ref}
{...other}
>
<RootSlot {...rootSlotProps}>
{icon !== false ? (
<AlertIcon ownerState={ownerState} className={classes.icon}>
<IconSlot {...iconSlotProps}>
{icon || iconMapping[severity] || defaultIconMapping[severity]}
</AlertIcon>
) : null}
<AlertMessage ownerState={ownerState} className={classes.message}>
{children}
</AlertMessage>
{action != null ? (
<AlertAction ownerState={ownerState} className={classes.action}>
{action}
</AlertAction>
</IconSlot>
) : null}
<MessageSlot {...messageSlotProps}>{children}</MessageSlot>
{action != null ? <ActionSlot {...actionSlotProps}>{action}</ActionSlot> : null}
{action == null && onClose ? (
<AlertAction ownerState={ownerState} className={classes.action}>
<ActionSlot {...actionSlotProps}>
<CloseButtonSlot
size="small"
aria-label={closeText}
Expand All @@ -248,9 +272,9 @@ const Alert = React.forwardRef(function Alert(inProps, ref) {
>
<CloseIconSlot fontSize="small" {...closeIconProps} />
</CloseButtonSlot>
</AlertAction>
</ActionSlot>
) : null}
</AlertRoot>
</RootSlot>
);
});

Expand Down Expand Up @@ -356,16 +380,24 @@ Alert.propTypes /* remove-proptypes */ = {
* @default {}
*/
slotProps: PropTypes.shape({
action: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
closeButton: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
closeIcon: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
icon: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
message: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
root: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
}),
/**
* The components used for each slot inside.
* @default {}
*/
slots: PropTypes.shape({
action: PropTypes.elementType,
closeButton: PropTypes.elementType,
closeIcon: PropTypes.elementType,
icon: PropTypes.elementType,
message: PropTypes.elementType,
root: PropTypes.elementType,
}),
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
Expand Down
Loading

0 comments on commit 60106b3

Please sign in to comment.