diff --git a/docs/pages/api-docs/alert.json b/docs/pages/api-docs/alert.json
index 78ef0408a53584..9e05e4951d0154 100644
--- a/docs/pages/api-docs/alert.json
+++ b/docs/pages/api-docs/alert.json
@@ -26,6 +26,7 @@
},
"default": "'success'"
},
+ "sx": { "type": { "name": "object" } },
"variant": {
"type": {
"name": "union",
@@ -65,5 +66,5 @@
"filename": "/packages/material-ui/src/Alert/Alert.js",
"inheritance": { "component": "Paper", "pathname": "/api/paper/" },
"demos": "
",
- "styledComponent": false
+ "styledComponent": true
}
diff --git a/docs/translations/api-docs/alert/alert.json b/docs/translations/api-docs/alert/alert.json
index 3ea8dad4644191..fd550471f34f7c 100644
--- a/docs/translations/api-docs/alert/alert.json
+++ b/docs/translations/api-docs/alert/alert.json
@@ -11,6 +11,7 @@
"onClose": "Callback fired when the component requests to be closed. When provided and no action
prop is set, a close icon button is displayed that triggers the callback when clicked.
Signature:
function(event: object) => void
event: The event source of the callback.",
"role": "The ARIA role attribute of the element.",
"severity": "The severity of the alert. This defines the color and icon used.",
+ "sx": "The system prop that allows defining system overrides as well as additional CSS styles. See the `sx` page for more details.",
"variant": "The variant to use."
},
"classDescriptions": {
diff --git a/packages/material-ui/src/Alert/Alert.d.ts b/packages/material-ui/src/Alert/Alert.d.ts
index e13764ef9dd5fe..2771dd7f7c1ed2 100644
--- a/packages/material-ui/src/Alert/Alert.d.ts
+++ b/packages/material-ui/src/Alert/Alert.d.ts
@@ -1,6 +1,7 @@
import * as React from 'react';
import { OverridableStringUnion } from '@material-ui/types';
-import { InternalStandardProps as StandardProps } from '..';
+import { SxProps } from '@material-ui/system';
+import { InternalStandardProps as StandardProps, Theme } from '..';
import { PaperProps } from '../Paper';
export type Color = 'success' | 'info' | 'warning' | 'error';
@@ -101,6 +102,10 @@ export interface AlertProps extends StandardProps {
* @default 'standard'
*/
variant?: OverridableStringUnion;
+ /**
+ * The system prop that allows defining system overrides as well as additional CSS styles.
+ */
+ sx?: SxProps;
}
export type AlertClassKey = keyof NonNullable;
diff --git a/packages/material-ui/src/Alert/Alert.js b/packages/material-ui/src/Alert/Alert.js
index 0eca98c4075665..ef81adb81b1d6c 100644
--- a/packages/material-ui/src/Alert/Alert.js
+++ b/packages/material-ui/src/Alert/Alert.js
@@ -1,11 +1,14 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import clsx from 'clsx';
-import { useThemeVariants } from '@material-ui/styles';
-import withStyles from '../styles/withStyles';
+import { deepmerge } from '@material-ui/utils';
+import { unstable_composeClasses as composeClasses } from '@material-ui/unstyled';
+import experimentalStyled from '../styles/experimentalStyled';
+import useThemeProps from '../styles/useThemeProps';
import { darken, lighten } from '../styles/colorManipulator';
import capitalize from '../utils/capitalize';
import Paper from '../Paper';
+import alertClasses, { getAlertUtilityClass } from './alertClasses';
import IconButton from '../IconButton';
import SuccessOutlinedIcon from '../internal/svg-icons/SuccessOutlined';
import ReportProblemOutlinedIcon from '../internal/svg-icons/ReportProblemOutlined';
@@ -13,135 +16,122 @@ import ErrorOutlineIcon from '../internal/svg-icons/ErrorOutline';
import InfoOutlinedIcon from '../internal/svg-icons/InfoOutlined';
import CloseIcon from '../internal/svg-icons/Close';
-export const styles = (theme) => {
+const overridesResolver = (props, styles) => {
+ const { styleProps } = props;
+
+ return deepmerge(styles.root || {}, {
+ ...styles[styleProps.variant],
+ ...styles[`${styleProps.variant}${capitalize(styleProps.color || styleProps.severity)}`],
+ [`& .${alertClasses.icon}`]: styles.icon,
+ [`& .${alertClasses.message}`]: styles.message,
+ [`& .${alertClasses.action}`]: styles.action,
+ });
+};
+
+const useUtilityClasses = (styleProps) => {
+ const { variant, color, severity, classes } = styleProps;
+
+ const slots = {
+ root: ['root', `${variant}${capitalize(color || severity)}`, `${variant}`],
+ icon: ['icon'],
+ message: ['message'],
+ action: ['action'],
+ };
+
+ return composeClasses(slots, getAlertUtilityClass, classes);
+};
+
+const AlertRoot = experimentalStyled(
+ Paper,
+ {},
+ {
+ name: 'MuiAlert',
+ slot: 'Root',
+ overridesResolver,
+ },
+)(({ theme, styleProps }) => {
const getColor = theme.palette.mode === 'light' ? darken : lighten;
const getBackgroundColor = theme.palette.mode === 'light' ? lighten : darken;
+ const color = styleProps.color || styleProps.severity;
return {
/* Styles applied to the root element. */
- root: {
- ...theme.typography.body2,
- borderRadius: theme.shape.borderRadius,
- backgroundColor: 'transparent',
- display: 'flex',
- padding: '6px 16px',
- },
- /* Styles applied to the root element if `variant="filled"`. */
- filled: {},
- /* Styles applied to the root element if `variant="outlined"`. */
- outlined: {},
- /* Styles applied to the root element if `variant="standard"`. */
- standard: {},
- /* Styles applied to the root element if `variant="standard"` and `color="success"`. */
- standardSuccess: {
- color: getColor(theme.palette.success.main, 0.6),
- backgroundColor: getBackgroundColor(theme.palette.success.main, 0.9),
- '& $icon': {
- color: theme.palette.success.main,
- },
- },
- /* Styles applied to the root element if `variant="standard"` and `color="info"`. */
- standardInfo: {
- color: getColor(theme.palette.info.main, 0.6),
- backgroundColor: getBackgroundColor(theme.palette.info.main, 0.9),
- '& $icon': {
- color: theme.palette.info.main,
- },
- },
- /* Styles applied to the root element if `variant="standard"` and `color="warning"`. */
- standardWarning: {
- color: getColor(theme.palette.warning.main, 0.6),
- backgroundColor: getBackgroundColor(theme.palette.warning.main, 0.9),
- '& $icon': {
- color: theme.palette.warning.main,
- },
- },
- /* Styles applied to the root element if `variant="standard"` and `color="error"`. */
- standardError: {
- color: getColor(theme.palette.error.main, 0.6),
- backgroundColor: getBackgroundColor(theme.palette.error.main, 0.9),
- '& $icon': {
- color: theme.palette.error.main,
- },
- },
- /* Styles applied to the root element if `variant="outlined"` and `color="success"`. */
- outlinedSuccess: {
- color: getColor(theme.palette.success.main, 0.6),
- border: `1px solid ${theme.palette.success.main}`,
- '& $icon': {
- color: theme.palette.success.main,
- },
- },
- /* Styles applied to the root element if `variant="outlined"` and `color="info"`. */
- outlinedInfo: {
- color: getColor(theme.palette.info.main, 0.6),
- border: `1px solid ${theme.palette.info.main}`,
- '& $icon': {
- color: theme.palette.info.main,
- },
- },
- /* Styles applied to the root element if `variant="outlined"` and `color="warning"`. */
- outlinedWarning: {
- color: getColor(theme.palette.warning.main, 0.6),
- border: `1px solid ${theme.palette.warning.main}`,
- '& $icon': {
- color: theme.palette.warning.main,
- },
- },
- /* Styles applied to the root element if `variant="outlined"` and `color="error"`. */
- outlinedError: {
- color: getColor(theme.palette.error.main, 0.6),
- border: `1px solid ${theme.palette.error.main}`,
- '& $icon': {
- color: theme.palette.error.main,
- },
- },
- /* Styles applied to the root element if `variant="filled"` and `color="success"`. */
- filledSuccess: {
- color: '#fff',
- fontWeight: theme.typography.fontWeightMedium,
- backgroundColor: theme.palette.success.main,
- },
- /* Styles applied to the root element if `variant="filled"` and `color="info"`. */
- filledInfo: {
- color: '#fff',
- fontWeight: theme.typography.fontWeightMedium,
- backgroundColor: theme.palette.info.main,
- },
- /* Styles applied to the root element if `variant="filled"` and `color="warning"`. */
- filledWarning: {
- color: '#fff',
- fontWeight: theme.typography.fontWeightMedium,
- backgroundColor: theme.palette.warning.main,
- },
- /* Styles applied to the root element if `variant="filled"` and `color="error"`. */
- filledError: {
- color: '#fff',
- fontWeight: theme.typography.fontWeightMedium,
- backgroundColor: theme.palette.error.main,
- },
- /* Styles applied to the icon wrapper element. */
- icon: {
- marginRight: 12,
- padding: '7px 0',
- display: 'flex',
- fontSize: 22,
- opacity: 0.9,
- },
- /* Styles applied to the message wrapper element. */
- message: {
- padding: '8px 0',
- },
- /* Styles applied to the action wrapper element if `action` is provided. */
- action: {
- display: 'flex',
- alignItems: 'center',
- marginLeft: 'auto',
- paddingLeft: 16,
- marginRight: -8,
- },
+ ...theme.typography.body2,
+ borderRadius: theme.shape.borderRadius,
+ backgroundColor: 'transparent',
+ display: 'flex',
+ padding: '6px 16px',
+ /* Styles applied to the root element if variant="standard". */
+ ...(color &&
+ styleProps.variant === 'standard' && {
+ color: getColor(theme.palette[color].main, 0.6),
+ backgroundColor: getBackgroundColor(theme.palette[color].main, 0.9),
+ [`& .${alertClasses.icon}`]: {
+ color: theme.palette[color].main,
+ },
+ }),
+ /* Styles applied to the root element if variant="outlined". */
+ ...(color &&
+ styleProps.variant === 'outlined' && {
+ color: getColor(theme.palette[color].main, 0.6),
+ border: `1px solid ${theme.palette[color].main}`,
+ [`& .${alertClasses.icon}`]: {
+ color: theme.palette[color].main,
+ },
+ }),
+ /* Styles applied to the root element if variant="filled". */
+ ...(color &&
+ styleProps.variant === 'filled' && {
+ color: '#fff',
+ fontWeight: theme.typography.fontWeightMedium,
+ backgroundColor: theme.palette[color].main,
+ }),
};
-};
+});
+
+/* Styles applied to the icon wrapper element. */
+const AlertIcon = experimentalStyled(
+ 'div',
+ {},
+ {
+ name: 'MuiAlert',
+ slot: 'Icon',
+ },
+)({
+ marginRight: 12,
+ padding: '7px 0',
+ display: 'flex',
+ fontSize: 22,
+ opacity: 0.9,
+});
+
+/* Styles applied to the message wrapper element. */
+const AlertMessage = experimentalStyled(
+ 'div',
+ {},
+ {
+ name: 'MuiAlert',
+ slot: 'Message',
+ },
+)({
+ padding: '8px 0',
+});
+
+/* Styles applied to the action wrapper element if `action` is provided. */
+const AlertAction = experimentalStyled(
+ 'div',
+ {},
+ {
+ name: 'MuiAlert',
+ slot: 'Action',
+ },
+)({
+ display: 'flex',
+ alignItems: 'center',
+ marginLeft: 'auto',
+ paddingLeft: 16,
+ marginRight: -8,
+});
const defaultIconMapping = {
success: ,
@@ -150,11 +140,11 @@ const defaultIconMapping = {
info: ,
};
-const Alert = React.forwardRef(function Alert(props, ref) {
+const Alert = React.forwardRef(function Alert(inProps, ref) {
+ const props = useThemeProps({ props: inProps, name: 'MuiAlert' });
const {
action,
children,
- classes,
className,
closeText = 'Close',
color,
@@ -167,42 +157,36 @@ const Alert = React.forwardRef(function Alert(props, ref) {
...other
} = props;
- const themeVariantsClasses = useThemeVariants(
- {
- ...props,
- closeText,
- iconMapping,
- role,
- severity,
- variant,
- },
- 'MuiAlert',
- );
+ const styleProps = {
+ ...other,
+ variant,
+ color,
+ severity,
+ };
+
+ const classes = useUtilityClasses(styleProps);
return (
-
{icon !== false ? (
-
+
{icon || iconMapping[severity] || defaultIconMapping[severity]}
-
+
) : null}
- {children}
- {action != null ? {action}
: null}
+
+ {children}
+
+ {action != null ? {action} : null}
{action == null && onClose ? (
-
+
) : null}
-
+
);
});
@@ -284,6 +268,10 @@ Alert.propTypes = {
* @default 'success'
*/
severity: PropTypes.oneOf(['error', 'info', 'success', 'warning']),
+ /**
+ * The system prop that allows defining system overrides as well as additional CSS styles.
+ */
+ sx: PropTypes.object,
/**
* The variant to use.
* @default 'standard'
@@ -294,4 +282,4 @@ Alert.propTypes = {
]),
};
-export default withStyles(styles, { name: 'MuiAlert' })(Alert);
+export default Alert;
diff --git a/packages/material-ui/src/Alert/Alert.test.js b/packages/material-ui/src/Alert/Alert.test.js
index 635ea6c1612023..6dd3f8573aa285 100644
--- a/packages/material-ui/src/Alert/Alert.test.js
+++ b/packages/material-ui/src/Alert/Alert.test.js
@@ -1,21 +1,20 @@
import * as React from 'react';
-import { getClasses, createMount, describeConformance } from 'test/utils';
+import { createMount, describeConformanceV5 } from 'test/utils';
+import classes from './alertClasses';
import Paper from '../Paper';
import Alert from './Alert';
describe('', () => {
const mount = createMount();
- let classes;
- before(() => {
- classes = getClasses();
- });
-
- describeConformance(, () => ({
+ describeConformanceV5(, () => ({
classes,
inheritComponent: Paper,
mount,
refInstanceof: window.HTMLDivElement,
- skip: ['componentProp'],
+ muiName: 'MuiAlert',
+ testVariantProps: { variant: 'standard', color: 'success' },
+ testDeepOverrides: { slotName: 'message', slotClassName: classes.message },
+ skip: ['componentsProp'],
}));
});
diff --git a/packages/material-ui/src/Alert/alertClasses.d.ts b/packages/material-ui/src/Alert/alertClasses.d.ts
new file mode 100644
index 00000000000000..0045864b3595e8
--- /dev/null
+++ b/packages/material-ui/src/Alert/alertClasses.d.ts
@@ -0,0 +1,24 @@
+export interface AlertClasses {
+ root: string;
+ action: string;
+ icon: string;
+ message: string;
+ filledSuccess: string;
+ filledInfo: string;
+ filledWarning: string;
+ filledError: string;
+ outlinedSuccess: string;
+ outlinedInfo: string;
+ outlinedWarning: string;
+ outlinedError: string;
+ standardSuccess: string;
+ standardInfo: string;
+ standardWarning: string;
+ standardError: string;
+}
+
+declare const alertClasses: AlertClasses;
+
+export function getAlertUtilityClass(slot: string): string;
+
+export default alertClasses;
diff --git a/packages/material-ui/src/Alert/alertClasses.js b/packages/material-ui/src/Alert/alertClasses.js
new file mode 100644
index 00000000000000..fb3fc4518f5b4a
--- /dev/null
+++ b/packages/material-ui/src/Alert/alertClasses.js
@@ -0,0 +1,26 @@
+import { generateUtilityClass, generateUtilityClasses } from '@material-ui/unstyled';
+
+export function getAlertUtilityClass(slot) {
+ return generateUtilityClass('MuiAlert', slot);
+}
+
+const alertClasses = generateUtilityClasses('MuiAlert', [
+ 'root',
+ 'action',
+ 'icon',
+ 'message',
+ 'filledSuccess',
+ 'filledInfo',
+ 'filledWarning',
+ 'filledError',
+ 'outlinedSuccess',
+ 'outlinedInfo',
+ 'outlinedWarning',
+ 'outlinedError',
+ 'standardSuccess',
+ 'standardInfo',
+ 'standardWarning',
+ 'standardError',
+]);
+
+export default alertClasses;
diff --git a/packages/material-ui/src/Alert/index.d.ts b/packages/material-ui/src/Alert/index.d.ts
index f8bf7e6b67860c..1543777bf847c1 100644
--- a/packages/material-ui/src/Alert/index.d.ts
+++ b/packages/material-ui/src/Alert/index.d.ts
@@ -1,2 +1,5 @@
export { default } from './Alert';
export * from './Alert';
+
+export { default as alertClasses } from './alertClasses';
+export * from './alertClasses';
diff --git a/packages/material-ui/src/Alert/index.js b/packages/material-ui/src/Alert/index.js
index becaea750b71e9..ae354db3f6bcac 100644
--- a/packages/material-ui/src/Alert/index.js
+++ b/packages/material-ui/src/Alert/index.js
@@ -1 +1,4 @@
export { default } from './Alert';
+
+export { default as alertClasses } from './alertClasses';
+export * from './alertClasses';