Skip to content

Commit

Permalink
[Joy] Add Select component (#33630)
Browse files Browse the repository at this point in the history
  • Loading branch information
siriwatknp authored Jul 25, 2022
1 parent cc1b56e commit ad4cdac
Show file tree
Hide file tree
Showing 44 changed files with 2,660 additions and 168 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,11 @@ export default function ExampleChoiceChipCheckbox() {
<Box role="group" aria-labelledby="rank">
<List
row
wrap
sx={{
'--List-gap': '0px',
'--List-gap': '8px',
'--List-item-radius': '20px',
'--List-item-minHeight': '32px',
gap: 1,
flexWrap: 'wrap',
}}
>
{['Elevator', 'Washer/Dryer', 'Fireplace', 'Dogs ok', 'Cats ok'].map(
Expand Down
5 changes: 2 additions & 3 deletions docs/data/joy/components/checkbox/IconlessCheckbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,10 @@ export default function IconlessCheckbox() {
<Box role="group" aria-labelledby="topping">
<List
row
wrap
sx={{
'--List-gap': '0px',
'--List-gap': '8px',
'--List-item-radius': '20px',
flexWrap: 'wrap',
gap: 1,
}}
>
{[
Expand Down
8 changes: 7 additions & 1 deletion docs/data/joy/components/list/ExampleIOSList.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@ import Podcasts from '@mui/icons-material/Podcasts';
export default function ExampleIOSList() {
return (
<Sheet variant="soft" sx={{ width: 343, p: 2, borderRadius: 'sm' }}>
<Typography level="h3" fontSize="xl2" fontWeight="xl" id="ios-example-demo">
<Typography
level="h3"
fontSize="xl2"
fontWeight="xl"
id="ios-example-demo"
mb={1}
>
Settings
</Typography>
<List
Expand Down
54 changes: 35 additions & 19 deletions docs/data/joy/components/menu/MenuToolbarExample.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ export default function MenuToolbarExample() {
'--List-item-radius': '8px',
}}
>
<ListItem role="none">
<ListItem>
<MenuButton
open={menuIndex === 0}
onOpen={() => setMenuIndex(0)}
Expand All @@ -176,23 +176,31 @@ export default function MenuToolbarExample() {
setMenuIndex(null);
}}
>
<MenuItem {...itemProps}>New File</MenuItem>
<MenuItem {...itemProps}>
New Text File... {renderShortcut('⌥ ⌘ N')}
</MenuItem>
<MenuItem {...itemProps}>
New Window {renderShortcut('⇧ ⌘ N')}
</MenuItem>
<ListDivider role="none" />
<MenuItem {...itemProps}>Open {renderShortcut('⌘ O')}</MenuItem>
<MenuItem {...itemProps}>Open Folder</MenuItem>
<ListItem nested>
<List aria-label="New">
<MenuItem {...itemProps}>New File</MenuItem>
<MenuItem {...itemProps}>
New Text File... {renderShortcut('⌥ ⌘ N')}
</MenuItem>
<MenuItem {...itemProps}>
New Window {renderShortcut('⇧ ⌘ N')}
</MenuItem>
</List>
</ListItem>
<ListDivider />
<ListItem nested>
<List aria-label="Open">
<MenuItem {...itemProps}>Open {renderShortcut('⌘ O')}</MenuItem>
<MenuItem {...itemProps}>Open Folder</MenuItem>
</List>
</ListItem>
</Menu>
}
>
File
</MenuButton>
</ListItem>
<ListItem role="none">
<ListItem>
<MenuButton
open={menuIndex === 1}
onOpen={() => setMenuIndex(1)}
Expand All @@ -212,19 +220,27 @@ export default function MenuToolbarExample() {
setMenuIndex(null);
}}
>
<MenuItem {...itemProps}>Undo {renderShortcut('⌘ Z')}</MenuItem>
<MenuItem {...itemProps}>Redo {renderShortcut('⇧ ⌘ Z')}</MenuItem>
<ListDivider role="none" />
<MenuItem {...itemProps}>Cut {renderShortcut('⌘ X')}</MenuItem>
<MenuItem {...itemProps}>Copy {renderShortcut('⌘ Z')}</MenuItem>
<MenuItem {...itemProps}>Paste {renderShortcut('⌘ V')}</MenuItem>
<ListItem nested>
<List aria-label="Time travel">
<MenuItem {...itemProps}>Undo {renderShortcut('⌘ Z')}</MenuItem>
<MenuItem {...itemProps}>Redo {renderShortcut('⇧ ⌘ Z')}</MenuItem>
</List>
</ListItem>
<ListDivider />
<ListItem nested>
<List aria-label="Tool">
<MenuItem {...itemProps}>Cut {renderShortcut('⌘ X')}</MenuItem>
<MenuItem {...itemProps}>Copy {renderShortcut('⌘ Z')}</MenuItem>
<MenuItem {...itemProps}>Paste {renderShortcut('⌘ V')}</MenuItem>
</List>
</ListItem>
</Menu>
}
>
Edit
</MenuButton>
</ListItem>
<ListItem role="none">
<ListItem>
<MenuButton
open={menuIndex === 2}
onOpen={() => setMenuIndex(2)}
Expand Down
5 changes: 5 additions & 0 deletions docs/data/joy/components/menu/menu.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ The primary responsibility of this component is handling the focus state.

{{"demo": "MenuListComposition.js"}}

## Debugging

To keep the list box open for inspecting elements, enable the `Emulate a focused page` option from the [Chrome DevTool Rendering](https://developer.chrome.com/docs/devtools/rendering/apply-effects/#emulate-a-focused-page) tab.
You can also access this option by using [command menu and search for it](https://developer.chrome.com/docs/devtools/command-menu/).

## Common examples

### Menu bar
Expand Down
26 changes: 11 additions & 15 deletions docs/data/joy/components/radio/ExamplePaymentChannels.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import ListDivider from '@mui/joy/ListDivider';
import Radio from '@mui/joy/Radio';
import RadioGroup from '@mui/joy/RadioGroup';
import Typography from '@mui/joy/Typography';
import Sheet from '@mui/joy/Sheet';
import Switch, { switchClasses } from '@mui/joy/Switch';

export default function ExamplePaymentChannels() {
Expand Down Expand Up @@ -49,26 +48,23 @@ export default function ExamplePaymentChannels() {
name="example-payment-channel"
defaultValue="Paypal"
>
<Sheet
<List
variant="outlined"
row={row}
sx={{
borderRadius: 'sm',
boxShadow: 'sm',
// use logical properties to support writing modes
...(row ? { paddingInline: '6px' } : { paddingBlock: '6px' }),
}}
>
<List row={row}>
{['Credit Card', 'Paypal', 'QR Code'].map((value, index) => (
<React.Fragment key={value}>
{index !== 0 && <ListDivider />}
<ListItem>
<Radio id={value} value={value} label={value} />
</ListItem>
</React.Fragment>
))}
</List>
</Sheet>
{['Credit Card', 'Paypal', 'QR Code'].map((value, index) => (
<React.Fragment key={value}>
{index !== 0 && <ListDivider />}
<ListItem>
<Radio id={value} value={value} label={value} />
</ListItem>
</React.Fragment>
))}
</List>
</RadioGroup>
</Box>
);
Expand Down
14 changes: 14 additions & 0 deletions docs/data/joy/components/select/SelectBasic.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import * as React from 'react';
import Select from '@mui/joy/Select';
import Option from '@mui/joy/Option';

export default function SelectBasic() {
return (
<Select defaultValue="dog">
<Option value="dog">Dog</Option>
<Option value="cat">Cat</Option>
<Option value="fish">Fish</Option>
<Option value="bird">Bird</Option>
</Select>
);
}
46 changes: 46 additions & 0 deletions docs/data/joy/components/select/SelectClearable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import * as React from 'react';
import Select from '@mui/joy/Select';
import Option from '@mui/joy/Option';
import IconButton from '@mui/joy/IconButton';
import CloseRounded from '@mui/icons-material/CloseRounded';

export default function SelectBasic() {
const [value, setValue] = React.useState('dog');
const action = React.useRef(null);
return (
<Select
action={action}
value={value}
placeholder="Favorite pet…"
onChange={setValue}
{...(value && {
// display the button and remove select indicator
// when user has selected a value
endDecorator: (
<IconButton
size="sm"
variant="plain"
color="neutral"
onMouseDown={(event) => {
// don't open the popup when clicking on this button
event.stopPropagation();
}}
onClick={() => {
setValue(null);
action.current?.focusVisible();
}}
>
<CloseRounded />
</IconButton>
),
indicator: null,
})}
sx={{ minWidth: 160 }}
>
<Option value="dog">Dog</Option>
<Option value="cat">Cat</Option>
<Option value="fish">Fish</Option>
<Option value="bird">Bird</Option>
</Select>
);
}
46 changes: 46 additions & 0 deletions docs/data/joy/components/select/SelectCustomOption.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import * as React from 'react';
import Avatar from '@mui/joy/Avatar';
import ListItemDecorator from '@mui/joy/ListItemDecorator';
import ListDivider from '@mui/joy/ListDivider';
import Select from '@mui/joy/Select';
import Option from '@mui/joy/Option';

export default function SelectCustomOption() {
return (
<Select
defaultValue="1"
componentsProps={{
listbox: {
sx: {
'--List-decorator-width': '44px',
},
},
}}
sx={{
'--List-decorator-width': '44px',
minWidth: 240,
}}
>
<Option value="1">
<ListItemDecorator>
<Avatar size="sm" src="/static/images/avatar/1.jpg" />
</ListItemDecorator>
Eric
</Option>
<ListDivider role="none" inset="startContent" />
<Option value="2">
<ListItemDecorator>
<Avatar size="sm" src="/static/images/avatar/2.jpg" />
</ListItemDecorator>
Smith
</Option>
<ListDivider role="none" inset="startContent" />
<Option value="3">
<ListItemDecorator>
<Avatar size="sm" src="/static/images/avatar/3.jpg" />
</ListItemDecorator>
Erika
</Option>
</Select>
);
}
67 changes: 67 additions & 0 deletions docs/data/joy/components/select/SelectCustomValueAppearance.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import * as React from 'react';
import Avatar from '@mui/joy/Avatar';
import Box from '@mui/joy/Box';
import Chip from '@mui/joy/Chip';
import ListItemDecorator from '@mui/joy/ListItemDecorator';
import Select from '@mui/joy/Select';
import Option from '@mui/joy/Option';
import Typography from '@mui/joy/Typography';

export default function SelectCustomValueAppearance() {
const people = [
{ name: 'Eric', role: 'PM', status: '2days ago' },
{ name: 'Smith', role: 'Engineer', status: 'secs ago' },
{ name: 'Erika', role: 'Designer', status: '10hrs ago' },
];
const colors = {
PM: 'success',
Engineer: 'primary',
Designer: 'warning',
};
return (
<Select
defaultValue="Eric"
componentsProps={{
listbox: {
sx: {
'--List-decorator-width': '48px',
},
},
}}
sx={{
minWidth: 240,
}}
>
{people.map((data, index) => (
<Option
key={data.name}
value={data.name}
label={data.name} // The appearance of the selected value will be a string
>
<ListItemDecorator>
<Avatar src={`/static/images/avatar/${index + 1}.jpg`} />
</ListItemDecorator>
<Box component="span" sx={{ display: 'block' }}>
<Typography component="span">{data.name}</Typography>
<Typography level="body4">{data.status}</Typography>
</Box>
<Chip
size="sm"
variant="outlined"
color={colors[data.role]}
sx={{
ml: 'auto',
borderRadius: '2px',
minHeight: '20px',
paddingInline: '4px',
fontSize: 'xs',
bgcolor: `${colors[data.role]}.softBg`,
}}
>
{data.role}
</Chip>
</Option>
))}
</Select>
);
}
25 changes: 25 additions & 0 deletions docs/data/joy/components/select/SelectDecorators.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import * as React from 'react';
import Select from '@mui/joy/Select';
import Option from '@mui/joy/Option';
import Chip from '@mui/joy/Chip';
import FavoriteBorder from '@mui/icons-material/FavoriteBorder';

export default function SelectDecorators() {
return (
<Select
placeholder="Select a pet…"
startDecorator={<FavoriteBorder />}
endDecorator={
<Chip size="sm" color="danger" variant="soft" sx={{ mr: -1 }}>
+5
</Chip>
}
sx={{ width: 240 }}
>
<Option value="dog">Dog</Option>
<Option value="cat">Cat</Option>
<Option value="fish">Fish</Option>
<Option value="bird">Bird</Option>
</Select>
);
}
Loading

0 comments on commit ad4cdac

Please sign in to comment.