diff --git a/docs/data/material/components/text-fields/InputAdornments.js b/docs/data/material/components/text-fields/InputAdornments.js index e773612be5d91e..4e15a4da27cc39 100644 --- a/docs/data/material/components/text-fields/InputAdornments.js +++ b/docs/data/material/components/text-fields/InputAdornments.js @@ -9,8 +9,10 @@ import InputAdornment from '@mui/material/InputAdornment'; import FormHelperText from '@mui/material/FormHelperText'; import FormControl from '@mui/material/FormControl'; import TextField from '@mui/material/TextField'; +import MenuItem from '@mui/material/MenuItem'; import Visibility from '@mui/icons-material/Visibility'; import VisibilityOff from '@mui/icons-material/VisibilityOff'; +import InfoOutlined from '@mui/icons-material/InfoOutlined'; export default function InputAdornments() { const outlinedStartId = React.useId(); @@ -37,6 +39,19 @@ export default function InputAdornments() { event.preventDefault(); }; + // An endAdornment coexists with the Select's chevron without overlapping it. + const infoEndAdornment = ( + + + + ); + + const infoStartAdornment = ( + + + + ); + return (
@@ -86,14 +101,40 @@ export default function InputAdornments() { label="Password" /> - - Amount - $} - label="Amount" - /> - +
+ + Amount + $} + label="Amount" + /> + + + Ten + Twenty + Thirty + + + + + + +
- - Amount - $} - /> - +
+ + Amount + $} + /> + + + Ten + Twenty + Thirty + + + + + + +
- - Amount - $} - /> - +
+ + Amount + $} + /> + + + Ten + Twenty + Thirty + + + + + + +
); diff --git a/docs/data/material/components/text-fields/InputAdornments.tsx b/docs/data/material/components/text-fields/InputAdornments.tsx index deb539b0708e8b..af61ee8a6266ba 100644 --- a/docs/data/material/components/text-fields/InputAdornments.tsx +++ b/docs/data/material/components/text-fields/InputAdornments.tsx @@ -9,8 +9,10 @@ import InputAdornment from '@mui/material/InputAdornment'; import FormHelperText from '@mui/material/FormHelperText'; import FormControl from '@mui/material/FormControl'; import TextField from '@mui/material/TextField'; +import MenuItem from '@mui/material/MenuItem'; import Visibility from '@mui/icons-material/Visibility'; import VisibilityOff from '@mui/icons-material/VisibilityOff'; +import InfoOutlined from '@mui/icons-material/InfoOutlined'; export default function InputAdornments() { const outlinedStartId = React.useId(); @@ -37,6 +39,18 @@ export default function InputAdornments() { event.preventDefault(); }; + // An endAdornment coexists with the Select's chevron without overlapping it. + const infoEndAdornment = ( + + + + ); + const infoStartAdornment = ( + + + + ); + return (
@@ -86,14 +100,40 @@ export default function InputAdornments() { label="Password" /> - - Amount - $} - label="Amount" - /> - +
+ + Amount + $} + label="Amount" + /> + + + Ten + Twenty + Thirty + + + + + + +
- - Amount - $} - /> - +
+ + Amount + $} + /> + + + Ten + Twenty + Thirty + + + + + + +
- - Amount - $} - /> - +
+ + Amount + $} + /> + + + Ten + Twenty + Thirty + + + + + + +
); diff --git a/packages/mui-material/src/FilledInput/FilledInput.js b/packages/mui-material/src/FilledInput/FilledInput.js index 349252d64c3d5e..4cc7aa92315b79 100644 --- a/packages/mui-material/src/FilledInput/FilledInput.js +++ b/packages/mui-material/src/FilledInput/FilledInput.js @@ -11,6 +11,7 @@ import memoTheme from '../utils/memoTheme'; import createSimplePaletteValueFilter from '../utils/createSimplePaletteValueFilter'; import { useDefaultProps } from '../DefaultPropsProvider'; import filledInputClasses, { getFilledInputUtilityClass } from './filledInputClasses'; +import selectClasses from '../Select/selectClasses'; import { rootOverridesResolver as inputBaseRootOverridesResolver, inputOverridesResolver as inputBaseInputOverridesResolver, @@ -163,7 +164,12 @@ const FilledInputRoot = styled(InputBaseRoot, { { props: ({ ownerState }) => ownerState.endAdornment, style: { - paddingRight: 12, + // use CSS variable to keep specificity + '--_trailingPad': '12px', + paddingRight: 'var(--_trailingPad)', + [`&.${selectClasses.root}`]: { + '--_trailingPad': '0px', + }, }, }, { diff --git a/packages/mui-material/src/NativeSelect/NativeSelectInput.js b/packages/mui-material/src/NativeSelect/NativeSelectInput.js index 68f1a1ac13a229..ca224bdb6f7877 100644 --- a/packages/mui-material/src/NativeSelect/NativeSelectInput.js +++ b/packages/mui-material/src/NativeSelect/NativeSelectInput.js @@ -6,8 +6,10 @@ import refType from '@mui/utils/refType'; import composeClasses from '@mui/utils/composeClasses'; import capitalize from '../utils/capitalize'; import nativeSelectClasses, { getNativeSelectUtilityClasses } from './nativeSelectClasses'; +import inputBaseClasses from '../InputBase/inputBaseClasses'; import { styled } from '../zero-styled'; import rootShouldForwardProp from '../styles/rootShouldForwardProp'; +import inputAdornmentClasses from '../InputAdornment/inputAdornmentClasses'; const useUtilityClasses = (ownerState) => { const { classes, variant, disabled, multiple, open, error } = ownerState; @@ -46,14 +48,29 @@ export const StyledSelectSelect = styled('select', { '&:not([multiple]) option, &:not([multiple]) optgroup': { backgroundColor: (theme.vars || theme).palette.background.paper, }, + [`& ~ .${inputAdornmentClasses.root}`]: { + position: 'absolute', + top: '50%', + transform: 'translateY(-50%)', + right: 'calc(var(--_caret) + 2px)', + }, + [`.${inputBaseClasses.root}:has(> &)`]: { + '--_endAdornment': '0px', + }, variants: [ { props: ({ ownerState }) => ownerState.variant !== 'filled' && ownerState.variant !== 'outlined', style: { + [`.${inputBaseClasses.root}:has(> &)`]: { + '--_caret': '24px', + }, + [`.${inputBaseClasses.root}:has(> & ~ .${inputAdornmentClasses.root})`]: { + '--_endAdornment': '28px', + }, // Bump specificity to allow extending custom inputs '&&&': { - paddingRight: 24, + paddingRight: 'calc(var(--_caret) + var(--_endAdornment))', minWidth: 16, // So it doesn't collapse. }, }, @@ -63,8 +80,14 @@ export const StyledSelectSelect = styled('select', { variant: 'filled', }, style: { + [`.${inputBaseClasses.root}:has(> &)`]: { + '--_caret': '32px', + }, + [`.${inputBaseClasses.root}:has(> & ~ .${inputAdornmentClasses.root})`]: { + '--_endAdornment': '28px', + }, '&&&': { - paddingRight: 32, + paddingRight: 'calc(var(--_caret) + var(--_endAdornment))', }, }, }, @@ -73,12 +96,18 @@ export const StyledSelectSelect = styled('select', { variant: 'outlined', }, style: { + [`.${inputBaseClasses.root}:has(> &)`]: { + '--_caret': '32px', + }, + [`.${inputBaseClasses.root}:has(> & ~ .${inputAdornmentClasses.root})`]: { + '--_endAdornment': '28px', + }, borderRadius: (theme.vars || theme).shape.borderRadius, '&:focus': { borderRadius: (theme.vars || theme).shape.borderRadius, // Reset the reset for Chrome style }, '&&&': { - paddingRight: 32, + paddingRight: 'calc(var(--_caret) + var(--_endAdornment))', }, }, }, diff --git a/packages/mui-material/src/OutlinedInput/OutlinedInput.js b/packages/mui-material/src/OutlinedInput/OutlinedInput.js index bb851995a8224d..4430abc6ab06f9 100644 --- a/packages/mui-material/src/OutlinedInput/OutlinedInput.js +++ b/packages/mui-material/src/OutlinedInput/OutlinedInput.js @@ -11,6 +11,7 @@ import memoTheme from '../utils/memoTheme'; import createSimplePaletteValueFilter from '../utils/createSimplePaletteValueFilter'; import { useDefaultProps } from '../DefaultPropsProvider'; import outlinedInputClasses, { getOutlinedInputUtilityClass } from './outlinedInputClasses'; +import selectClasses from '../Select/selectClasses'; import InputBase, { rootOverridesResolver as inputBaseRootOverridesResolver, inputOverridesResolver as inputBaseInputOverridesResolver, @@ -93,7 +94,12 @@ const OutlinedInputRoot = styled(InputBaseRoot, { { props: ({ ownerState }) => ownerState.endAdornment, style: { - paddingRight: 14, + // use CSS variable to keep specificity + '--_trailingPad': '14px', + paddingRight: 'var(--_trailingPad)', + [`&.${selectClasses.root}`]: { + '--_trailingPad': '0px', + }, }, }, { diff --git a/test/regressions/fixtures/Select/SelectEndAdornment.js b/test/regressions/fixtures/Select/SelectEndAdornment.js new file mode 100644 index 00000000000000..97a9674b36198f --- /dev/null +++ b/test/regressions/fixtures/Select/SelectEndAdornment.js @@ -0,0 +1,59 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import MenuItem from '@mui/material/MenuItem'; +import Select from '@mui/material/Select'; +import FormControl from '@mui/material/FormControl'; +import InputLabel from '@mui/material/InputLabel'; +import InputAdornment from '@mui/material/InputAdornment'; +import InfoOutlined from '@mui/icons-material/InfoOutlined'; + +// https://github.com/mui/material-ui/issues/45270 +// The endAdornment sits left of the chevron (not over it) and the value clears +// both, across variants and with a start adornment present. +const variants = ['outlined', 'filled', 'standard']; + +const endAdornment = ( + + + +); + +const startAdornment = ( + + + +); + +export default function SelectEndAdornment() { + return ( + + {variants.map((variant) => ( + + Label + + + ))} + + Label + + + + ); +}