Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions packages/mui-material/src/Input/Input.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { styled } from '../zero-styled';
import memoTheme from '../utils/memoTheme';
import createSimplePaletteValueFilter from '../utils/createSimplePaletteValueFilter';
import { useDefaultProps } from '../DefaultPropsProvider';
import inputLabelClasses from '../InputLabel/inputLabelClasses';
import inputClasses, { getInputUtilityClass } from './inputClasses';
import {
rootOverridesResolver as inputBaseRootOverridesResolver,
Expand Down Expand Up @@ -62,9 +63,10 @@ const InputRoot = styled(InputBaseRoot, {
{
props: ({ ownerState }) => ownerState.formControl,
style: {
'label + &': {
marginTop: 16,
},
[`label + &, :where(.${inputLabelClasses.root}) + &, div:where(.${inputLabelClasses.root}) + &`]:
Comment thread
ZeeshanTamboli marked this conversation as resolved.
Outdated
{
marginTop: 16,
},
},
},
{
Expand Down
2 changes: 2 additions & 0 deletions packages/mui-material/src/Select/SelectInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,7 @@ const SelectInput = React.forwardRef(function SelectInput(props, ref) {
};

const listboxId = useId();
const nativeInputId = useId();

return (
<React.Fragment>
Expand Down Expand Up @@ -574,6 +575,7 @@ const SelectInput = React.forwardRef(function SelectInput(props, ref) {
autoFocus={autoFocus}
required={required}
{...other}
id={other.id ?? nativeInputId}
ownerState={ownerState}
/>
<SelectIcon as={IconComponent} className={classes.icon} ownerState={ownerState} />
Expand Down
23 changes: 15 additions & 8 deletions packages/mui-material/src/TextField/TextField.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,14 @@ const TextField = React.forwardRef(function TextField(inProps, ref) {
slotProps,
};

const [SelectSlot, selectProps] = useSlot('select', {
elementType: Select,
externalForwardedProps,
ownerState,
});

const nativeSelect = select && selectProps.native;

const inputAdditionalProps = {};
const inputLabelSlotProps = externalForwardedProps.slotProps.inputLabel;

Expand All @@ -151,7 +159,7 @@ const TextField = React.forwardRef(function TextField(inProps, ref) {
}
if (select) {
// unset defaults from textbox inputs
if (!slotProps.select || !slotProps.select.native) {
if (!nativeSelect) {
inputAdditionalProps.id = undefined;
}
inputAdditionalProps['aria-describedby'] = undefined;
Expand Down Expand Up @@ -202,12 +210,6 @@ const TextField = React.forwardRef(function TextField(inProps, ref) {
ownerState,
});

const [SelectSlot, selectProps] = useSlot('select', {
elementType: Select,
externalForwardedProps,
ownerState,
});

const InputElement = (
<InputSlot
aria-describedby={helperTextId}
Expand Down Expand Up @@ -239,7 +241,12 @@ const TextField = React.forwardRef(function TextField(inProps, ref) {
return (
<RootSlot {...rootProps}>
{label != null && label !== '' && (
<InputLabelSlot htmlFor={id} id={inputLabelId} {...inputLabelProps}>
<InputLabelSlot
htmlFor={select && !nativeSelect ? undefined : id}
id={inputLabelId}
{...(select && !nativeSelect && { component: 'div' })}
{...inputLabelProps}
>
{label}
</InputLabelSlot>
)}
Expand Down
59 changes: 57 additions & 2 deletions packages/mui-material/src/TextField/TextField.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -283,15 +283,70 @@ describe('<TextField />', () => {
expect(screen.getByRole('combobox')).toHaveAccessibleName('Release:');
});

it('creates an input[hidden] that has no accessible properties', () => {
it('renders the label as a <div> without htmlFor when select', () => {
render(
<TextField select label="Release" value="stable" variant="standard">
<MenuItem value="stable">Stable</MenuItem>
</TextField>,
);

const labelElement = screen.getByText('Release');
expect(labelElement.tagName).to.equal('DIV');
expect(labelElement).not.to.have.attribute('for');

const combobox = screen.getByRole('combobox');
expect(combobox).to.have.attribute('aria-labelledby');
expect(combobox.getAttribute('aria-labelledby')).to.include(labelElement.id);
});

it('renders the label as a <div> when native is set via slotProps', () => {
render(
<TextField
select
label="Release"
value="stable"
variant="standard"
slotProps={{ select: { native: false } }}
>
<MenuItem value="stable">Stable</MenuItem>
</TextField>,
);

const labelElement = screen.getByText('Release');
expect(labelElement.tagName).to.equal('DIV');
expect(labelElement).not.to.have.attribute('for');

const combobox = screen.getByRole('combobox');
expect(combobox.getAttribute('aria-labelledby')).to.include(labelElement.id);
});

it('renders the label as a <label> with htmlFor for native select via slotProps', () => {
render(
<TextField
select
label="Release"
value="stable"
variant="standard"
slotProps={{ select: { native: true } }}
>
<option value="stable">Stable</option>
</TextField>,
);

const labelElement = screen.getByText('Release');
expect(labelElement.tagName).to.equal('LABEL');
expect(labelElement).to.have.attribute('for');
});

it('creates an input[hidden] that has no accessible properties besides id', () => {
const { container } = render(
<TextField select label="Release: " value="stable" variant="standard">
<MenuItem value="stable">Stable</MenuItem>
</TextField>,
);

const input = container.querySelector('input[aria-hidden]');
expect(input).not.to.have.attribute('id');
expect(input).to.have.attribute('id');
expect(input).not.to.have.attribute('aria-describedby');
});

Expand Down
Loading