Sidebar cleanup and fixes
- Merge functions handling sidebar section events, focusing and toggling - Use hidden attribute instead of v-show for sidebar sections - Ignore hidden sidebar sections when navigating with the keyboard - Allow focusing an already visible section via down arrow on its button
This commit is contained in:
parent
ef28afaceb
commit
4e8780b3a4
@ -17,24 +17,24 @@
|
|||||||
<template>
|
<template>
|
||||||
<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 || serverCount > 1" :class="{'button--maps': true}" @click="toggleMaps"
|
<button v-if="mapCount > 1 || serverCount > 1" class="button--maps" data-section="maps"
|
||||||
:title="mapCount > 1 ? messageWorlds : messageServers"
|
:title="mapCount > 1 ? messageWorlds : messageServers"
|
||||||
:aria-label="mapCount > 1 ? messageWorlds : messageServers"
|
:aria-label="mapCount > 1 ? messageWorlds : messageServers"
|
||||||
:aria-expanded="mapsVisible" @keydown="handleMapsKeydown">
|
:aria-expanded="mapsVisible"
|
||||||
|
@click="handleSectionClick" @keydown="handleSectionKeydown">
|
||||||
<SvgIcon :name="mapCount > 1 ? 'maps' : 'servers'"></SvgIcon>
|
<SvgIcon :name="mapCount > 1 ? 'maps' : 'servers'"></SvgIcon>
|
||||||
</button>
|
</button>
|
||||||
<button v-if="playerMakersEnabled" :class="{'button--players': true}" @click="togglePlayers"
|
<button v-if="playerMakersEnabled" class="button--players" data-section="players"
|
||||||
:title="messagePlayers" :aria-label="messagePlayers" :aria-expanded="playersVisible"
|
:title="messagePlayers" :aria-label="messagePlayers" :aria-expanded="playersVisible"
|
||||||
@keydown="handlePlayersKeydown">
|
@click="handleSectionClick" @keydown="handleSectionKeydown">
|
||||||
<SvgIcon name="players"></SvgIcon>
|
<SvgIcon name="players"></SvgIcon>
|
||||||
</button>
|
</button>
|
||||||
</header>
|
</header>
|
||||||
<div class="sidebar__content" @keydown="handleSidebarKeydown">
|
<div class="sidebar__content" @keydown="handleSidebarKeydown">
|
||||||
<ServersSection v-if="serverCount > 1" v-show="mapsVisible"></ServersSection>
|
<ServersSection v-if="serverCount > 1" :hidden="!mapsVisible"></ServersSection>
|
||||||
<WorldsSection v-if="mapCount > 1" v-show="mapsVisible"></WorldsSection>
|
<WorldsSection v-if="mapCount > 1" :hidden="!mapsVisible"></WorldsSection>
|
||||||
<PlayersSection id="players" v-if="playerMakersEnabled && previouslyVisible.has('players')"
|
<PlayersSection v-if="playerMakersEnabled && previouslyVisible.has('players')" :hidden="!playersVisible"></PlayersSection>
|
||||||
v-show="playersVisible"></PlayersSection>
|
<FollowTargetSection v-if="following" :hidden="!followVisible" :target="following"></FollowTargetSection>
|
||||||
<FollowTargetSection v-if="following" v-show="followVisible" :target="following"></FollowTargetSection>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
@ -54,6 +54,7 @@ import "@/assets/icons/servers.svg";
|
|||||||
import {nextTick, ref, watch} from "vue";
|
import {nextTick, ref, watch} from "vue";
|
||||||
import {handleKeyboardEvent} from "@/util/events";
|
import {handleKeyboardEvent} from "@/util/events";
|
||||||
import {focus} from "@/util";
|
import {focus} from "@/util";
|
||||||
|
import {LiveAtlasSidebarSection} from "@/index";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
@ -96,33 +97,41 @@ export default defineComponent({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sectionHeadings: HTMLElement[] = Array.from(sidebar.value!.querySelectorAll('.section__heading button'));
|
const sectionHeadings: HTMLElement[] = Array.from(sidebar.value!
|
||||||
|
.querySelectorAll('.sidebar__section:not([hidden]) .section__heading button'));
|
||||||
handleKeyboardEvent(e, sectionHeadings);
|
handleKeyboardEvent(e, sectionHeadings);
|
||||||
};
|
};
|
||||||
|
|
||||||
//Show sectinos on ArrowDown from button
|
//Show sections on ArrowDown from button
|
||||||
const handleMapsKeydown = (e: KeyboardEvent) => {
|
const handleSectionKeydown = (e: KeyboardEvent) => {
|
||||||
if(e.key === 'ArrowDown') {
|
const section = (e.target as HTMLElement).dataset.section as LiveAtlasSidebarSection;
|
||||||
store.commit(MutationTypes.SET_UI_ELEMENT_VISIBILITY, {element: 'maps', state: true});
|
|
||||||
|
if(e.key === 'ArrowDown' && section) {
|
||||||
|
if(currentlyVisible.value.has(section)) {
|
||||||
|
focusSection(section);
|
||||||
|
} else {
|
||||||
|
store.commit(MutationTypes.SET_UI_ELEMENT_VISIBILITY, {
|
||||||
|
element: section,
|
||||||
|
state: true
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePlayersKeydown = (e: KeyboardEvent) => {
|
const handleSectionClick = (e: MouseEvent) => {
|
||||||
if(e.key === 'ArrowDown') {
|
const section = (e.target as HTMLElement).dataset.section as LiveAtlasSidebarSection;
|
||||||
store.commit(MutationTypes.SET_UI_ELEMENT_VISIBILITY, {element: 'players', state: true});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const togglePlayers = () => store.commit(MutationTypes.TOGGLE_UI_ELEMENT_VISIBILITY, 'players');
|
if(section) {
|
||||||
const toggleMaps = () => store.commit(MutationTypes.TOGGLE_UI_ELEMENT_VISIBILITY, 'maps');
|
store.commit(MutationTypes.TOGGLE_UI_ELEMENT_VISIBILITY, section);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Move focus when sidebar sections become visible
|
//Move focus when sidebar sections become visible
|
||||||
const focusMaps = () => focus('.section__heading button');
|
const focusSection = (section: LiveAtlasSidebarSection) => focus(`[data-section=${section}] .section__heading button`);
|
||||||
const focusPlayers = () => focus('#players-heading');
|
|
||||||
|
|
||||||
//Focus sidebar sections when they become visible, except on initial load
|
//Focus sidebar sections when they become visible, except on initial load
|
||||||
watch(playersVisible, newValue => newValue && !firstLoad.value && nextTick(() => focusPlayers()));
|
watch(playersVisible, newValue => newValue && !firstLoad.value && nextTick(() => focusSection('players')));
|
||||||
watch(mapsVisible, newValue => newValue && !firstLoad.value && nextTick(() => focusMaps()));
|
watch(mapsVisible, newValue => newValue && !firstLoad.value && nextTick(() => focusSection('maps')));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
sidebar,
|
sidebar,
|
||||||
@ -142,11 +151,8 @@ export default defineComponent({
|
|||||||
playerMakersEnabled,
|
playerMakersEnabled,
|
||||||
|
|
||||||
handleSidebarKeydown,
|
handleSidebarKeydown,
|
||||||
handleMapsKeydown,
|
handleSectionKeydown,
|
||||||
handlePlayersKeydown,
|
handleSectionClick,
|
||||||
|
|
||||||
togglePlayers,
|
|
||||||
toggleMaps
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -95,6 +95,10 @@ export default defineComponent({
|
|||||||
max-width: 26rem;
|
max-width: 26rem;
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
|
|
||||||
|
&[hidden] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.section__heading {
|
.section__heading {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
2
src/index.d.ts
vendored
2
src/index.d.ts
vendored
@ -98,7 +98,7 @@ interface LiveAtlasUIConfig {
|
|||||||
compactPlayerMarkers: boolean;
|
compactPlayerMarkers: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type LiveAtlasUIElement = 'layers' | 'chat' | 'players' | 'maps';
|
export type LiveAtlasUIElement = 'layers' | 'chat' | LiveAtlasSidebarSection;
|
||||||
export type LiveAtlasUIModal = 'login' | 'settings';
|
export type LiveAtlasUIModal = 'login' | 'settings';
|
||||||
export type LiveAtlasSidebarSection = 'servers' | 'players' | 'maps';
|
export type LiveAtlasSidebarSection = 'servers' | 'players' | 'maps';
|
||||||
export type LiveAtlasDimension = 'overworld' | 'nether' | 'end';
|
export type LiveAtlasDimension = 'overworld' | 'nether' | 'end';
|
||||||
|
Loading…
Reference in New Issue
Block a user