diff --git a/docs/pages/material-ui/api/link.json b/docs/pages/material-ui/api/link.json index 64a6aef9859d7f..a277ca0f21a218 100644 --- a/docs/pages/material-ui/api/link.json +++ b/docs/pages/material-ui/api/link.json @@ -2,7 +2,13 @@ "props": { "children": { "type": { "name": "node" } }, "classes": { "type": { "name": "object" }, "additionalInfo": { "cssApi": true } }, - "color": { "type": { "name": "any" }, "default": "'primary'" }, + "color": { + "type": { + "name": "union", + "description": "'primary'
| 'secondary'
| 'success'
| 'error'
| 'info'
| 'warning'
| 'textPrimary'
| 'textSecondary'
| 'textDisabled'
| string" + }, + "default": "'primary'" + }, "component": { "type": { "name": "custom", "description": "element type" } }, "sx": { "type": { diff --git a/docs/pages/material-ui/api/typography.json b/docs/pages/material-ui/api/typography.json index a86efbb836ab3e..5bc2114152dd81 100644 --- a/docs/pages/material-ui/api/typography.json +++ b/docs/pages/material-ui/api/typography.json @@ -9,6 +9,12 @@ }, "children": { "type": { "name": "node" } }, "classes": { "type": { "name": "object" }, "additionalInfo": { "cssApi": true } }, + "color": { + "type": { + "name": "union", + "description": "'primary'
| 'secondary'
| 'success'
| 'error'
| 'info'
| 'warning'
| 'textPrimary'
| 'textSecondary'
| 'textDisabled'
| string" + } + }, "component": { "type": { "name": "elementType" } }, "gutterBottom": { "type": { "name": "bool" }, "default": "false" }, "noWrap": { "type": { "name": "bool" }, "default": "false" }, diff --git a/docs/translations/api-docs/typography/typography.json b/docs/translations/api-docs/typography/typography.json index 369e9d2b613a5f..39506c3f3df3d2 100644 --- a/docs/translations/api-docs/typography/typography.json +++ b/docs/translations/api-docs/typography/typography.json @@ -4,6 +4,9 @@ "align": { "description": "Set the text-align on the component." }, "children": { "description": "The content of the component." }, "classes": { "description": "Override or extend the styles applied to the component." }, + "color": { + "description": "The color of the component. It supports both default and custom theme colors, which can be added as shown in the palette customization guide." + }, "component": { "description": "The component used for the root node. Either a string to use a HTML element or a component." }, diff --git a/packages/mui-material/src/Breadcrumbs/Breadcrumbs.js b/packages/mui-material/src/Breadcrumbs/Breadcrumbs.js index a398e73d9fd778..650644850712ac 100644 --- a/packages/mui-material/src/Breadcrumbs/Breadcrumbs.js +++ b/packages/mui-material/src/Breadcrumbs/Breadcrumbs.js @@ -183,7 +183,7 @@ const Breadcrumbs = React.forwardRef(function Breadcrumbs(inProps, ref) { { - + {/* TODO: system props did not catch this error. Add @ts-expect-error after it is fixed. */} diff --git a/packages/mui-material/src/InputAdornment/InputAdornment.js b/packages/mui-material/src/InputAdornment/InputAdornment.js index 58f8c75fbc7764..dcb85e41a1b8bc 100644 --- a/packages/mui-material/src/InputAdornment/InputAdornment.js +++ b/packages/mui-material/src/InputAdornment/InputAdornment.js @@ -139,7 +139,7 @@ const InputAdornment = React.forwardRef(function InputAdornment(inProps, ref) { {...other} > {typeof children === 'string' && !disableTypography ? ( - {children} + {children} ) : ( {/* To have the correct vertical alignment baseline */} diff --git a/packages/mui-material/src/Link/Link.js b/packages/mui-material/src/Link/Link.js index 895fb42716d157..a452e41828657e 100644 --- a/packages/mui-material/src/Link/Link.js +++ b/packages/mui-material/src/Link/Link.js @@ -11,7 +11,19 @@ import { styled, useTheme } from '../zero-styled'; import { useDefaultProps } from '../DefaultPropsProvider'; import Typography from '../Typography'; import linkClasses, { getLinkUtilityClass } from './linkClasses'; -import getTextDecoration, { colorTransformations } from './getTextDecoration'; +import getTextDecoration from './getTextDecoration'; + +const v6Colors = { + primary: true, + secondary: true, + error: true, + info: true, + success: true, + warning: true, + textPrimary: true, + textSecondary: true, + textDisabled: true, +}; const useUtilityClasses = (ownerState) => { const { classes, component, focusVisible, underline } = ownerState; @@ -90,6 +102,28 @@ const LinkRoot = styled(Typography, { : alpha(theme.palette[color].main, 0.4), }, })), + { + props: { underline: 'always', color: 'textPrimary' }, + style: { + '--Link-underlineColor': theme.vars + ? `rgba(${theme.vars.palette.text.primaryChannel} / 0.4)` + : alpha(theme.palette.text.primary, 0.4), + }, + }, + { + props: { underline: 'always', color: 'textSecondary' }, + style: { + '--Link-underlineColor': theme.vars + ? `rgba(${theme.vars.palette.text.secondaryChannel} / 0.4)` + : alpha(theme.palette.text.secondary, 0.4), + }, + }, + { + props: { underline: 'always', color: 'textDisabled' }, + style: { + '--Link-underlineColor': (theme.vars || theme).palette.text.disabled, + }, + }, { props: { component: 'button', @@ -183,13 +217,14 @@ const Link = React.forwardRef(function Link(inProps, ref) { variant={variant} {...other} sx={[ - ...(colorTransformations[color] === undefined ? [{ color }] : []), + ...(v6Colors[color] === undefined ? [{ color }] : []), ...(Array.isArray(sx) ? sx : [sx]), ]} style={{ ...other.style, ...(underline === 'always' && - color !== 'inherit' && { + color !== 'inherit' && + !v6Colors[color] && { '--Link-underlineColor': getTextDecoration({ theme, ownerState }), }), }} @@ -218,7 +253,20 @@ Link.propTypes /* remove-proptypes */ = { * The color of the link. * @default 'primary' */ - color: PropTypes /* @typescript-to-proptypes-ignore */.any, + color: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([ + PropTypes.oneOf([ + 'primary', + 'secondary', + 'success', + 'error', + 'info', + 'warning', + 'textPrimary', + 'textSecondary', + 'textDisabled', + ]), + PropTypes.string, + ]), /** * The component used for the root node. * Either a string to use a HTML element or a component. diff --git a/packages/mui-material/src/Link/getTextDecoration.test.js b/packages/mui-material/src/Link/getTextDecoration.test.js index cf15c993b1d48c..142b16a9499ad0 100644 --- a/packages/mui-material/src/Link/getTextDecoration.test.js +++ b/packages/mui-material/src/Link/getTextDecoration.test.js @@ -6,21 +6,6 @@ describe('getTextDecoration', () => { describe('without theme.vars', () => { const theme = createTheme(); - it('deprecated color', () => { - expect(getTextDecoration({ theme, ownerState: { color: 'textPrimary' } })).to.equal( - 'rgba(0, 0, 0, 0.4)', - ); - expect(getTextDecoration({ theme, ownerState: { color: 'textSecondary' } })).to.equal( - 'rgba(0, 0, 0, 0.4)', - ); - expect(getTextDecoration({ theme, ownerState: { color: 'primary' } })).to.equal(null); - expect(getTextDecoration({ theme, ownerState: { color: 'secondary' } })).to.equal(null); - expect(getTextDecoration({ theme, ownerState: { color: 'error' } })).to.equal(null); - expect(getTextDecoration({ theme, ownerState: { color: 'info' } })).to.equal(null); - expect(getTextDecoration({ theme, ownerState: { color: 'success' } })).to.equal(null); - expect(getTextDecoration({ theme, ownerState: { color: 'warning' } })).to.equal(null); - }); - it('system color', () => { expect(getTextDecoration({ theme, ownerState: { color: 'primary.main' } })).to.equal( 'rgba(25, 118, 210, 0.4)', @@ -73,21 +58,6 @@ describe('getTextDecoration', () => { }, }, }; - // in the application, the value will be CSS variable: `rgba(var(--the-color-channel) / 0.4)` - it('deprecated color', () => { - expect(getTextDecoration({ theme, ownerState: { color: 'textPrimary' } })).to.equal( - 'rgba(var(--palette-text-primaryChannel) / 0.4)', - ); - expect(getTextDecoration({ theme, ownerState: { color: 'textSecondary' } })).to.equal( - 'rgba(var(--palette-text-secondaryChannel) / 0.4)', - ); - expect(getTextDecoration({ theme, ownerState: { color: 'primary' } })).to.equal(null); - expect(getTextDecoration({ theme, ownerState: { color: 'secondary' } })).to.equal(null); - expect(getTextDecoration({ theme, ownerState: { color: 'error' } })).to.equal(null); - expect(getTextDecoration({ theme, ownerState: { color: 'info' } })).to.equal(null); - expect(getTextDecoration({ theme, ownerState: { color: 'success' } })).to.equal(null); - expect(getTextDecoration({ theme, ownerState: { color: 'warning' } })).to.equal(null); - }); it('system color', () => { expect(getTextDecoration({ theme, ownerState: { color: 'primary.main' } })).to.equal( diff --git a/packages/mui-material/src/Link/getTextDecoration.ts b/packages/mui-material/src/Link/getTextDecoration.ts index 517d8e77eaab23..8afec8d8a45927 100644 --- a/packages/mui-material/src/Link/getTextDecoration.ts +++ b/packages/mui-material/src/Link/getTextDecoration.ts @@ -2,19 +2,6 @@ import { getPath } from '@mui/system/style'; import { alpha } from '@mui/system/colorManipulator'; import type { Theme } from '../styles'; -// TODO v7: remove this transformation -export const colorTransformations: Record = { - textPrimary: 'text.primary', - textSecondary: 'text.secondary', - // For main palette, the color will be applied by the styles above. - primary: null, - secondary: null, - error: null, - info: null, - success: null, - warning: null, -}; - const getTextDecoration = ({ theme, ownerState, @@ -22,13 +9,7 @@ const getTextDecoration = ({ theme: T; ownerState: { color: string }; }) => { - let transformedColor = colorTransformations[ownerState.color]; - if (transformedColor === null) { - return null; - } - if (transformedColor === undefined) { - transformedColor = ownerState.color; - } + const transformedColor = ownerState.color; const color = (getPath(theme, `palette.${transformedColor}`, false) || ownerState.color) as string; const channelColor = getPath(theme, `palette.${transformedColor}Channel`) as string | null; diff --git a/packages/mui-material/src/ListItemText/ListItemText.js b/packages/mui-material/src/ListItemText/ListItemText.js index aa7256d91194ea..51379b3d523836 100644 --- a/packages/mui-material/src/ListItemText/ListItemText.js +++ b/packages/mui-material/src/ListItemText/ListItemText.js @@ -106,7 +106,7 @@ const ListItemText = React.forwardRef(function ListItemText(inProps, ref) { diff --git a/packages/mui-material/src/Typography/Typography.d.ts b/packages/mui-material/src/Typography/Typography.d.ts index e4ff039a9cac8c..f07841314f040f 100644 --- a/packages/mui-material/src/Typography/Typography.d.ts +++ b/packages/mui-material/src/Typography/Typography.d.ts @@ -1,14 +1,16 @@ import * as React from 'react'; import { OverridableStringUnion } from '@mui/types'; import { SxProps, SystemProps } from '@mui/system'; -import { Theme } from '../styles'; +import { Theme, TypeText } from '../styles'; import { OverrideProps, OverridableComponent } from '../OverridableComponent'; import { Variant } from '../styles/createTypography'; import { TypographyClasses } from './typographyClasses'; export interface TypographyPropsVariantOverrides {} -export interface TypographyOwnProps extends SystemProps { +export interface TypographyPropsColorOverrides {} + +export interface TypographyOwnProps extends Omit, 'color'> { /** * Set the text-align on the component. * @default 'inherit' @@ -22,6 +24,23 @@ export interface TypographyOwnProps extends SystemProps { * Override or extend the styles applied to the component. */ classes?: Partial; + /** + * The color of the component. + * It supports both default and custom theme colors, which can be added as shown in the + * [palette customization guide](https://mui.com/material-ui/customization/palette/#custom-colors). + */ + color?: + | OverridableStringUnion< + | 'primary' + | 'secondary' + | 'success' + | 'error' + | 'info' + | 'warning' + | `text${Capitalize}`, + TypographyPropsColorOverrides + > + | (string & {}); // to work with v5 color prop type which allows any string /** * If `true`, the text will have a bottom margin. * @default false diff --git a/packages/mui-material/src/Typography/Typography.js b/packages/mui-material/src/Typography/Typography.js index c5b7391526137c..9ba5bdffcec985 100644 --- a/packages/mui-material/src/Typography/Typography.js +++ b/packages/mui-material/src/Typography/Typography.js @@ -8,6 +8,18 @@ import { useDefaultProps } from '../DefaultPropsProvider'; import capitalize from '../utils/capitalize'; import { getTypographyUtilityClass } from './typographyClasses'; +const v6Colors = { + primary: true, + secondary: true, + error: true, + info: true, + success: true, + warning: true, + textPrimary: true, + textSecondary: true, + textDisabled: true, +}; + const extendSxProp = internal_createExtendSxProp(); const useUtilityClasses = (ownerState) => { @@ -70,6 +82,14 @@ export const TypographyRoot = styled('span', { color: (theme.vars || theme).palette[color].main, }, })), + ...Object.entries(theme.palette?.text || {}) + .filter(([, value]) => typeof value === 'string') + .map(([color]) => ({ + props: { color: `text${capitalize(color)}` }, + style: { + color: (theme.vars || theme).palette.text[color], + }, + })), { props: ({ ownerState }) => ownerState.align !== 'inherit', style: { @@ -113,27 +133,13 @@ const defaultVariantMapping = { inherit: 'p', }; -// TODO v7: remove this transformation and `extendSxProp` -const colorTransformations = { - textPrimary: 'text.primary', - textSecondary: 'text.secondary', - // For the main palette, the color will be applied by the `...Object.entries(theme.palette)` clause in the TypographyRoot's styles - primary: null, - secondary: null, - error: null, - info: null, - success: null, - warning: null, -}; - const Typography = React.forwardRef(function Typography(inProps, ref) { const { color, ...themeProps } = useDefaultProps({ props: inProps, name: 'MuiTypography' }); - const textColor = colorTransformations[color]; + const isSxColor = !v6Colors[color]; + // TODO: Remove `extendSxProp` in v7 const props = extendSxProp({ ...themeProps, - ...(textColor !== null && { - color: textColor || color, - }), + ...(isSxColor && { color }), }); const { @@ -205,6 +211,25 @@ Typography.propTypes /* remove-proptypes */ = { * @ignore */ className: PropTypes.string, + /** + * The color of the component. + * It supports both default and custom theme colors, which can be added as shown in the + * [palette customization guide](https://mui.com/material-ui/customization/palette/#custom-colors). + */ + color: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([ + PropTypes.oneOf([ + 'primary', + 'secondary', + 'success', + 'error', + 'info', + 'warning', + 'textPrimary', + 'textSecondary', + 'textDisabled', + ]), + PropTypes.string, + ]), /** * The component used for the root node. * Either a string to use a HTML element or a component. diff --git a/packages/mui-material/src/Typography/typography.spec.tsx b/packages/mui-material/src/Typography/typography.spec.tsx index e5a04e944952d7..c2a8be36a0960e 100644 --- a/packages/mui-material/src/Typography/typography.spec.tsx +++ b/packages/mui-material/src/Typography/typography.spec.tsx @@ -32,7 +32,8 @@ const typographyTest = () => { - + + {/* TODO: system props did not catch this error. Add @ts-expect-error after it is fixed. */}