Skip to content

Commit

Permalink
[docs] Improve the useSelect demo styling (#33883)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaldudak committed Nov 23, 2022
1 parent f397fa9 commit 23276db
Show file tree
Hide file tree
Showing 5 changed files with 207 additions and 74 deletions.
Expand Up @@ -33,7 +33,7 @@ const Button = React.forwardRef(function Button(props, ref) {
return (
<button type="button" {...other} ref={ref}>
{other.children}
{ownerState.open ? <UnfoldMoreRoundedIcon /> : <UnfoldMoreRoundedIcon />}
<UnfoldMoreRoundedIcon />
</button>
);
});
Expand Down
Expand Up @@ -39,7 +39,7 @@ const Button = React.forwardRef(function Button<TValue extends {}>(
return (
<button type="button" {...other} ref={ref}>
{other.children}
{ownerState.open ? <UnfoldMoreRoundedIcon /> : <UnfoldMoreRoundedIcon />}
<UnfoldMoreRoundedIcon />
</button>
);
});
Expand Down
136 changes: 101 additions & 35 deletions docs/data/base/components/select/UseSelect.js
Expand Up @@ -2,6 +2,16 @@ import * as React from 'react';
import PropTypes from 'prop-types';
import { useSelect } from '@mui/base';
import { styled } from '@mui/system';
import UnfoldMoreRoundedIcon from '@mui/icons-material/UnfoldMoreRounded';

const blue = {
100: '#DAECFF',
200: '#99CCF3',
400: '#3399FF',
500: '#007FFF',
600: '#0072E5',
900: '#003A75',
};

const grey = {
50: '#f6f8fa',
Expand All @@ -20,29 +30,44 @@ const Root = styled('div')`
position: relative;
`;

const Toggle = styled('div')(
const Toggle = styled('button')(
({ theme }) => `
font-family: IBM Plex Sans, sans-serif;
font-size: 0.875rem;
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;
background: ${theme.palette.mode === 'dark' ? grey[900] : '#fff'};
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'});
display: inline-flex;
align-items: center;
justify-content: center;
cursor: default;
position: relative;
transition-property: all;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 120ms;
& .placeholder {
opacity: 0.8;
box-shadow: 0 0 0 2px var(--color) inset;
&:hover {
background: ${theme.palette.mode === 'dark' ? grey[800] : grey[50]};
border-color: ${theme.palette.mode === 'dark' ? grey[600] : grey[300]};
}
&:focus-visible {
border-color: ${blue[400]};
outline: 3px solid ${theme.palette.mode === 'dark' ? grey[600] : grey[200]};
}
& > svg {
font-size: 1rem;
position: absolute;
height: 100%;
top: 0;
right: 10px;
}
`,
);
Expand Down Expand Up @@ -74,32 +99,62 @@ const Listbox = styled('ul')(
&.hidden {
opacity: 0;
visibility: hidden;
transition: opacity 0.4s 0.5s ease, visibility 0.4s 0.5s step-end;
transition: opacity 0.4s ease, visibility 0.4s step-end;
}
`,
);

const Option = styled('li')(
({ theme }) => `
padding: 8px;
border-radius: 0.45em;
&[aria-selected='true'] {
background-color: ${theme.palette.mode === 'dark' ? blue[900] : blue[100]};
color: ${theme.palette.mode === 'dark' ? blue[100] : blue[900]};
}
& > li {
padding: 8px;
border-radius: 0.45em;
&.highlighted,
&:hover {
background-color: ${theme.palette.mode === 'dark' ? grey[800] : grey[100]};
color: ${theme.palette.mode === 'dark' ? grey[300] : grey[900]};
}
&:hover {
background: ${theme.palette.mode === 'dark' ? grey[800] : grey[100]};
}
&[aria-selected='true'].highlighted {
background-color: ${theme.palette.mode === 'dark' ? blue[900] : blue[100]};
color: ${theme.palette.mode === 'dark' ? blue[100] : blue[900]};
}
&[aria-selected='true'] {
background: ${theme.palette.mode === 'dark' ? grey[700] : grey[200]};
}
&:before {
content: '';
width: 1ex;
height: 1ex;
margin-right: 1ex;
background-color: var(--color);
display: inline-block;
border-radius: 50%;
vertical-align: middle;
}
`,
);

function renderSelectedValue(value, options) {
const selectedOption = options.find((option) => option.value === value);

return selectedOption ? `${selectedOption.label} (${value})` : null;
}

function CustomSelect({ options, placeholder }) {
const listboxRef = React.useRef(null);
const [listboxVisible, setListboxVisible] = React.useState(false);

const { getButtonProps, getListboxProps, getOptionProps, value } = useSelect({
listboxRef,
options,
});
const { getButtonProps, getListboxProps, getOptionProps, getOptionState, value } =
useSelect({
listboxRef,
onOpenChange: setListboxVisible,
open: listboxVisible,
options,
});

React.useEffect(() => {
if (listboxVisible) {
Expand All @@ -108,21 +163,32 @@ function CustomSelect({ options, placeholder }) {
}, [listboxVisible]);

return (
<Root
onMouseOver={() => setListboxVisible(true)}
onMouseOut={() => setListboxVisible(false)}
onFocus={() => setListboxVisible(true)}
onBlur={() => setListboxVisible(false)}
>
<Root>
<Toggle {...getButtonProps()} style={{ '--color': value }}>
{value ?? <span className="placeholder">{placeholder ?? ' '}</span>}
{renderSelectedValue(value, options) || (
<span className="placeholder">{placeholder ?? ' '}</span>
)}

<UnfoldMoreRoundedIcon />
</Toggle>
<Listbox {...getListboxProps()} className={listboxVisible ? '' : 'hidden'}>
{options.map((option) => (
<li key={option.value} {...getOptionProps(option)}>
{option.label}
</li>
))}
<Listbox
{...getListboxProps()}
aria-hidden={!listboxVisible}
className={listboxVisible ? '' : 'hidden'}
>
{options.map((option) => {
const optionState = getOptionState(option);
return (
<Option
key={option.value}
{...getOptionProps(option)}
style={{ '--color': option.value }}
className={optionState.highlighted ? 'highlighted' : ''}
>
{option.label}
</Option>
);
})}
</Listbox>
</Root>
);
Expand Down

0 comments on commit 23276db

Please sign in to comment.