From 50a23f17c53e06386c2b64e7f93f1496d440f5ba Mon Sep 17 00:00:00 2001 From: dragonwocky Date: Tue, 24 Jan 2023 00:15:10 +1100 Subject: [PATCH] fix(menu): keyboard triggering of inputs and switches via space/enter, don't trap tab in hotkey input --- src/core/menu/components/Button.mjs | 2 +- src/core/menu/components/Checkbox.mjs | 6 +++ src/core/menu/components/Input.mjs | 11 +++++- src/core/menu/components/Popup.mjs | 5 ++- src/core/menu/components/Toggle.mjs | 9 ++++- src/core/menu/islands/Profiles.mjs | 53 +++++++++++++++------------ 6 files changed, 59 insertions(+), 27 deletions(-) diff --git a/src/core/menu/components/Button.mjs b/src/core/menu/components/Button.mjs index b41ead1..21dadaf 100644 --- a/src/core/menu/components/Button.mjs +++ b/src/core/menu/components/Button.mjs @@ -25,7 +25,7 @@ function Button({ icon, variant, tagName, ...props }, ...children) { hover:bg-[color:var(--theme--bg-hover)]` }`, }); - return html`<${tagName ?? "button"} ...${props}> + return html`<${tagName ?? "button"} tabindex="0" ...${props}> ${icon ? html` { + if ([" ", "Enter"].includes(event.key)) { + event.preventDefault(); + $input.click(); + } + }} > ${$input}
diff --git a/src/core/menu/components/Input.mjs b/src/core/menu/components/Input.mjs index 45735eb..f7ea65e 100644 --- a/src/core/menu/components/Input.mjs +++ b/src/core/menu/components/Input.mjs @@ -7,13 +7,16 @@ import { extendProps, useState } from "../state.mjs"; const updateHotkey = (event) => { - event.preventDefault(); const keys = []; for (const modifier of ["metaKey", "ctrlKey", "altKey", "shiftKey"]) { if (!event[modifier]) continue; const alias = modifier[0].toUpperCase() + modifier.slice(1, -3); keys.push(alias); } + // retain tab for keyboard navigation of menu + if (event.key === "Tab" && !keys.length) { + return; + } else event.preventDefault(); if (!keys.length && ["Backspace", "Delete"].includes(event.key)) { event.target.value = ""; } else if (event.key) { @@ -146,6 +149,12 @@ function Input({ h-[28px] px-[8px] bg-[color:var(--theme--bg-secondary)] text-([14px] [color:var(--theme--fg-secondary)]) rounded-[4px] transition duration-[20ms] hover:bg-[color:var(--theme--bg-hover)]" + onkeydown=${(event) => { + if ([" ", "Enter"].includes(event.key)) { + event.preventDefault(); + $input.click(); + } + }} >${$input}${$icon.children[0]}${$filename} ${$clear} diff --git a/src/core/menu/components/Popup.mjs b/src/core/menu/components/Popup.mjs index b9057bf..f67a1c2 100644 --- a/src/core/menu/components/Popup.mjs +++ b/src/core/menu/components/Popup.mjs @@ -50,7 +50,10 @@ function Popup({ trigger, onopen, onclose, onbeforeclose }, ...children) { extendProps(trigger, { onclick: $popup.show, onkeydown(event) { - if (event.key === "Enter") $popup.show(); + if ([" ", "Enter"].includes(event.key)) { + event.preventDefault(); + $popup.show(); + } }, }); } diff --git a/src/core/menu/components/Toggle.mjs b/src/core/menu/components/Toggle.mjs index ec491b7..85c4802 100644 --- a/src/core/menu/components/Toggle.mjs +++ b/src/core/menu/components/Toggle.mjs @@ -11,7 +11,8 @@ function Toggle({ _get, _set, ...props }) { $input = html``; extendProps($input, { onchange: () => _set?.($input.checked) }); @@ -25,6 +26,12 @@ function Toggle({ _get, _set, ...props }) { tabindex="0" class="w-[30px] h-[18px] rounded-[44px] cursor-pointer transition duration-200 bg-[color:var(--theme--bg-hover)]" + onkeydown=${(event) => { + if ([" ", "Enter"].includes(event.key)) { + event.preventDefault(); + $input.click(); + } + }} >
`, - $success = html`<${Popup} + $uploadSuccess = html`<${Popup} onopen=${async () => ($successName.innerText = await getName())} >

The profile ${$successName} has been updated successfully.

`, - $error = html`<${Popup}> + $uploadError = html`<${Popup}>

{ const res = progress.currentTarget.result; try { - await profile.import({ - ...JSON.parse(res), - profileName: await getName(), - }); + await profile.import(JSON.parse(res)); setState({ rerender: true, databaseUpdated: true }); - $success.show(); - setTimeout(() => $success.hide(), 2000); + $uploadSuccess.show(); + setTimeout(() => $uploadSuccess.hide(), 2000); } catch (err) { - $error.show(); - setTimeout(() => $error.hide(), 2000); + $uploadError.show(); + setTimeout(() => $uploadError.hide(), 2000); } }; reader.readAsText(file); @@ -94,7 +91,14 @@ function Profile({ id }) { $a.click(); $a.remove(); }, - deleteProfile = async () => { + $uploadInput = html``; + + const deleteProfile = async () => { let profileIds = await db.get("profileIds"); if (!profileIds?.length) profileIds = ["default"]; // clear profile data @@ -108,9 +112,8 @@ function Profile({ id }) { await db.remove("activeProfile"); setState({ rerender: true, databaseUpdated: true }); } else setState({ rerender: true }); - }; - - const $delete = html`