Skip to content

Commit

Permalink
[Select] Improve integration with a <label> (mui#34116)
Browse files Browse the repository at this point in the history
  • Loading branch information
oliviertassinari authored and alexfauquette committed Oct 14, 2022
1 parent 6be8e11 commit b408dc4
Show file tree
Hide file tree
Showing 11 changed files with 162 additions and 104 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,6 @@ export default function UnstyledSelectObjectValues() {
</StyledOption>
))}
</CustomSelect>

<Paragraph>Selected character:</Paragraph>
<Pre>{JSON.stringify(character, null, 2)}</Pre>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,6 @@ export default function UnstyledSelectObjectValues() {
</StyledOption>
))}
</CustomSelect>

<Paragraph>Selected character:</Paragraph>
<Pre>{JSON.stringify(character, null, 2)}</Pre>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,5 @@
</StyledOption>
))}
</CustomSelect>

<Paragraph>Selected character:</Paragraph>
<Pre>{JSON.stringify(character, null, 2)}</Pre>
92 changes: 55 additions & 37 deletions docs/data/base/components/select/UnstyledSelectObjectValuesForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import SelectUnstyled, { selectUnstyledClasses } from '@mui/base/SelectUnstyled'
import OptionUnstyled, { optionUnstyledClasses } from '@mui/base/OptionUnstyled';
import PopperUnstyled from '@mui/base/PopperUnstyled';
import { styled } from '@mui/system';
import Box from '@mui/system/Box';

const blue = {
100: '#DAECFF',
Expand Down Expand Up @@ -37,7 +38,6 @@ const StyledButton = styled('button')(
background: ${theme.palette.mode === 'dark' ? grey[900] : '#fff'};
border: 1px solid ${theme.palette.mode === 'dark' ? grey[800] : grey[300]};
border-radius: 0.75em;
margin: 0.5em;
padding: 10px;
text-align: left;
line-height: 1.5;
Expand Down Expand Up @@ -123,11 +123,12 @@ const StyledPopper = styled(PopperUnstyled)`
z-index: 1;
`;

const Header = styled('h1')(
const Label = styled('label')(
({ theme }) => `
font-family: IBM Plex Sans, sans-serif;
font-size: 1rem;
margin: 10px 0;
font-size: 0.85rem;
display: block;
margin-bottom: 4px;
font-weight: 400;
color: ${theme.palette.mode === 'dark' ? grey[400] : grey[700]};
`,
Expand Down Expand Up @@ -183,9 +184,7 @@ const characters = [
{ name: 'Gimli', race: 'Dwarf' },
];

export default function UnstyledSelectObjectValues() {
const [character, setCharacter] = React.useState(characters[0]);

export default function UnstyledSelectObjectValuesForm() {
const getSerializedValue = (option) => {
if (option?.value == null) {
return '';
Expand All @@ -202,39 +201,58 @@ export default function UnstyledSelectObjectValues() {

return (
<div>
<Header>Default behavior</Header>
<form onSubmit={handleSubmit}>
<CustomSelect
value={character}
onChange={(e, newValue) => setCharacter(newValue)}
name="character"
>
{characters.map((c) => (
<StyledOption key={c.name} value={c}>
{c.name}
</StyledOption>
))}
</CustomSelect>

<Button type="submit">Submit</Button>
<Box sx={{ display: 'flex', alignItems: 'flex-end' }}>
<div>
<Label
id="object-value-default-label"
htmlFor="object-value-default-button"
>
Default behavior
</Label>
<CustomSelect
name="character"
id="object-value-default-button"
aria-labelledby="object-value-default-label object-value-default-button"
>
{characters.map((character) => (
<StyledOption key={character.name} value={character}>
{character.name}
</StyledOption>
))}
</CustomSelect>
</div>
<Button sx={{ ml: 1 }} type="submit">
Submit
</Button>
</Box>
</form>

<Header>Custom getSerializedValue</Header>
<form onSubmit={handleSubmit}>
<CustomSelect
value={character}
onChange={(e, newValue) => setCharacter(newValue)}
getSerializedValue={getSerializedValue}
name="character"
>
{characters.map((c) => (
<StyledOption key={c.name} value={c}>
{c.name}
</StyledOption>
))}
</CustomSelect>

<Button type="submit">Submit</Button>
<Box sx={{ display: 'flex', alignItems: 'flex-end', mt: 2 }}>
<div>
<Label
id="object-value-serialize-label"
htmlFor="object-value-serialize-button"
>
Custom getSerializedValue
</Label>
<CustomSelect
getSerializedValue={getSerializedValue}
name="character"
id="object-value-serialize-button"
aria-labelledby="object-value-serialize-label object-value-serialize-button"
>
{characters.map((character) => (
<StyledOption key={character.name} value={character}>
{character.name}
</StyledOption>
))}
</CustomSelect>
</div>
<Button sx={{ ml: 1 }} type="submit">
Submit
</Button>
</Box>
</form>
</div>
);
Expand Down
92 changes: 55 additions & 37 deletions docs/data/base/components/select/UnstyledSelectObjectValuesForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import SelectUnstyled, {
import OptionUnstyled, { optionUnstyledClasses } from '@mui/base/OptionUnstyled';
import PopperUnstyled from '@mui/base/PopperUnstyled';
import { styled } from '@mui/system';
import Box from '@mui/system/Box';

const blue = {
100: '#DAECFF',
Expand Down Expand Up @@ -40,7 +41,6 @@ const StyledButton = styled('button')(
background: ${theme.palette.mode === 'dark' ? grey[900] : '#fff'};
border: 1px solid ${theme.palette.mode === 'dark' ? grey[800] : grey[300]};
border-radius: 0.75em;
margin: 0.5em;
padding: 10px;
text-align: left;
line-height: 1.5;
Expand Down Expand Up @@ -126,11 +126,12 @@ const StyledPopper = styled(PopperUnstyled)`
z-index: 1;
`;

const Header = styled('h1')(
const Label = styled('label')(
({ theme }) => `
font-family: IBM Plex Sans, sans-serif;
font-size: 1rem;
margin: 10px 0;
font-size: 0.85rem;
display: block;
margin-bottom: 4px;
font-weight: 400;
color: ${theme.palette.mode === 'dark' ? grey[400] : grey[700]};
`,
Expand Down Expand Up @@ -178,9 +179,7 @@ const characters: Character[] = [
{ name: 'Gimli', race: 'Dwarf' },
];

export default function UnstyledSelectObjectValues() {
const [character, setCharacter] = React.useState<Character | null>(characters[0]);

export default function UnstyledSelectObjectValuesForm() {
const getSerializedValue = (option: SelectOption<Character> | null) => {
if (option?.value == null) {
return '';
Expand All @@ -197,39 +196,58 @@ export default function UnstyledSelectObjectValues() {

return (
<div>
<Header>Default behavior</Header>
<form onSubmit={handleSubmit}>
<CustomSelect
value={character}
onChange={(e, newValue) => setCharacter(newValue)}
name="character"
>
{characters.map((c) => (
<StyledOption key={c.name} value={c}>
{c.name}
</StyledOption>
))}
</CustomSelect>

<Button type="submit">Submit</Button>
<Box sx={{ display: 'flex', alignItems: 'flex-end' }}>
<div>
<Label
id="object-value-default-label"
htmlFor="object-value-default-button"
>
Default behavior
</Label>
<CustomSelect
name="character"
id="object-value-default-button"
aria-labelledby="object-value-default-label object-value-default-button"
>
{characters.map((character) => (
<StyledOption key={character.name} value={character}>
{character.name}
</StyledOption>
))}
</CustomSelect>
</div>
<Button sx={{ ml: 1 }} type="submit">
Submit
</Button>
</Box>
</form>

<Header>Custom getSerializedValue</Header>
<form onSubmit={handleSubmit}>
<CustomSelect
value={character}
onChange={(e, newValue) => setCharacter(newValue)}
getSerializedValue={getSerializedValue}
name="character"
>
{characters.map((c) => (
<StyledOption key={c.name} value={c}>
{c.name}
</StyledOption>
))}
</CustomSelect>

<Button type="submit">Submit</Button>
<Box sx={{ display: 'flex', alignItems: 'flex-end', mt: 2 }}>
<div>
<Label
id="object-value-serialize-label"
htmlFor="object-value-serialize-button"
>
Custom getSerializedValue
</Label>
<CustomSelect
getSerializedValue={getSerializedValue}
name="character"
id="object-value-serialize-button"
aria-labelledby="object-value-serialize-label object-value-serialize-button"
>
{characters.map((character) => (
<StyledOption key={character.name} value={character}>
{character.name}
</StyledOption>
))}
</CustomSelect>
</div>
<Button sx={{ ml: 1 }} type="submit">
Submit
</Button>
</Box>
</form>
</div>
);
Expand Down
8 changes: 0 additions & 8 deletions docs/data/base/components/select/UseSelect.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,7 @@ const grey = {
};

const Root = styled('div')`
font-family: IBM Plex Sans, sans-serif;
font-size: 0.875rem;
position: relative;
display: inline-block;
vertical-align: baseline;
color: #000;
`;

const Toggle = styled('div')(
Expand All @@ -32,19 +27,16 @@ const Toggle = styled('div')(
box-sizing: border-box;
min-height: calc(1.5em + 22px);
min-width: 320px;
padding: 12px;
border-radius: 12px;
text-align: left;
line-height: 1.5;
border: 1px solid ${theme.palette.mode === 'dark' ? grey[700] : grey[200]};
color: ${theme.palette.mode === 'dark' ? grey[300] : grey[900]};
background: var(--color, ${theme.palette.mode === 'dark' ? grey[900] : '#fff'});
margin: 0.5em;
display: inline-flex;
align-items: center;
justify-content: center;
cursor: default;
transition-property: all;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 120ms;
Expand Down
8 changes: 0 additions & 8 deletions docs/data/base/components/select/UseSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,7 @@ const grey = {
};

const Root = styled('div')`
font-family: IBM Plex Sans, sans-serif;
font-size: 0.875rem;
position: relative;
display: inline-block;
vertical-align: baseline;
color: #000;
`;

const Toggle = styled('div')(
Expand All @@ -31,19 +26,16 @@ const Toggle = styled('div')(
box-sizing: border-box;
min-height: calc(1.5em + 22px);
min-width: 320px;
padding: 12px;
border-radius: 12px;
text-align: left;
line-height: 1.5;
border: 1px solid ${theme.palette.mode === 'dark' ? grey[700] : grey[200]};
color: ${theme.palette.mode === 'dark' ? grey[300] : grey[900]};
background: var(--color, ${theme.palette.mode === 'dark' ? grey[900] : '#fff'});
margin: 0.5em;
display: inline-flex;
align-items: center;
justify-content: center;
cursor: default;
transition-property: all;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 120ms;
Expand Down
20 changes: 12 additions & 8 deletions docs/data/joy/components/select/SelectFieldDemo.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,30 @@ import Select from '@mui/joy/Select';
import Option from '@mui/joy/Option';

export default function SelectFieldDemo() {
const [value, setValue] = React.useState('dog');
return (
<FormControl sx={{ width: 240 }}>
<FormLabel
// screen readers will announce "Favorite pet, dog selected" when the select is focused.
aria-label={`Favorite pet, ${value} selected.`}
>
<FormLabel id="select-field-demo-label" htmlFor="select-field-demo-button">
Favorite pet
</FormLabel>
<Select
defaultValue="dog"
value={value}
onChange={(e, newValue) => setValue(newValue)}
componentsProps={{
button: {
id: 'select-field-demo-button',
// TODO: Material UI set aria-labelledby correctly & automatically
// but MUI Base and Joy UI don't yet.
'aria-labelledby': 'select-field-demo-label select-field-demo-button',
},
}}
>
<Option value="dog">Dog</Option>
<Option value="cat">Cat</Option>
<Option value="fish">Fish</Option>
<Option value="bird">Bird</Option>
</Select>
<FormHelperText>This is a helper text.</FormHelperText>
<FormHelperText id="select-field-demo-helper">
This is a helper text.
</FormHelperText>
</FormControl>
);
}

0 comments on commit b408dc4

Please sign in to comment.