From 45f1bd291e0afe9b852918247269ee0a38046f34 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Mon, 26 Dec 2022 03:34:22 -0800 Subject: [PATCH] Fix being able to open multiple selects at once This was miserable --- components/AccountModal/index.tsx | 52 ++++++---- components/AwakeningSelect/index.tsx | 9 +- components/AxSelect/index.tsx | 26 ++++- components/Dialog/index.tsx | 7 +- components/FilterBar/index.tsx | 7 ++ components/JobDropdown/index.tsx | 1 + components/RaidDropdown/index.tsx | 1 + components/Select/index.tsx | 31 +++++- components/SelectTableField/index.tsx | 6 +- components/WeaponKeySelect/index.tsx | 12 +-- components/WeaponModal/index.tsx | 139 ++++++++++++++++++-------- 11 files changed, 215 insertions(+), 76 deletions(-) diff --git a/components/AccountModal/index.tsx b/components/AccountModal/index.tsx index d3e1b615..c5da21ef 100644 --- a/components/AccountModal/index.tsx +++ b/components/AccountModal/index.tsx @@ -80,6 +80,10 @@ const AccountModal = (props: Props) => { // const [privateProfile, setPrivateProfile] = useState(false) // Setup + const [pictureOpen, setPictureOpen] = useState(false) + const [genderOpen, setGenderOpen] = useState(false) + const [languageOpen, setLanguageOpen] = useState(false) + const [themeOpen, setThemeOpen] = useState(false) // UI management function openChange(open: boolean) { @@ -87,16 +91,10 @@ const AccountModal = (props: Props) => { } function openSelect(name: 'picture' | 'gender' | 'language' | 'theme') { - const stateVars = selectOpenState - Object.keys(stateVars).forEach((key) => { - if (key === name) { - stateVars[name] = true - } else { - stateVars[key] = false - } - }) - - setSelectOpenState(stateVars) + setPictureOpen(name === 'picture' ? !pictureOpen : false) + setGenderOpen(name === 'gender' ? !genderOpen : false) + setLanguageOpen(name === 'language' ? !languageOpen : false) + setThemeOpen(name === 'theme' ? !themeOpen : false) } // Event handlers @@ -117,6 +115,14 @@ const AccountModal = (props: Props) => { setAppTheme(value) } + function onEscapeKeyDown(event: KeyboardEvent) { + if (pictureOpen || genderOpen || languageOpen || themeOpen) { + return event.preventDefault() + } else { + setOpen(false) + } + } + // API calls function update(event: React.FormEvent) { event.preventDefault() @@ -189,9 +195,10 @@ const AccountModal = (props: Props) => { description={t('modals.settings.descriptions.picture')} className="Image" label={t('modals.settings.labels.picture')} - open={selectOpenState.picture} - onClick={() => openSelect('picture')} + open={pictureOpen} + onOpenChange={() => openSelect('picture')} onChange={handlePictureChange} + onClose={() => setPictureOpen(false)} imageAlt={t('modals.settings.labels.image_alt')} imageClass={pictureData.find((i) => i.filename === picture)?.element} imageSrc={[`/profile/${picture}.png`, `/profile/${picture}@2x.png 2x`]} @@ -206,9 +213,10 @@ const AccountModal = (props: Props) => { name="gender" description={t('modals.settings.descriptions.gender')} label={t('modals.settings.labels.gender')} - open={selectOpenState.gender} - onClick={() => openSelect('gender')} + open={genderOpen} + onOpenChange={() => openSelect('gender')} onChange={handleGenderChange} + onClose={() => setGenderOpen(false)} value={`${gender}`} > @@ -224,9 +232,10 @@ const AccountModal = (props: Props) => { openSelect('language')} + open={languageOpen} + onOpenChange={() => openSelect('language')} onChange={handleLanguageChange} + onClose={() => setLanguageOpen(false)} value={language} > @@ -242,9 +251,10 @@ const AccountModal = (props: Props) => { openSelect('theme')} + open={themeOpen} + onOpenChange={() => openSelect('theme')} onChange={handleThemeChange} + onClose={() => setThemeOpen(false)} value={theme} > @@ -274,7 +284,11 @@ const AccountModal = (props: Props) => { {t('menu.settings')} - + {}} + onEscapeKeyDown={onEscapeKeyDown} + >
diff --git a/components/AwakeningSelect/index.tsx b/components/AwakeningSelect/index.tsx index ed01ccfb..eb6158bb 100644 --- a/components/AwakeningSelect/index.tsx +++ b/components/AwakeningSelect/index.tsx @@ -17,6 +17,7 @@ interface Props { object: 'character' | 'weapon' awakeningType?: number awakeningLevel?: number + onOpenChange: (open: boolean) => void sendValidity: (isValid: boolean) => void sendValues: (type: number, level: number) => void } @@ -81,6 +82,11 @@ const AwakeningSelect = (props: Props) => { // Classes function changeOpen() { setOpen(!open) + props.onOpenChange(!open) + } + + function onClose() { + props.onOpenChange(false) } function generateOptions(object: 'character' | 'weapon') { @@ -165,7 +171,8 @@ const AwakeningSelect = (props: Props) => { value={`${awakeningType}`} open={open} onValueChange={handleSelectChange} - onClick={() => changeOpen()} + onOpenChange={() => changeOpen()} + onClose={onClose} triggerClass="modal" > {generateOptions(props.object)} diff --git a/components/AxSelect/index.tsx b/components/AxSelect/index.tsx index 5c33def7..01c9c17e 100644 --- a/components/AxSelect/index.tsx +++ b/components/AxSelect/index.tsx @@ -20,6 +20,7 @@ interface ErrorMap { interface Props { axType: number currentSkills?: SimpleAxSkill[] + onOpenChange: (index: 1 | 2, open: boolean) => void sendValidity: (isValid: boolean) => void sendValues: ( primaryAxModifier: number, @@ -193,9 +194,22 @@ const AXSelect = (props: Props) => { : undefined } - function openSelect(ref: ForwardedRef) { - if (ref === primaryAxModifierSelect) setOpenAX1(!openAX1) - if (ref === secondaryAxModifierSelect) setOpenAX2(!openAX2) + function openSelect(index: 1 | 2) { + if (index === 1) { + setOpenAX1(!openAX1) + setOpenAX2(false) + props.onOpenChange(1, !openAX1) + props.onOpenChange(2, false) + } else if (index === 2) { + setOpenAX2(!openAX2) + setOpenAX1(false) + props.onOpenChange(2, !openAX2) + props.onOpenChange(1, false) + } + } + + function onClose(index: 1 | 2) { + props.onOpenChange(index, false) } function generateOptions(modifierSet: number) { @@ -392,8 +406,9 @@ const AXSelect = (props: Props) => { key="ax1" value={`${primaryAxModifier}`} open={openAX1} + onClose={() => onClose(1)} + onOpenChange={() => openSelect(1)} onValueChange={handleAX1SelectChange} - onClick={() => openSelect(primaryAxModifierSelect)} triggerClass="modal" > {generateOptions(0)} @@ -419,8 +434,9 @@ const AXSelect = (props: Props) => { key="ax2" value={`${secondaryAxModifier}`} open={openAX2} + onClose={() => onClose(2)} + onOpenChange={() => openSelect(2)} onValueChange={handleAX2SelectChange} - onClick={() => openSelect(secondaryAxModifierSelect)} triggerClass="modal" ref={secondaryAxModifierSelect} > diff --git a/components/Dialog/index.tsx b/components/Dialog/index.tsx index fb58acd8..54a0be03 100644 --- a/components/Dialog/index.tsx +++ b/components/Dialog/index.tsx @@ -8,7 +8,10 @@ interface Props extends React.DetailedHTMLProps< React.DialogHTMLAttributes, HTMLDivElement - > {} + > { + onEscapeKeyDown: (event: KeyboardEvent) => void + onOpenAutoFocus: (event: Event) => void +} export const DialogContent = React.forwardRef( function dialog({ children, ...props }, forwardedRef) { @@ -25,6 +28,8 @@ export const DialogContent = React.forwardRef( {children} diff --git a/components/FilterBar/index.tsx b/components/FilterBar/index.tsx index dfaec65b..e145b12c 100644 --- a/components/FilterBar/index.tsx +++ b/components/FilterBar/index.tsx @@ -60,12 +60,18 @@ const FilterBar = (props: Props) => { props.onFilter({ raidSlug: slug }) } + function onSelectChange(name: 'element' | 'recency') { + setElementOpen(name === 'element' ? !elementOpen : false) + setRecencyOpen(name === 'recency' ? !recencyOpen : false) + } + return (
{props.children} diff --git a/components/WeaponKeySelect/index.tsx b/components/WeaponKeySelect/index.tsx index e430635a..a11c1474 100644 --- a/components/WeaponKeySelect/index.tsx +++ b/components/WeaponKeySelect/index.tsx @@ -9,10 +9,13 @@ import './index.scss' // Props interface Props { + open: boolean currentValue?: WeaponKey series: number slot: number onChange?: (value: string, slot: number) => void + onOpenChange: () => void + onClose?: () => void } const WeaponKeySelect = React.forwardRef( @@ -64,10 +67,6 @@ const WeaponKeySelect = React.forwardRef( fetchWeaponKeys() }, [props.series, props.slot]) - function openSelect() { - setOpen(!open) - } - function weaponKeyGroup(index: number) { ;['α', 'β', 'γ', 'Δ'].sort((a, b) => a.localeCompare(b, 'el')) @@ -125,9 +124,10 @@ const WeaponKeySelect = React.forwardRef(