Keyboard menu/widget navigation (#628)

* Keyboard menu navigation

* Fix dropdown keyboard navigation

* Fix merge error

* Some code review

* Interactive dropdowns

* Query by data attr not class name

* Add locking behaviour

* Change query selector style

* Change query selector style (again)

* Code review feedback

* Fix highlighted entry regression

* Styling and disabling checkbox tabindex in MenuLists

* Don't redirect space off canvas to backend

* Do not emit update if value same

* Escape closes all floating menus

* Close dropdowns on blur

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
0HyperCube
2022-05-25 14:10:18 -07:00
committed by Keavon Chambers
co-authored by Keavon Chambers
parent eca9797597
commit 889e988fb3
12 changed files with 176 additions and 15 deletions
@@ -1,12 +1,20 @@
<template>
<div class="menu-bar-input">
<div class="entry-container">
<div @click="() => visitWebsite('https://graphite.rs')" class="entry">
<button @click="() => visitWebsite('https://graphite.rs')" class="entry">
<IconLabel :icon="'GraphiteLogo'" />
</div>
</button>
</div>
<div class="entry-container" v-for="(entry, index) in entries" :key="index">
<div @click="() => onClick(entry)" class="entry" :class="{ open: entry.ref?.open }" data-hover-menu-spawner>
<div
@click="(e) => onClick(entry, e.target)"
@blur="() => close(entry)"
tabindex="0"
@keydown="entry.ref?.keydown"
class="entry"
:class="{ open: entry.ref?.open }"
data-hover-menu-spawner
>
<IconLabel v-if="entry.icon" :icon="entry.icon" />
<span v-if="entry.label">{{ entry.label }}</span>
</div>
@@ -36,6 +44,9 @@
align-items: center;
white-space: nowrap;
padding: 0 8px;
background: none;
border: 0;
margin: 0;
svg {
fill: var(--color-e-nearwhite);
@@ -207,10 +218,16 @@ function makeEntries(editor: Editor): MenuListEntries {
export default defineComponent({
inject: ["editor"],
methods: {
onClick(menuEntry: MenuListEntry) {
onClick(menuEntry: MenuListEntry, target: EventTarget | null) {
// Focus the target so that keyboard inputs are sent to the dropdown
(target as HTMLElement)?.focus();
if (menuEntry.ref) menuEntry.ref.isOpen = true;
else throw new Error("The menu bar floating menu has no associated ref");
},
close(menuEntry: MenuListEntry) {
if (menuEntry.ref) menuEntry.ref.isOpen = false;
},
// TODO: Move to backend
visitWebsite(url: string) {
// This method is required because `window` isn't accessible from the Vue component HTML