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

View File

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

View File

@ -50,7 +50,14 @@ export default defineComponent({
e.preventDefault(); e.preventDefault();
} else if(e.key === 'Enter') { } else if(e.key === 'Enter') {
if(e.target instanceof HTMLInputElement && e.target.type === 'radio') { 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);
} }
} }
} }