add better availability picker ux

This commit is contained in:
Michael Fatemi 2021-06-24 12:44:23 -04:00
parent e422fec6f5
commit a48e6eff91

View File

@ -1,5 +1,5 @@
import { CSSProperties } from '@material-ui/styles'; import { CSSProperties } from '@material-ui/styles';
import { useCallback, useMemo } from 'react'; import { MouseEventHandler, useCallback, useState } from 'react';
export type AvailabilityKind = export type AvailabilityKind =
| 'going/can-bring-someone' | 'going/can-bring-someone'
@ -18,10 +18,19 @@ const optionStyle: CSSProperties = {
height: '3rem', height: '3rem',
backgroundColor: 'white', backgroundColor: 'white',
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'row',
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
cursor: 'pointer', cursor: 'pointer',
transition: 'background-color 100ms cubic-bezier',
userSelect: 'none',
position: 'relative',
fontWeight: 'normal',
};
const selectedOptionStyle = {
...optionStyle,
fontWeight: 600,
}; };
function Option({ function Option({
@ -33,20 +42,17 @@ function Option({
current: AvailabilityKind; current: AvailabilityKind;
onSelected: (kind: AvailabilityKind) => void; onSelected: (kind: AvailabilityKind) => void;
}) { }) {
const style = useMemo( const selected = current === bind;
() =>
current === bind const select: MouseEventHandler<HTMLDivElement> = useCallback(
? { ...optionStyle, backgroundColor: '#5080f0', color: 'white' } (event) => {
: optionStyle, onSelected(bind);
[bind, current] },
[onSelected, bind]
); );
const select = useCallback(() => {
onSelected(bind);
}, [onSelected, bind]);
return ( return (
<div style={style} onClick={select}> <div style={selected ? selectedOptionStyle : optionStyle} onClick={select}>
{availabilityNames[bind]} {availabilityNames[bind]}
</div> </div>
); );
@ -54,11 +60,19 @@ function Option({
export default function Availability({ export default function Availability({
selected, selected,
onSelected, onSelected: onSelectedInner,
}: { }: {
selected: AvailabilityKind; selected: AvailabilityKind;
onSelected: (kind: AvailabilityKind) => void; onSelected: (kind: AvailabilityKind) => void;
}) { }) {
const [focused, setFocused] = useState(false);
const onSelected = useCallback(
(kind: AvailabilityKind) => {
setFocused(false);
onSelectedInner(kind);
},
[onSelectedInner]
);
return ( return (
<div <div
style={{ style={{
@ -70,23 +84,39 @@ export default function Availability({
marginTop: '1rem', marginTop: '1rem',
marginBottom: '1rem', marginBottom: '1rem',
}} }}
tabIndex={0}
onBlur={() => setFocused(false)}
> >
<Option {focused ? (
bind="going/can-bring-someone" <>
current={selected} <Option
onSelected={onSelected} bind="going/can-bring-someone"
/> current={selected}
<Option onSelected={onSelected}
bind="going/cannot-bring-someone" />
current={selected} <Option
onSelected={onSelected} bind="going/cannot-bring-someone"
/> current={selected}
<Option bind="interested" current={selected} onSelected={onSelected} /> onSelected={onSelected}
<Option />
bind="not-interested" <Option
current={selected} bind="interested"
onSelected={onSelected} current={selected}
/> onSelected={onSelected}
/>
<Option
bind="not-interested"
current={selected}
onSelected={onSelected}
/>
</>
) : (
<Option
bind={selected}
current={selected}
onSelected={() => setFocused(true)}
/>
)}
</div> </div>
); );
} }