Use radio buttons for player list

This commit is contained in:
James Lyne 2021-05-28 00:13:46 +01:00
parent 97111f3bbc
commit d5ed9392a0
3 changed files with 39 additions and 25 deletions

View File

@ -18,10 +18,10 @@
<CollapsibleSection name="players">
<template v-slot:heading>{{ heading }} [{{ players.size }}/{{ maxPlayers }}]</template>
<template v-slot:default>
<ul class="section__content menu" role="listbox">
<RadioList class="section__content">
<PlayerListItem v-for="[account, player] in players" :key="account" :player="player"></PlayerListItem>
<li v-if="!players.size" class="section__skeleton">{{ skeletonPlayers }}</li>
</ul>
<span v-if="!players.size" class="section__skeleton">{{ skeletonPlayers }}</span>
</RadioList>
</template>
</CollapsibleSection>
</template>
@ -31,9 +31,11 @@ import PlayerListItem from "./PlayerListItem.vue";
import {defineComponent} from "@vue/runtime-core";
import {useStore} from "@/store";
import CollapsibleSection from "@/components/sidebar/CollapsibleSection.vue";
import RadioList from "@/components/util/RadioList.vue";
export default defineComponent({
components: {
RadioList,
CollapsibleSection,
PlayerListItem
},

View File

@ -15,13 +15,14 @@
-->
<template>
<li :class="{'player': true, 'player--hidden' : !!player.hidden, 'player--other-world': otherWorld}">
<input :id="`player-${player.account}`" type="radio" name="player" v-bind:value="player" v-model="followTarget"
@click.prevent="onInputClick" />
<label :for="`player-${player.account}`"
:class="{'player': true, 'player--hidden' : !!player.hidden, 'player--other-world': otherWorld}" :title="title"
@click.prevent="onLabelClick">
<img width="16" height="16" class="player__icon" :src="image" alt="" aria-hidden="true" />
<button class="player__name" type="button" :title="title"
:disbled="player.hidden"
@click.prevent="onClick"
@dblclick.prevent="follow" v-html="player.name"></button>
</li>
<span class="player__name" v-html="player.name"></span>
</label>
</template>
<script lang="ts">
@ -57,9 +58,10 @@ export default defineComponent({
}
}),
followTarget = computed(() => store.state.followTarget),
pan = () => {
if(!props.player.hidden) {
console.log('clear?');
store.commit(MutationTypes.CLEAR_FOLLOW_TARGET, undefined);
store.commit(MutationTypes.SET_PAN_TARGET, props.player);
}
@ -67,10 +69,19 @@ export default defineComponent({
follow = () => store.commit(MutationTypes.SET_FOLLOW_TARGET, props.player),
onClick = (e: MouseEvent) => {
onInputClick = (e: MouseEvent) => {
e.preventDefault();
if(e.shiftKey) {
follow();
e.preventDefault();
} else {
pan();
}
},
onLabelClick = (e: MouseEvent) => {
if(e.shiftKey || e.detail === 2) {
follow();
} else {
pan();
}
@ -88,9 +99,9 @@ export default defineComponent({
image,
title,
otherWorld,
pan,
follow,
onClick
followTarget,
onInputClick,
onLabelClick
}
},
@ -98,6 +109,8 @@ export default defineComponent({
</script>
<style lang="scss" scoped>
@import '../../scss/mixins';
.player {
.player__icon {
position: absolute;
@ -111,7 +124,7 @@ export default defineComponent({
}
.player__name {
padding-left: 3.5rem;
padding-left: 2.7rem;
}
&.player--hidden {
@ -119,14 +132,6 @@ export default defineComponent({
filter: grayscale(1);
opacity: 0.5;
}
.player__name {
cursor: not-allowed;
}
.player__name {
color: var(--text-disabled);
}
}
&.player--other-world {

View File

@ -50,7 +50,14 @@ export default defineComponent({
e.preventDefault();
} else if(e.key === 'Enter') {
if(e.target instanceof HTMLInputElement && e.target.type === 'radio') {
e.target.click();
const mouseEvent = new MouseEvent('click', {
ctrlKey: e.ctrlKey,
shiftKey: e.shiftKey,
metaKey: e.metaKey,
altKey: e.altKey,
});
e.target.dispatchEvent(mouseEvent);
}
}
}