From a48e6eff91b2fa44d5399a6e2c980194f8882354 Mon Sep 17 00:00:00 2001 From: Michael Fatemi <myfatemi04@gmail.com> Date: Thu, 24 Jun 2021 12:44:23 -0400 Subject: [PATCH] add better availability picker ux --- src/components/NewUI/Availability.tsx | 90 ++++++++++++++++++--------- 1 file changed, 60 insertions(+), 30 deletions(-) diff --git a/src/components/NewUI/Availability.tsx b/src/components/NewUI/Availability.tsx index 75718bf..7ade014 100644 --- a/src/components/NewUI/Availability.tsx +++ b/src/components/NewUI/Availability.tsx @@ -1,5 +1,5 @@ import { CSSProperties } from '@material-ui/styles'; -import { useCallback, useMemo } from 'react'; +import { MouseEventHandler, useCallback, useState } from 'react'; export type AvailabilityKind = | 'going/can-bring-someone' @@ -18,10 +18,19 @@ const optionStyle: CSSProperties = { height: '3rem', backgroundColor: 'white', display: 'flex', - flexDirection: 'column', + flexDirection: 'row', justifyContent: 'center', alignItems: 'center', cursor: 'pointer', + transition: 'background-color 100ms cubic-bezier', + userSelect: 'none', + position: 'relative', + fontWeight: 'normal', +}; + +const selectedOptionStyle = { + ...optionStyle, + fontWeight: 600, }; function Option({ @@ -33,20 +42,17 @@ function Option({ current: AvailabilityKind; onSelected: (kind: AvailabilityKind) => void; }) { - const style = useMemo( - () => - current === bind - ? { ...optionStyle, backgroundColor: '#5080f0', color: 'white' } - : optionStyle, - [bind, current] + const selected = current === bind; + + const select: MouseEventHandler<HTMLDivElement> = useCallback( + (event) => { + onSelected(bind); + }, + [onSelected, bind] ); - const select = useCallback(() => { - onSelected(bind); - }, [onSelected, bind]); - return ( - <div style={style} onClick={select}> + <div style={selected ? selectedOptionStyle : optionStyle} onClick={select}> {availabilityNames[bind]} </div> ); @@ -54,11 +60,19 @@ function Option({ export default function Availability({ selected, - onSelected, + onSelected: onSelectedInner, }: { selected: AvailabilityKind; onSelected: (kind: AvailabilityKind) => void; }) { + const [focused, setFocused] = useState(false); + const onSelected = useCallback( + (kind: AvailabilityKind) => { + setFocused(false); + onSelectedInner(kind); + }, + [onSelectedInner] + ); return ( <div style={{ @@ -70,23 +84,39 @@ export default function Availability({ marginTop: '1rem', marginBottom: '1rem', }} + tabIndex={0} + onBlur={() => setFocused(false)} > - <Option - bind="going/can-bring-someone" - current={selected} - onSelected={onSelected} - /> - <Option - bind="going/cannot-bring-someone" - current={selected} - onSelected={onSelected} - /> - <Option bind="interested" current={selected} onSelected={onSelected} /> - <Option - bind="not-interested" - current={selected} - onSelected={onSelected} - /> + {focused ? ( + <> + <Option + bind="going/can-bring-someone" + current={selected} + onSelected={onSelected} + /> + <Option + bind="going/cannot-bring-someone" + current={selected} + onSelected={onSelected} + /> + <Option + bind="interested" + current={selected} + onSelected={onSelected} + /> + <Option + bind="not-interested" + current={selected} + onSelected={onSelected} + /> + </> + ) : ( + <Option + bind={selected} + current={selected} + onSelected={() => setFocused(true)} + /> + )} </div> ); }