More keyboard handlers

This commit is contained in:
James Lyne 2021-05-29 00:22:31 +01:00
parent 34bacc044f
commit 1f44f7e752
3 changed files with 55 additions and 18 deletions

View File

@ -18,11 +18,11 @@
<section class="sidebar" role="none" ref="sidebar"> <section class="sidebar" role="none" ref="sidebar">
<header class="sidebar__buttons"> <header class="sidebar__buttons">
<button v-if="mapCount > 1" :class="{'button--maps': true}" @click="toggleMaps" :title="messageWorlds" <button v-if="mapCount > 1" :class="{'button--maps': true}" @click="toggleMaps" :title="messageWorlds"
:aria-label="messageWorlds" :aria-expanded="mapsVisible"> :aria-label="messageWorlds" :aria-expanded="mapsVisible" @keydown="handleMapsKeydown">
<SvgIcon name="maps"></SvgIcon> <SvgIcon name="maps"></SvgIcon>
</button> </button>
<button :class="{'button--players': true}" @click="togglePlayers" :title="messagePlayers" <button :class="{'button--players': true}" @click="togglePlayers" :title="messagePlayers"
:aria-label="messagePlayers" :aria-expanded="playersVisible"> :aria-label="messagePlayers" :aria-expanded="playersVisible" @keydown="handlePlayersKeydown">
<SvgIcon name="players"></SvgIcon> <SvgIcon name="players"></SvgIcon>
</button> </button>
</header> </header>
@ -91,6 +91,19 @@ export default defineComponent({
handleKeyboardEvent(e, sectionHeadings); handleKeyboardEvent(e, sectionHeadings);
}; };
//Show sectinos on ArrowDown from button
const handleMapsKeydown = (e: KeyboardEvent) => {
if(e.key === 'ArrowDown') {
store.commit(MutationTypes.SET_UI_ELEMENT_VISIBILITY, {element: 'maps', state: true});
}
};
const handlePlayersKeydown = (e: KeyboardEvent) => {
if(e.key === 'ArrowDown') {
store.commit(MutationTypes.SET_UI_ELEMENT_VISIBILITY, {element: 'players', state: true});
}
};
const togglePlayers = () => store.commit(MutationTypes.TOGGLE_UI_ELEMENT_VISIBILITY, 'players'); const togglePlayers = () => store.commit(MutationTypes.TOGGLE_UI_ELEMENT_VISIBILITY, 'players');
const toggleMaps = () => store.commit(MutationTypes.TOGGLE_UI_ELEMENT_VISIBILITY, 'maps'); const toggleMaps = () => store.commit(MutationTypes.TOGGLE_UI_ELEMENT_VISIBILITY, 'maps');
@ -117,6 +130,9 @@ export default defineComponent({
followVisible, followVisible,
handleSidebarKeydown, handleSidebarKeydown,
handleMapsKeydown,
handlePlayersKeydown,
togglePlayers, togglePlayers,
toggleMaps toggleMaps
} }

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import {Control, ControlOptions, DomUtil} from 'leaflet'; import {Control, ControlOptions, DomEvent, DomUtil} from 'leaflet';
import {useStore} from "@/store"; import {useStore} from "@/store";
import {MutationTypes} from "@/store/mutation-types"; import {MutationTypes} from "@/store/mutation-types";
import {watch} from "@vue/runtime-core"; import {watch} from "@vue/runtime-core";
@ -30,22 +30,30 @@ export class ChatControl extends Control {
} }
onAdd() { onAdd() {
const chatButton = DomUtil.create('button', 'leaflet-control-chat') as HTMLButtonElement; const store = useStore(),
chatButton = DomUtil.create('button', 'leaflet-control-chat') as HTMLButtonElement;
chatButton.type = 'button'; chatButton.type = 'button';
chatButton.title = useStore().state.messages.chatTitle; chatButton.title = store.state.messages.chatTitle;
chatButton.innerHTML = ` chatButton.innerHTML = `
<svg class="svg-icon"> <svg class="svg-icon">
<use xlink:href="#icon--chat" /> <use xlink:href="#icon--chat" />
</svg>`; </svg>`;
chatButton.addEventListener('click', e => { chatButton.addEventListener('click', e => {
useStore().commit(MutationTypes.TOGGLE_UI_ELEMENT_VISIBILITY, 'chat'); store.commit(MutationTypes.TOGGLE_UI_ELEMENT_VISIBILITY, 'chat');
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
}); });
watch(useStore().state.ui.visibleElements, (newValue) => { //Open chat on ArrowRight from button
DomEvent.on(chatButton,'keydown', (e: Event) => {
if((e as KeyboardEvent).key === 'ArrowRight') {
store.commit(MutationTypes.SET_UI_ELEMENT_VISIBILITY, {element: 'chat', state: true});
}
});
watch(store.state.ui.visibleElements, (newValue) => {
chatButton.setAttribute('aria-expanded', newValue.has('chat').toString()); chatButton.setAttribute('aria-expanded', newValue.has('chat').toString());
}); });

View File

@ -17,17 +17,17 @@
* limitations under the License. * limitations under the License.
*/ */
import {Util, Control, DomEvent, LeafletEvent, Map as LeafletMap, Layer, DomUtil} from 'leaflet'; import {Control, DomEvent, DomUtil, Layer, LeafletEvent, Map as LeafletMap, Util} from 'leaflet';
import LayersObject = Control.LayersObject;
import LayersOptions = Control.LayersOptions;
import Layers = Control.Layers;
import '@/assets/icons/layers.svg'; import '@/assets/icons/layers.svg';
import '@/assets/icons/checkbox.svg'; import '@/assets/icons/checkbox.svg';
import {useStore} from "@/store"; import {useStore} from "@/store";
import {MutationTypes} from "@/store/mutation-types"; import {MutationTypes} from "@/store/mutation-types";
import {watch} from "vue"; import {nextTick, watch} from "vue";
import {handleKeyboardEvent} from "@/util/events"; import {handleKeyboardEvent} from "@/util/events";
import LayersObject = Control.LayersObject;
import LayersOptions = Control.LayersOptions;
import Layers = Control.Layers;
const store = useStore(); const store = useStore();
@ -91,18 +91,32 @@ export class DynmapLayerControl extends Control.Layers {
_initLayout() { _initLayout() {
const className = 'leaflet-control-layers', const className = 'leaflet-control-layers',
container = this._container = DomUtil.create('div', className); container = this._container = DomUtil.create('div', className),
section = this._section = DomUtil.create('section', className + '-list'),
button = this._layersButton = DomUtil.create('button', className + '-toggle', container);
DomEvent.disableClickPropagation(container); DomEvent.disableClickPropagation(container);
DomEvent.disableScrollPropagation(container); DomEvent.disableScrollPropagation(container);
//Open layer list on ArrowRight from button
DomEvent.on(button,'keydown', (e: Event) => {
if((e as KeyboardEvent).key === 'ArrowRight') {
store.commit(MutationTypes.SET_UI_ELEMENT_VISIBILITY, {element: 'layers', state: true});
}
});
DomEvent.on(container, 'keydown', (e: Event) => { DomEvent.on(container, 'keydown', (e: Event) => {
//Close layer list on ArrowLeft from within list
if((e as KeyboardEvent).key === 'ArrowLeft') {
e.preventDefault();
store.commit(MutationTypes.SET_UI_ELEMENT_VISIBILITY, {element: 'layers', state: false});
nextTick(() => button.focus());
}
const elements = Array.from(container.querySelectorAll('input')) as HTMLElement[]; const elements = Array.from(container.querySelectorAll('input')) as HTMLElement[];
handleKeyboardEvent(e as KeyboardEvent, elements); handleKeyboardEvent(e as KeyboardEvent, elements);
}); });
DomEvent.on(button,'click', () => store.commit(MutationTypes.TOGGLE_UI_ELEMENT_VISIBILITY, 'layers'));
const section = this._section = DomUtil.create('section', className + '-list'),
button = this._layersButton = DomUtil.create('button', className + '-toggle', container);
section.style.display = 'none'; section.style.display = 'none';
@ -113,9 +127,8 @@ export class DynmapLayerControl extends Control.Layers {
<use xlink:href="#icon--layers" /> <use xlink:href="#icon--layers" />
</svg>`; </svg>`;
//Use vuex to toggle and track expanded state
DomEvent.on(button,'click', () => store.commit(MutationTypes.TOGGLE_UI_ELEMENT_VISIBILITY, 'layers'));
//Use vuex track expanded state
watch(store.state.ui.visibleElements, (newValue) => { watch(store.state.ui.visibleElements, (newValue) => {
if(newValue.has('layers') && !this.visible) { if(newValue.has('layers') && !this.visible) {
this.expand(); this.expand();