From 0d290f8850d18965cadd6a85a9791f9a79fe6882 Mon Sep 17 00:00:00 2001 From: Siriwat K Date: Tue, 8 Nov 2022 22:16:22 +0700 Subject: [PATCH] [Joy] Miscellaneous fixes (#35044) --- .../joy/components/link/DecoratorExamples.js | 4 +- .../data/joy/components/select/SelectUsage.js | 22 ---- .../typography/DecoratorExamples.js | 3 +- .../components/typography/NestedTypography.js | 2 +- .../typography/TypographyDecorators.js | 2 +- .../dark-mode/IdentifySystemMode.js | 1 - .../dark-mode/IdentifySystemMode.tsx | 1 - docs/src/modules/components/JoyUsageDemo.tsx | 107 +++++++++--------- .../src/CircularProgress/CircularProgress.tsx | 17 ++- .../mui-joy/src/CssBaseline/CssBaseline.tsx | 7 +- .../mui-joy/src/FormControl/FormControl.tsx | 2 +- packages/mui-joy/src/GlobalStyles/index.ts | 7 +- packages/mui-joy/src/Input/Input.tsx | 24 +++- packages/mui-joy/src/Link/Link.tsx | 9 +- packages/mui-joy/src/List/List.tsx | 2 +- .../src/ListItemButton/ListItemButton.tsx | 3 +- .../src/ListSubheader/ListSubheader.tsx | 12 +- .../src/ListSubheader/ListSubheaderProps.ts | 2 - packages/mui-joy/src/Menu/Menu.tsx | 4 +- packages/mui-joy/src/MenuItem/MenuItem.tsx | 4 +- packages/mui-joy/src/MenuList/MenuList.tsx | 4 +- .../mui-joy/src/ModalClose/ModalClose.tsx | 4 +- packages/mui-joy/src/Option/Option.tsx | 4 +- packages/mui-joy/src/Select/Select.tsx | 12 +- packages/mui-joy/src/Tab/Tab.tsx | 4 +- packages/mui-joy/src/TabList/TabList.tsx | 4 +- packages/mui-joy/src/TabList/TabListProps.ts | 12 +- packages/mui-joy/src/Textarea/Textarea.tsx | 21 +++- .../mui-joy/src/Typography/Typography.tsx | 27 +++-- .../mui-joy/src/styles/CssVarsProvider.tsx | 1 + 30 files changed, 183 insertions(+), 145 deletions(-) diff --git a/docs/data/joy/components/link/DecoratorExamples.js b/docs/data/joy/components/link/DecoratorExamples.js index e62804bb63bffc..2b2a6842f12aab 100644 --- a/docs/data/joy/components/link/DecoratorExamples.js +++ b/docs/data/joy/components/link/DecoratorExamples.js @@ -13,7 +13,7 @@ const circulate = keyframes({ }, }); -export default function LinkScales() { +export default function DecoratorExamples() { return ( + HIRING! } diff --git a/docs/data/joy/components/select/SelectUsage.js b/docs/data/joy/components/select/SelectUsage.js index cf55f6ab62e1af..7bd4f3d1652cf0 100644 --- a/docs/data/joy/components/select/SelectUsage.js +++ b/docs/data/joy/components/select/SelectUsage.js @@ -1,9 +1,7 @@ import * as React from 'react'; import Select from '@mui/joy/Select'; import Option from '@mui/joy/Option'; -import IconButton from '@mui/joy/IconButton'; import JoyUsageDemo from 'docs/src/modules/components/JoyUsageDemo'; -import CloseRounded from '@mui/icons-material/CloseRounded'; export default function SelectUsage() { const [value, setValue] = React.useState(null); @@ -50,26 +48,6 @@ export default function SelectUsage() { action={action} value={value} onChange={(e, newValue) => setValue(newValue)} - {...(value && { - endDecorator: ( - { - event.stopPropagation(); - }} - onClick={() => { - setValue(null); - action.current?.focusVisible(); - }} - > - - - ), - indicator: null, - })} sx={{ minWidth: 160, mb: 20 }} > diff --git a/docs/data/joy/components/typography/DecoratorExamples.js b/docs/data/joy/components/typography/DecoratorExamples.js index c54ded0fe83402..b157ef5f7537f8 100644 --- a/docs/data/joy/components/typography/DecoratorExamples.js +++ b/docs/data/joy/components/typography/DecoratorExamples.js @@ -3,7 +3,7 @@ import Box from '@mui/joy/Box'; import Typography from '@mui/joy/Typography'; import InfoOutlined from '@mui/icons-material/InfoOutlined'; -export default function TypographyScales() { +export default function DecoratorExamples() { return ( + Typography lets you create nested{' '} typography. Use your{' '} diff --git a/docs/data/joy/components/typography/TypographyDecorators.js b/docs/data/joy/components/typography/TypographyDecorators.js index fc2edc14db73e4..dca2ee5951faa7 100644 --- a/docs/data/joy/components/typography/TypographyDecorators.js +++ b/docs/data/joy/components/typography/TypographyDecorators.js @@ -4,7 +4,7 @@ import Typography from '@mui/joy/Typography'; import Chip from '@mui/joy/Chip'; import InfoOutlined from '@mui/icons-material/InfoOutlined'; -export default function TypographyScales() { +export default function TypographyDecorators() { return ( } mb={2}> diff --git a/docs/data/joy/customization/dark-mode/IdentifySystemMode.js b/docs/data/joy/customization/dark-mode/IdentifySystemMode.js index 753c05a966202d..c7dc70ca688797 100644 --- a/docs/data/joy/customization/dark-mode/IdentifySystemMode.js +++ b/docs/data/joy/customization/dark-mode/IdentifySystemMode.js @@ -23,7 +23,6 @@ const Identifier = () => { fontSize="md" sx={{ boxShadow: 'sm', - py: 0.25, fontFamily: 'code', bgcolor: 'background.level1', }} diff --git a/docs/data/joy/customization/dark-mode/IdentifySystemMode.tsx b/docs/data/joy/customization/dark-mode/IdentifySystemMode.tsx index 753c05a966202d..c7dc70ca688797 100644 --- a/docs/data/joy/customization/dark-mode/IdentifySystemMode.tsx +++ b/docs/data/joy/customization/dark-mode/IdentifySystemMode.tsx @@ -23,7 +23,6 @@ const Identifier = () => { fontSize="md" sx={{ boxShadow: 'sm', - py: 0.25, fontFamily: 'code', bgcolor: 'background.level1', }} diff --git a/docs/src/modules/components/JoyUsageDemo.tsx b/docs/src/modules/components/JoyUsageDemo.tsx index a967ff70d41560..4d01d9a331a13a 100644 --- a/docs/src/modules/components/JoyUsageDemo.tsx +++ b/docs/src/modules/components/JoyUsageDemo.tsx @@ -13,7 +13,6 @@ import Radio, { radioClasses } from '@mui/joy/Radio'; import RadioGroup from '@mui/joy/RadioGroup'; import Select from '@mui/joy/Select'; import Sheet from '@mui/joy/Sheet'; -import { ColorPaletteProp } from '@mui/joy/styles'; import Switch from '@mui/joy/Switch'; import TextField from '@mui/joy/TextField'; import Typography from '@mui/joy/Typography'; @@ -436,63 +435,67 @@ export default function JoyUsageDemo({ } sx={{ flexWrap: 'wrap', gap: 1.5 }} > - {['primary', 'neutral', 'danger', 'info', 'success', 'warning'].map((value) => { - const checked = resolvedValue === value; - return ( - - { + const checked = resolvedValue === value; + return ( + - {checked && ( - + - )} - - ); - })} + {checked && ( + + )} + + ); + }, + )} ); diff --git a/packages/mui-joy/src/CircularProgress/CircularProgress.tsx b/packages/mui-joy/src/CircularProgress/CircularProgress.tsx index 04b4a1c6a36b30..ec6cb7d6d76de9 100644 --- a/packages/mui-joy/src/CircularProgress/CircularProgress.tsx +++ b/packages/mui-joy/src/CircularProgress/CircularProgress.tsx @@ -91,6 +91,8 @@ const CircularProgressRoot = styled('span', { '--_thickness-diff': 'calc(var(--CircularProgress-track-thickness) - var(--CircularProgress-progress-thickness))', '--_inner-size': 'calc(var(--_root-size) - 2 * var(--variant-borderWidth))', + '--_outlined-inset': + 'max(var(--CircularProgress-track-thickness), var(--CircularProgress-progress-thickness))', width: 'var(--_root-size)', height: 'var(--_root-size)', borderRadius: 'var(--_root-size)', @@ -109,6 +111,19 @@ const CircularProgressRoot = styled('span', { fontSize: 'calc(0.2 * var(--_root-size))', }), ...rest, + ...(ownerState.variant === 'outlined' && { + '&:before': { + content: '""', + display: 'block', + position: 'absolute', + borderRadius: 'inherit', + top: 'var(--_outlined-inset)', + left: 'var(--_outlined-inset)', + right: 'var(--_outlined-inset)', + bottom: 'var(--_outlined-inset)', + ...rest, + }, + }), }; }); @@ -169,7 +184,7 @@ const CircularProgressProgress = styled('circle', { : css` animation: var( --CircularProgress-circulation, - 0.5s linear 0s infinite normal none running + 0.8s linear 0s infinite normal none running ) ${circulate}; `, diff --git a/packages/mui-joy/src/CssBaseline/CssBaseline.tsx b/packages/mui-joy/src/CssBaseline/CssBaseline.tsx index 164e15cff7b3fe..9dd20792f29a63 100644 --- a/packages/mui-joy/src/CssBaseline/CssBaseline.tsx +++ b/packages/mui-joy/src/CssBaseline/CssBaseline.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import { GlobalStyles } from '@mui/system'; import { Theme, DefaultColorScheme, ColorSystem } from '../styles/types'; +import { Components } from '../styles/components'; import { CssBaselineProps } from './CssBaselineProps'; /** @@ -23,6 +24,9 @@ function CssBaseline({ children, disableColorScheme = false }: CssBaselineProps) }; }); } + const defaultTypographyLevel = + (theme as unknown as { components: Components }).components?.JoyTypography + ?.defaultProps?.level ?? 'body1'; return { html: { WebkitFontSmoothing: 'antialiased', @@ -42,7 +46,8 @@ function CssBaseline({ children, disableColorScheme = false }: CssBaselineProps) body: { margin: 0, // Remove the margin in all browsers. color: theme.vars.palette.text.primary, - ...(theme.typography.body1 as any), + fontFamily: theme.vars.fontFamily.body, + ...(theme.typography as any)[defaultTypographyLevel], backgroundColor: theme.vars.palette.background.body, '@media print': { // Save printer ink. diff --git a/packages/mui-joy/src/FormControl/FormControl.tsx b/packages/mui-joy/src/FormControl/FormControl.tsx index 88f4606b367157..a0b2cf6077deec 100644 --- a/packages/mui-joy/src/FormControl/FormControl.tsx +++ b/packages/mui-joy/src/FormControl/FormControl.tsx @@ -32,7 +32,7 @@ export const FormControlRoot = styled('div', { })<{ ownerState: FormControlOwnerState }>(({ theme, ownerState }) => ({ '--FormLabel-margin': ownerState.orientation === 'horizontal' ? '0 0.375rem 0 0' : '0 0 0.25rem 0', - '--FormLabel-alignSelf': 'flex-start', + '--FormLabel-alignSelf': ownerState.orientation === 'horizontal' ? 'align-items' : 'flex-start', '--FormHelperText-margin': '0.375rem 0 0 0', '--FormLabel-asterisk-color': theme.vars.palette.danger[500], '--FormHelperText-color': theme.vars.palette[ownerState.color!]?.[500], diff --git a/packages/mui-joy/src/GlobalStyles/index.ts b/packages/mui-joy/src/GlobalStyles/index.ts index 63d5f8f365ad1a..9e2fd2d125efb8 100644 --- a/packages/mui-joy/src/GlobalStyles/index.ts +++ b/packages/mui-joy/src/GlobalStyles/index.ts @@ -1 +1,6 @@ -export { GlobalStyles as default } from '@mui/system'; +import { GlobalStyles as SystemGlobalStyles } from '@mui/system'; +import { Theme } from '../styles/types'; + +const GlobalStyles = SystemGlobalStyles; + +export default GlobalStyles; diff --git a/packages/mui-joy/src/Input/Input.tsx b/packages/mui-joy/src/Input/Input.tsx index 06353aa3f932ae..4896090d31b2e5 100644 --- a/packages/mui-joy/src/Input/Input.tsx +++ b/packages/mui-joy/src/Input/Input.tsx @@ -36,6 +36,7 @@ export const StyledInputRoot = styled('div')<{ ownerState: InputOwnerState }>( { '--Input-radius': theme.vars.radius.sm, '--Input-gap': '0.5rem', + '--Input-placeholderColor': 'inherit', '--Input-placeholderOpacity': 0.5, '--Input-focusedThickness': theme.vars.focus.thickness, ...(ownerState.color === 'context' @@ -153,10 +154,25 @@ export const StyledInputHtml = styled('input')<{ ownerState: InputOwnerState }>( WebkitBackgroundClip: 'text', // remove autofill background WebkitTextFillColor: 'currentColor', }, - '&::-webkit-input-placeholder': { opacity: 'var(--Input-placeholderOpacity)', color: 'inherit' }, - '&::-moz-placeholder': { opacity: 'var(--Input-placeholderOpacity)', color: 'inherit' }, // Firefox 19+ - '&:-ms-input-placeholder': { opacity: 'var(--Input-placeholderOpacity)', color: 'inherit' }, // IE11 - '&::-ms-input-placeholder': { opacity: 'var(--Input-placeholderOpacity)', color: 'inherit' }, // Edge + '&::-webkit-input-placeholder': { + color: 'var(--Input-placeholderColor)', + opacity: 'var(--Input-placeholderOpacity)', + }, + '&::-moz-placeholder': { + // Firefox 19+ + color: 'var(--Input-placeholderColor)', + opacity: 'var(--Input-placeholderOpacity)', + }, + '&:-ms-input-placeholder': { + // IE11 + color: 'var(--Input-placeholderColor)', + opacity: 'var(--Input-placeholderOpacity)', + }, + '&::-ms-input-placeholder': { + // Edge + color: 'var(--Input-placeholderColor)', + opacity: 'var(--Input-placeholderOpacity)', + }, }); export const StyledInputStartDecorator = styled('span')<{ ownerState: InputOwnerState }>( diff --git a/packages/mui-joy/src/Link/Link.tsx b/packages/mui-joy/src/Link/Link.tsx index c06c07a82dbd42..7eceb43ca025da 100644 --- a/packages/mui-joy/src/Link/Link.tsx +++ b/packages/mui-joy/src/Link/Link.tsx @@ -41,7 +41,7 @@ const StartDecorator = styled('span', { overridesResolver: (props, styles) => styles.startDecorator, })<{ ownerState: LinkOwnerState }>({ display: 'inline-flex', - marginInlineEnd: 'clamp(4px, var(--Link-gap, 0.25em), 0.5rem)', + marginInlineEnd: 'clamp(4px, var(--Link-gap, 0.375em), 0.75rem)', }); const EndDecorator = styled('span', { @@ -50,7 +50,7 @@ const EndDecorator = styled('span', { overridesResolver: (props, styles) => styles.endDecorator, })<{ ownerState: LinkOwnerState }>({ display: 'inline-flex', - marginInlineStart: 'clamp(4px, var(--Link-gap, 0.25em), 0.5rem)', + marginInlineStart: 'clamp(4px, var(--Link-gap, 0.25em), 0.5rem)', // for end decorator, 0.25em looks better. }); const LinkRoot = styled('a', { @@ -98,9 +98,10 @@ const LinkRoot = styled('a', { } / var(--Link-underlineOpacity, 0.72))`, ...(ownerState.variant ? { - paddingInline: '0.25em', // better than left, right because it also works with writing mode. + paddingBlock: 'min(0.15em, 4px)', + paddingInline: '0.375em', // better than left, right because it also works with writing mode. ...(!ownerState.nested && { - marginInline: '-0.25em', + marginInline: '-0.375em', }), } : { diff --git a/packages/mui-joy/src/List/List.tsx b/packages/mui-joy/src/List/List.tsx index 7d1a9dffbf7e09..b4af0a8cde9116 100644 --- a/packages/mui-joy/src/List/List.tsx +++ b/packages/mui-joy/src/List/List.tsx @@ -136,7 +136,7 @@ export const StyledList = styled('ul')<{ ownerState: ListOwnerState }>(({ theme, ]; }); -export const ListRoot = styled(StyledList, { +const ListRoot = styled(StyledList, { name: 'JoyList', slot: 'Root', overridesResolver: (props, styles) => styles.root, diff --git a/packages/mui-joy/src/ListItemButton/ListItemButton.tsx b/packages/mui-joy/src/ListItemButton/ListItemButton.tsx index 169cf1da3d4fe6..c2565af8fb3ecd 100644 --- a/packages/mui-joy/src/ListItemButton/ListItemButton.tsx +++ b/packages/mui-joy/src/ListItemButton/ListItemButton.tsx @@ -97,8 +97,7 @@ export const StyledListItemButton = styled('div')<{ ownerState: ListItemButtonOw ], ); -// MenuItem uses ListItemButtonRoot (not the whole ListItemButton) to leverage only styles and CSS variables. -export const ListItemButtonRoot = styled(StyledListItemButton, { +const ListItemButtonRoot = styled(StyledListItemButton, { name: 'JoyListItemButton', slot: 'Root', overridesResolver: (props, styles) => styles.root, diff --git a/packages/mui-joy/src/ListSubheader/ListSubheader.tsx b/packages/mui-joy/src/ListSubheader/ListSubheader.tsx index acb3162e209e90..0ac1ce43fe88e0 100644 --- a/packages/mui-joy/src/ListSubheader/ListSubheader.tsx +++ b/packages/mui-joy/src/ListSubheader/ListSubheader.tsx @@ -47,8 +47,10 @@ const ListSubheaderRoot = styled('div', { zIndex: 1, background: 'var(--List-item-stickyBackground)', }), + color: ownerState.color + ? `rgba(${theme.vars.palette[ownerState.color!]?.mainChannel} / 1)` + : theme.vars.palette.text.tertiary, ...theme.variants[ownerState.variant!]?.[ownerState.color!], - color: theme.vars.palette[ownerState.color!]?.[500], // make the subheader less contrast })); const ListSubheader = React.forwardRef(function ListSubheader(inProps, ref) { @@ -63,8 +65,8 @@ const ListSubheader = React.forwardRef(function ListSubheader(inProps, ref) { children, id: idOverride, sticky = false, - variant = 'plain', - color = 'neutral', + variant, + color, ...other } = props; const id = useId(idOverride); @@ -81,7 +83,7 @@ const ListSubheader = React.forwardRef(function ListSubheader(inProps, ref) { id, sticky, variant, - color, + color: variant ? color ?? 'neutral' : color, }; const classes = useUtilityClasses(ownerState); @@ -115,7 +117,6 @@ ListSubheader.propTypes /* remove-proptypes */ = { className: PropTypes.string, /** * The color of the component. It supports those theme colors that make sense for this component. - * @default 'neutral' */ color: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([ PropTypes.oneOf(['danger', 'info', 'neutral', 'primary', 'success', 'warning']), @@ -145,7 +146,6 @@ ListSubheader.propTypes /* remove-proptypes */ = { ]), /** * The variant to use. - * @default 'plain' */ variant: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([ PropTypes.oneOf(['outlined', 'plain', 'soft', 'solid']), diff --git a/packages/mui-joy/src/ListSubheader/ListSubheaderProps.ts b/packages/mui-joy/src/ListSubheader/ListSubheaderProps.ts index 2ad081aea83c08..049653316bd689 100644 --- a/packages/mui-joy/src/ListSubheader/ListSubheaderProps.ts +++ b/packages/mui-joy/src/ListSubheader/ListSubheaderProps.ts @@ -12,7 +12,6 @@ export interface ListSubheaderTypeMap

; /** @@ -30,7 +29,6 @@ export interface ListSubheaderTypeMap

; }; diff --git a/packages/mui-joy/src/Menu/Menu.tsx b/packages/mui-joy/src/Menu/Menu.tsx index 9c48b30966bd50..ac6f32b32b89f9 100644 --- a/packages/mui-joy/src/Menu/Menu.tsx +++ b/packages/mui-joy/src/Menu/Menu.tsx @@ -6,7 +6,7 @@ import composeClasses from '@mui/base/composeClasses'; import { useSlotProps } from '@mui/base/utils'; import { useMenu, MenuUnstyledContext, MenuUnstyledContextType } from '@mui/base/MenuUnstyled'; import PopperUnstyled from '@mui/base/PopperUnstyled'; -import { ListRoot } from '../List/List'; +import { StyledList } from '../List/List'; import ListProvider, { scopedVariables } from '../List/ListProvider'; import { styled, useThemeProps } from '../styles'; import { MenuTypeMap, MenuProps, MenuOwnerState } from './MenuProps'; @@ -27,7 +27,7 @@ const useUtilityClasses = (ownerState: MenuProps) => { return composeClasses(slots, getMenuUtilityClass, {}); }; -const MenuRoot = styled(ListRoot, { +const MenuRoot = styled(StyledList, { name: 'JoyMenu', slot: 'Root', overridesResolver: (props, styles) => styles.root, diff --git a/packages/mui-joy/src/MenuItem/MenuItem.tsx b/packages/mui-joy/src/MenuItem/MenuItem.tsx index 7aeb20eeef5cb5..5d7598cbf394f5 100644 --- a/packages/mui-joy/src/MenuItem/MenuItem.tsx +++ b/packages/mui-joy/src/MenuItem/MenuItem.tsx @@ -4,7 +4,7 @@ import { unstable_capitalize as capitalize } from '@mui/utils'; import composeClasses from '@mui/base/composeClasses'; import { useSlotProps } from '@mui/base/utils'; import { useMenuItem } from '@mui/base/MenuItemUnstyled'; -import { ListItemButtonRoot } from '../ListItemButton/ListItemButton'; +import { StyledListItemButton } from '../ListItemButton/ListItemButton'; import { styled, useThemeProps } from '../styles'; import { getMenuItemUtilityClass } from './menuItemClasses'; import { @@ -33,7 +33,7 @@ const useUtilityClasses = (ownerState: MenuItemProps & { focusVisible?: boolean return composedClasses; }; -const MenuItemRoot = styled(ListItemButtonRoot, { +const MenuItemRoot = styled(StyledListItemButton, { name: 'JoyMenuItem', slot: 'Root', overridesResolver: (props, styles) => styles.root, diff --git a/packages/mui-joy/src/MenuList/MenuList.tsx b/packages/mui-joy/src/MenuList/MenuList.tsx index f1f06d1dc21b53..d36f7f48b22846 100644 --- a/packages/mui-joy/src/MenuList/MenuList.tsx +++ b/packages/mui-joy/src/MenuList/MenuList.tsx @@ -6,7 +6,7 @@ import composeClasses from '@mui/base/composeClasses'; import { useSlotProps } from '@mui/base/utils'; import { useMenu, MenuUnstyledContext, MenuUnstyledContextType } from '@mui/base/MenuUnstyled'; import { styled, useThemeProps } from '../styles'; -import { ListRoot } from '../List/List'; +import { StyledList } from '../List/List'; import ListProvider, { scopedVariables } from '../List/ListProvider'; import { MenuListProps, MenuListOwnerState, MenuListTypeMap } from './MenuListProps'; import { getMenuListUtilityClass } from './menuListClasses'; @@ -25,7 +25,7 @@ const useUtilityClasses = (ownerState: MenuListProps) => { return composeClasses(slots, getMenuListUtilityClass, {}); }; -const MenuListRoot = styled(ListRoot, { +const MenuListRoot = styled(StyledList, { name: 'MuiMenuList', slot: 'Root', overridesResolver: (props, styles) => styles.root, diff --git a/packages/mui-joy/src/ModalClose/ModalClose.tsx b/packages/mui-joy/src/ModalClose/ModalClose.tsx index 6b8d88ac8b68d2..48dd83236fca04 100644 --- a/packages/mui-joy/src/ModalClose/ModalClose.tsx +++ b/packages/mui-joy/src/ModalClose/ModalClose.tsx @@ -6,7 +6,7 @@ import { unstable_capitalize as capitalize } from '@mui/utils'; import { useSlotProps } from '@mui/base/utils'; import { useButton } from '@mui/base/ButtonUnstyled'; import { useThemeProps, styled } from '../styles'; -import { IconButtonRoot } from '../IconButton/IconButton'; +import { StyledIconButton } from '../IconButton/IconButton'; import { getModalCloseUtilityClass } from './modalCloseClasses'; import { ModalCloseProps, ModalCloseTypeMap } from './ModalCloseProps'; import CloseIcon from '../internal/svg-icons/Close'; @@ -31,7 +31,7 @@ const useUtilityClasses = (ownerState: ModalCloseProps & { focusVisible?: boolea return composeClasses(slots, getModalCloseUtilityClass, {}); }; -export const ModalCloseRoot = styled(IconButtonRoot, { +export const ModalCloseRoot = styled(StyledIconButton, { name: 'JoyModalClose', slot: 'Root', overridesResolver: (props, styles) => styles.root, diff --git a/packages/mui-joy/src/Option/Option.tsx b/packages/mui-joy/src/Option/Option.tsx index 4538b5cb89802a..c7a8ab4683f327 100644 --- a/packages/mui-joy/src/Option/Option.tsx +++ b/packages/mui-joy/src/Option/Option.tsx @@ -4,7 +4,7 @@ import { unstable_useForkRef as useForkRef } from '@mui/utils'; import composeClasses from '@mui/base/composeClasses'; import { useSlotProps } from '@mui/base/utils'; import { SelectUnstyledContext } from '@mui/base/SelectUnstyled'; -import { ListItemButtonRoot } from '../ListItemButton/ListItemButton'; +import { StyledListItemButton } from '../ListItemButton/ListItemButton'; import { styled, useThemeProps } from '../styles'; import { OptionOwnerState, ExtendOption, OptionTypeMap } from './OptionProps'; import optionClasses, { getOptionUtilityClass } from './optionClasses'; @@ -20,7 +20,7 @@ const useUtilityClasses = (ownerState: OptionOwnerState) => { return composeClasses(slots, getOptionUtilityClass, {}); }; -const OptionRoot = styled(ListItemButtonRoot as unknown as 'button', { +const OptionRoot = styled(StyledListItemButton as unknown as 'button', { name: 'JoyOption', slot: 'Root', overridesResolver: (props, styles) => styles.root, diff --git a/packages/mui-joy/src/Select/Select.tsx b/packages/mui-joy/src/Select/Select.tsx index 8fb32af35e4371..e51f9f4006ff5c 100644 --- a/packages/mui-joy/src/Select/Select.tsx +++ b/packages/mui-joy/src/Select/Select.tsx @@ -16,7 +16,7 @@ import { import type { SelectChild, SelectOption } from '@mui/base/SelectUnstyled'; import { useSlotProps } from '@mui/base/utils'; import composeClasses from '@mui/base/composeClasses'; -import { ListRoot } from '../List/List'; +import { StyledList } from '../List/List'; import ListProvider, { scopedVariables } from '../List/ListProvider'; import Unfold from '../internal/svg-icons/Unfold'; import { styled, useThemeProps } from '../styles'; @@ -85,7 +85,9 @@ const SelectRoot = styled('div', { '--Select-focusedThickness': theme.vars.focus.thickness, '--Select-focusedHighlight': theme.vars.palette[ownerState.color === 'neutral' ? 'primary' : ownerState.color!]?.[500], - '--Select-indicator-color': theme.vars.palette.text.tertiary, + '--Select-indicator-color': variantStyle?.backgroundColor + ? variantStyle?.color + : theme.vars.palette.text.tertiary, ...(ownerState.size === 'sm' && { '--Select-minHeight': '2rem', '--Select-paddingInline': '0.5rem', @@ -125,6 +127,9 @@ const SelectRoot = styled('div', { ...(!variantStyle.backgroundColor && { backgroundColor: theme.vars.palette.background.surface, }), + ...(ownerState.size && { + paddingBlock: { sm: 2, md: 3, lg: 4 }[ownerState.size], // the padding-block act as a minimum spacing between content and root element + }), paddingInline: `var(--Select-paddingInline)`, fontFamily: theme.vars.fontFamily.body, fontSize: theme.vars.fontSize.md, @@ -189,13 +194,14 @@ const SelectButton = styled('button', { display: 'flex', alignItems: 'center', flex: 1, + fontFamily: 'inherit', cursor: 'pointer', ...((ownerState.value === null || ownerState.value === undefined) && { opacity: 'var(--Select-placeholderOpacity)', }), })); -const SelectListbox = styled(ListRoot, { +const SelectListbox = styled(StyledList, { name: 'JoySelect', slot: 'Listbox', overridesResolver: (props, styles) => styles.listbox, diff --git a/packages/mui-joy/src/Tab/Tab.tsx b/packages/mui-joy/src/Tab/Tab.tsx index 346e499181445f..a5c30a0e8f7d24 100644 --- a/packages/mui-joy/src/Tab/Tab.tsx +++ b/packages/mui-joy/src/Tab/Tab.tsx @@ -5,7 +5,7 @@ import { unstable_capitalize as capitalize, unstable_useForkRef as useForkRef } import { unstable_composeClasses as composeClasses } from '@mui/base'; import { useTab } from '@mui/base/TabUnstyled'; import { useSlotProps } from '@mui/base/utils'; -import { ListItemButtonRoot } from '../ListItemButton/ListItemButton'; +import { StyledListItemButton } from '../ListItemButton/ListItemButton'; import { useThemeProps } from '../styles'; import styled from '../styles/styled'; import { getTabUtilityClass } from './tabClasses'; @@ -31,7 +31,7 @@ const useUtilityClasses = (ownerState: TabOwnerState) => { return composeClasses(slots, getTabUtilityClass, {}); }; -const TabRoot = styled(ListItemButtonRoot, { +const TabRoot = styled(StyledListItemButton, { name: 'JoyTab', slot: 'Root', overridesResolver: (props, styles) => styles.root, diff --git a/packages/mui-joy/src/TabList/TabList.tsx b/packages/mui-joy/src/TabList/TabList.tsx index ec88f4bc339760..810c97ac88260a 100644 --- a/packages/mui-joy/src/TabList/TabList.tsx +++ b/packages/mui-joy/src/TabList/TabList.tsx @@ -7,7 +7,7 @@ import { useTabsList } from '@mui/base/TabsListUnstyled'; import { useSlotProps } from '@mui/base/utils'; import { useThemeProps } from '../styles'; import styled from '../styles/styled'; -import { ListRoot } from '../List/List'; +import { StyledList } from '../List/List'; import ListProvider, { scopedVariables } from '../List/ListProvider'; import SizeTabsContext from '../Tabs/SizeTabsContext'; import { getTabListUtilityClass } from './tabListClasses'; @@ -29,7 +29,7 @@ const useUtilityClasses = (ownerState: TabListOwnerState) => { return composeClasses(slots, getTabListUtilityClass, {}); }; -const TabListRoot = styled(ListRoot, { +const TabListRoot = styled(StyledList, { name: 'JoyTabList', slot: 'Root', overridesResolver: (props, styles) => styles.root, diff --git a/packages/mui-joy/src/TabList/TabListProps.ts b/packages/mui-joy/src/TabList/TabListProps.ts index 087dab315a5f8f..be0783ba9671bf 100644 --- a/packages/mui-joy/src/TabList/TabListProps.ts +++ b/packages/mui-joy/src/TabList/TabListProps.ts @@ -4,11 +4,11 @@ import { ColorPaletteProp, SxProps, VariantProp } from '../styles/types'; export type TabListSlot = 'root'; -export interface TabListColorOverrides {} +export interface TabListPropsColorOverrides {} -export interface TabListVariantOverrides {} +export interface TabListPropsVariantOverrides {} -export interface TabListSizeOverrides {} +export interface TabListPropsSizeOverrides {} export interface TabListTypeMap

{ props: P & { @@ -16,7 +16,7 @@ export interface TabListTypeMap

{ * The color of the component. It supports those theme colors that make sense for this component. * @default 'neutral' */ - color?: OverridableStringUnion; + color?: OverridableStringUnion; /** * Used to render icon or text elements inside the TabList if `src` is not set. * This can be an element, or just a string. @@ -25,7 +25,7 @@ export interface TabListTypeMap

{ /** * The size of the component. */ - size?: OverridableStringUnion<'sm' | 'md' | 'lg', TabListSizeOverrides>; + size?: OverridableStringUnion<'sm' | 'md' | 'lg', TabListPropsSizeOverrides>; /** * The system prop that allows defining system overrides as well as additional CSS styles. */ @@ -34,7 +34,7 @@ export interface TabListTypeMap

{ * The variant to use. * @default 'soft' */ - variant?: OverridableStringUnion; + variant?: OverridableStringUnion; }; defaultComponent: D; } diff --git a/packages/mui-joy/src/Textarea/Textarea.tsx b/packages/mui-joy/src/Textarea/Textarea.tsx index cabef266ae0219..c4ff6765ea7a11 100644 --- a/packages/mui-joy/src/Textarea/Textarea.tsx +++ b/packages/mui-joy/src/Textarea/Textarea.tsx @@ -39,6 +39,7 @@ const TextareaRoot = styled('div', { { '--Textarea-radius': theme.vars.radius.sm, '--Textarea-gap': '0.5rem', + '--Textarea-placeholderColor': 'inherit', '--Textarea-placeholderOpacity': 0.5, '--Textarea-focusedThickness': theme.vars.focus.thickness, ...(ownerState.color === 'context' @@ -162,12 +163,24 @@ const TextareaInput = styled(TextareaAutosize, { WebkitTextFillColor: 'currentColor', }, '&::-webkit-input-placeholder': { + color: 'var(--Textarea-placeholderColor)', + opacity: 'var(--Textarea-placeholderOpacity)', + }, + '&::-moz-placeholder': { + // Firefox 19+ + color: 'var(--Textarea-placeholderColor)', + opacity: 'var(--Textarea-placeholderOpacity)', + }, + '&:-ms-input-placeholder': { + // IE11 + color: 'var(--Textarea-placeholderColor)', + opacity: 'var(--Textarea-placeholderOpacity)', + }, + '&::-ms-input-placeholder': { + // Edge + color: 'var(--Textarea-placeholderColor)', opacity: 'var(--Textarea-placeholderOpacity)', - color: 'inherit', }, - '&::-moz-placeholder': { opacity: 'var(--Textarea-placeholderOpacity)', color: 'inherit' }, // Firefox 19+ - '&:-ms-input-placeholder': { opacity: 'var(--Textarea-placeholderOpacity)', color: 'inherit' }, // IE11 - '&::-ms-input-placeholder': { opacity: 'var(--Textarea-placeholderOpacity)', color: 'inherit' }, // Edge }); const TextareaStartDecorator = styled('div', { diff --git a/packages/mui-joy/src/Typography/Typography.tsx b/packages/mui-joy/src/Typography/Typography.tsx index 3cd2de31cb2c55..18be3e797d39c8 100644 --- a/packages/mui-joy/src/Typography/Typography.tsx +++ b/packages/mui-joy/src/Typography/Typography.tsx @@ -37,7 +37,7 @@ const StartDecorator = styled('span', { overridesResolver: (props, styles) => styles.startDecorator, })<{ ownerState: TypographyOwnerState }>(({ ownerState }) => ({ display: 'inline-flex', - marginInlineEnd: 'clamp(4px, var(--Typography-gap, 0.25em), 0.5rem)', + marginInlineEnd: 'clamp(4px, var(--Typography-gap, 0.375em), 0.75rem)', ...((ownerState.sx as any)?.alignItems === 'flex-start' && { marginTop: '2px', // this makes the alignment perfect in most cases }), @@ -49,7 +49,7 @@ const EndDecorator = styled('span', { overridesResolver: (props, styles) => styles.endDecorator, })<{ ownerState: TypographyOwnerState }>(({ ownerState }) => ({ display: 'inline-flex', - marginInlineStart: 'clamp(4px, var(--Typography-gap, 0.25em), 0.5rem)', + marginInlineStart: 'clamp(4px, var(--Typography-gap, 0.375em), 0.75rem)', ...((ownerState.sx as any)?.alignItems === 'flex-start' && { marginTop: '2px', // this makes the alignment perfect in most cases }), @@ -89,11 +89,15 @@ const TypographyRoot = styled('span', { ...(ownerState.gutterBottom && { marginBottom: '0.35em', }), + ...(ownerState.color && { + color: `rgba(${theme.vars.palette[ownerState.color]?.mainChannel} / 1)`, + }), ...(ownerState.variant && { borderRadius: theme.vars.radius.xs, - paddingInline: '0.25em', // better than left, right because it also works with writing mode. + paddingBlock: 'min(0.15em, 4px)', + paddingInline: '0.375em', // better than left, right because it also works with writing mode. ...(!ownerState.nesting && { - marginInline: '-0.25em', + marginInline: '-0.375em', }), ...theme.variants[ownerState.variant]?.[ownerState.color!], }), @@ -117,11 +121,9 @@ const defaultVariantMapping: Record = { }; const Typography = React.forwardRef(function Typography(inProps, ref) { - const { - color: colorThemeProp, - textColor, - ...themeProps - } = useThemeProps({ + const { color, textColor, ...themeProps } = useThemeProps< + typeof inProps & { component?: React.ElementType } + >({ props: inProps, name: 'JoyTypography', }); @@ -140,12 +142,9 @@ const Typography = React.forwardRef(function Typography(inProps, ref) { children, endDecorator, startDecorator, - variant = colorThemeProp ? 'plain' : undefined, + variant, ...other } = props; - - const color = colorThemeProp || (variant ? 'neutral' : undefined); - const level = nesting ? inProps.level || 'inherit' : levelProp; const component = @@ -158,7 +157,7 @@ const Typography = React.forwardRef(function Typography(inProps, ref) { ...props, level, component, - color, + color: variant ? color ?? 'neutral' : color, gutterBottom, noWrap, nesting, diff --git a/packages/mui-joy/src/styles/CssVarsProvider.tsx b/packages/mui-joy/src/styles/CssVarsProvider.tsx index 4036b1605f10e7..f47e62034c3886 100644 --- a/packages/mui-joy/src/styles/CssVarsProvider.tsx +++ b/packages/mui-joy/src/styles/CssVarsProvider.tsx @@ -6,6 +6,7 @@ import type { Theme, DefaultColorScheme, ExtendedColorScheme } from './types'; const shouldSkipGeneratingVar = (keys: string[]) => !!keys[0].match(/^(typography|variants|breakpoints|colorInversion|colorInversionConfig)$/) || + (keys[0] === 'palette' && !!keys[1]?.match(/^(mode)$/)) || (keys[0] === 'focus' && keys[1] !== 'thickness'); const { CssVarsProvider, useColorScheme, getInitColorSchemeScript } = createCssVarsProvider<