Merge branch '576-no-span-button' into 'develop'
Fix #576: Improved keyboard accessibility on player, queue and various controls Closes #576 See merge request funkwhale/funkwhale!453
This commit is contained in:
commit
7a5a7208bf
|
@ -0,0 +1 @@
|
|||
Improved keyboard accessibility on player, queue and various controls (#576)
|
|
@ -359,6 +359,13 @@ html, body {
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
.ui.really.basic.button {
|
||||
&:not(:focus) {
|
||||
box-shadow: none !important;
|
||||
background-color: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.floated.buttons .button ~ .dropdown {
|
||||
border-left: none;
|
||||
}
|
||||
|
@ -380,4 +387,27 @@ a {
|
|||
display: none;
|
||||
}
|
||||
|
||||
button.reset {
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: auto;
|
||||
overflow: visible;
|
||||
|
||||
background: transparent;
|
||||
|
||||
/* inherit font & color from ancestor */
|
||||
color: inherit;
|
||||
font: inherit;
|
||||
|
||||
/* Normalize `line-height`. Cannot be changed from `normal` in Firefox 4+. */
|
||||
line-height: normal;
|
||||
|
||||
/* Corrects font smoothing for webkit */
|
||||
-webkit-font-smoothing: inherit;
|
||||
-moz-osx-font-smoothing: inherit;
|
||||
/* Corrects inability to style clickable `input` types in iOS */
|
||||
-webkit-appearance: none;
|
||||
text-align: inherit;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
<template>
|
||||
<div class="ui pagination menu">
|
||||
<div
|
||||
<a href
|
||||
:disabled="current - 1 < 1"
|
||||
@click="selectPage(current - 1)"
|
||||
:class="[{'disabled': current - 1 < 1}, 'item']"><i class="angle left icon"></i></div>
|
||||
@click.prevent.stop="selectPage(current - 1)"
|
||||
:class="[{'disabled': current - 1 < 1}, 'item']"><i class="angle left icon"></i></a>
|
||||
<template v-if="!compact">
|
||||
<div
|
||||
<a href
|
||||
v-if="page !== 'skip'"
|
||||
v-for="page in pages"
|
||||
@click="selectPage(page)"
|
||||
@click.prevent.stop="selectPage(page)"
|
||||
:class="[{'active': page === current}, 'item']">
|
||||
{{ page }}
|
||||
</div>
|
||||
</a href>
|
||||
<div v-else class="disabled item">
|
||||
...
|
||||
</div>
|
||||
</template>
|
||||
<div
|
||||
<a href
|
||||
:disabled="current + 1 > maxPage"
|
||||
@click="selectPage(current + 1)"
|
||||
:class="[{'disabled': current + 1 > maxPage}, 'item']"><i class="angle right icon"></i></div>
|
||||
@click.prevent.stop="selectPage(current + 1)"
|
||||
:class="[{'disabled': current + 1 > maxPage}, 'item']"><i class="angle right icon"></i></a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -90,4 +90,3 @@ export default {
|
|||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
|
||||
<div class="menu-area">
|
||||
<div class="ui compact fluid two item inverted menu">
|
||||
<a class="active item" @click="selectedTab = 'library'" data-tab="library"><translate>Browse</translate></a>
|
||||
<a class="item" @click="selectedTab = 'queue'" data-tab="queue">
|
||||
<a class="active item" href @click.prevent.stop="selectedTab = 'library'" data-tab="library"><translate>Browse</translate></a>
|
||||
<a class="item" href @click.prevent.stop="selectedTab = 'queue'" data-tab="queue">
|
||||
<translate>Queue</translate>
|
||||
<template v-if="queue.tracks.length === 0">
|
||||
<translate>(empty)</translate>
|
||||
|
@ -128,8 +128,10 @@
|
|||
<img class="ui mini image" v-else src="../assets/audio/default-cover.png">
|
||||
</td>
|
||||
<td colspan="4">
|
||||
<strong>{{ track.title }}</strong><br />
|
||||
{{ track.artist.name }}
|
||||
<button class="title reset ellipsis">
|
||||
<strong>{{ track.title }}</strong><br />
|
||||
{{ track.artist.name }}
|
||||
</button>
|
||||
</td>
|
||||
<td>
|
||||
<template v-if="$store.getters['favorites/isFavorite'](track.id)">
|
||||
|
@ -137,7 +139,9 @@
|
|||
</template>
|
||||
</td>
|
||||
<td>
|
||||
<i @click.stop="cleanTrack(index)" class="circular trash icon"></i>
|
||||
<button @click.stop="cleanTrack(index)" :class="['ui', {'inverted': index != queue.currentIndex}, 'really', 'tiny', 'basic', 'circular', 'icon', 'button']">
|
||||
<i class="trash icon"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</draggable>
|
||||
|
@ -428,4 +432,8 @@ $sidebar-color: #3d3e3f;
|
|||
top: -0.5em;
|
||||
width: 3em;
|
||||
}
|
||||
|
||||
:not(.active) button.title {
|
||||
outline-color: white;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -12,9 +12,9 @@
|
|||
<div v-if="!discrete && !iconOnly" :class="['ui', {disabled: !playable}, 'floating', 'dropdown', {'icon': !dropdownOnly}, {'button': !dropdownOnly}]">
|
||||
<i :class="dropdownIconClasses.concat(['icon'])"></i>
|
||||
<div class="menu">
|
||||
<div class="item" :disabled="!playable" @click="add" :title="labels.addToQueue"><i class="plus icon"></i><translate>Add to queue</translate></div>
|
||||
<div class="item" :disabled="!playable" @click="addNext()" :title="labels.playNext"><i class="step forward icon"></i><translate>Play next</translate></div>
|
||||
<div class="item" :disabled="!playable" @click="addNext(true)" :title="labels.playNow"><i class="play icon"></i><translate>Play now</translate></div>
|
||||
<button class="item basic" ref="add" data-ref="add" :disabled="!playable" @click.stop.prevent="add" :title="labels.addToQueue"><i class="plus icon"></i><translate>Add to queue</translate></button>
|
||||
<button class="item basic" ref="addNext" data-ref="addNext" :disabled="!playable" @click.stop.prevent="addNext()" :title="labels.playNext"><i class="step forward icon"></i><translate>Play next</translate></button>
|
||||
<button class="item basic" ref="playNow" data-ref="playNow" :disabled="!playable" @click.stop.prevent="addNext(true)" :title="labels.playNow"><i class="play icon"></i><translate>Play now</translate></button>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
|
@ -46,7 +46,16 @@ export default {
|
|||
}
|
||||
},
|
||||
mounted () {
|
||||
jQuery(this.$el).find('.ui.dropdown').dropdown()
|
||||
let self = this
|
||||
jQuery(this.$el).find('.ui.dropdown').dropdown({
|
||||
selectOnKeydown: false,
|
||||
action: function (text, value, $el) {
|
||||
// used ton ensure focusing the dropdown and clicking via keyboard
|
||||
// works as expected
|
||||
self.$refs[$el.data('ref')].click()
|
||||
jQuery(self.$el).find('.ui.dropdown').dropdown('hide')
|
||||
}
|
||||
})
|
||||
},
|
||||
computed: {
|
||||
labels () {
|
||||
|
@ -139,6 +148,7 @@ export default {
|
|||
this.getPlayableTracks().then((tracks) => {
|
||||
self.$store.dispatch('queue/appendMany', {tracks: tracks}).then(() => self.addMessage(tracks))
|
||||
})
|
||||
jQuery(self.$el).find('.ui.dropdown').dropdown('hide')
|
||||
},
|
||||
addNext (next) {
|
||||
let self = this
|
||||
|
@ -150,6 +160,7 @@ export default {
|
|||
self.$store.dispatch('queue/next')
|
||||
}
|
||||
})
|
||||
jQuery(self.$el).find('.ui.dropdown').dropdown('hide')
|
||||
},
|
||||
addMessage (tracks) {
|
||||
if (tracks.length < 1) {
|
||||
|
@ -170,4 +181,8 @@ export default {
|
|||
i {
|
||||
cursor: pointer;
|
||||
}
|
||||
button.item {
|
||||
background-color: white;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -31,9 +31,11 @@
|
|||
<div class="description">
|
||||
<track-favorite-icon
|
||||
v-if="$store.state.auth.authenticated"
|
||||
:class="{'inverted': !$store.getters['favorites/isFavorite'](currentTrack.id)}"
|
||||
:track="currentTrack"></track-favorite-icon>
|
||||
<track-playlist-icon
|
||||
v-if="$store.state.auth.authenticated"
|
||||
:class="['inverted']"
|
||||
:track="currentTrack"></track-playlist-icon>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -55,44 +57,71 @@
|
|||
</div>
|
||||
|
||||
<div class="two wide column controls ui grid">
|
||||
<div
|
||||
<a
|
||||
href
|
||||
:title="labels.previousTrack"
|
||||
:aria-label="labels.previousTrack"
|
||||
class="two wide column control"
|
||||
@click.prevent.stop="previous"
|
||||
:disabled="emptyQueue">
|
||||
<i @click="previous" :class="['ui', 'backward', {'disabled': emptyQueue}, 'secondary', 'icon']"></i>
|
||||
</div>
|
||||
<div
|
||||
<i :class="['ui', 'backward', {'disabled': emptyQueue}, 'secondary', 'icon']"></i>
|
||||
</a>
|
||||
<a
|
||||
href
|
||||
v-if="!playing"
|
||||
:title="labels.play"
|
||||
:aria-label="labels.play"
|
||||
@click.prevent.stop="togglePlay"
|
||||
class="two wide column control">
|
||||
<i @click="togglePlay" :class="['ui', 'play', {'disabled': !currentTrack}, 'secondary', 'icon']"></i>
|
||||
</div>
|
||||
<div
|
||||
<i :class="['ui', 'play', {'disabled': !currentTrack}, 'secondary', 'icon']"></i>
|
||||
</a>
|
||||
<a
|
||||
href
|
||||
v-else
|
||||
:title="labels.pause"
|
||||
:aria-label="labels.pause"
|
||||
@click.prevent.stop="togglePlay"
|
||||
class="two wide column control">
|
||||
<i @click="togglePlay" :class="['ui', 'pause', {'disabled': !currentTrack}, 'secondary', 'icon']"></i>
|
||||
</div>
|
||||
<div
|
||||
<i :class="['ui', 'pause', {'disabled': !currentTrack}, 'secondary', 'icon']"></i>
|
||||
</a>
|
||||
<a
|
||||
href
|
||||
:title="labels.next"
|
||||
:aria-label="labels.next"
|
||||
class="two wide column control"
|
||||
@click.prevent.stop="next"
|
||||
:disabled="!hasNext">
|
||||
<i @click="next" :class="['ui', {'disabled': !hasNext}, 'step', 'forward', 'secondary', 'icon']" ></i>
|
||||
</div>
|
||||
<i :class="['ui', {'disabled': !hasNext}, 'step', 'forward', 'secondary', 'icon']" ></i>
|
||||
</a>
|
||||
<div
|
||||
class="wide column control volume-control"
|
||||
v-on:mouseover="showVolume = true"
|
||||
v-on:mouseleave="showVolume = false"
|
||||
v-bind:class="{ active : showVolume }">
|
||||
<i
|
||||
<a
|
||||
href
|
||||
v-if="volume === 0"
|
||||
:title="labels.unmute"
|
||||
@click="unmute" v-if="volume === 0" class="volume off secondary icon"></i>
|
||||
<i
|
||||
:aria-label="labels.unmute"
|
||||
@click.prevent.stop="unmute">
|
||||
<i class="volume off secondary icon"></i>
|
||||
</a>
|
||||
<a
|
||||
href
|
||||
v-else-if="volume < 0.5"
|
||||
:title="labels.mute"
|
||||
@click="mute" v-else-if="volume < 0.5" class="volume down secondary icon"></i>
|
||||
<i
|
||||
:aria-label="labels.mute"
|
||||
@click.prevent.stop="mute">
|
||||
<i class="volume down secondary icon"></i>
|
||||
</a>
|
||||
<a
|
||||
href
|
||||
v-else
|
||||
:title="labels.mute"
|
||||
@click="mute" v-else class="volume up secondary icon"></i>
|
||||
:aria-label="labels.mute"
|
||||
@click.prevent.stop="mute">
|
||||
<i class="volume up secondary icon"></i>
|
||||
</a>
|
||||
<input
|
||||
type="range"
|
||||
step="0.05"
|
||||
|
@ -102,44 +131,61 @@
|
|||
v-if="showVolume" />
|
||||
</div>
|
||||
<div class="two wide column control looping" v-if="!showVolume">
|
||||
<i
|
||||
:title="labels.loopingDisabled"
|
||||
<a
|
||||
href
|
||||
v-if="looping === 0"
|
||||
@click="$store.commit('player/looping', 1)"
|
||||
:disabled="!currentTrack"
|
||||
:class="['ui', {'disabled': !currentTrack}, 'step', 'repeat', 'secondary', 'icon']"></i>
|
||||
<i
|
||||
:title="labels.loopingDisabled"
|
||||
:aria-label="labels.loopingDisabled"
|
||||
@click.prevent.stop="$store.commit('player/looping', 1)"
|
||||
:disabled="!currentTrack">
|
||||
<i :class="['ui', {'disabled': !currentTrack}, 'step', 'repeat', 'secondary', 'icon']"></i>
|
||||
</a>
|
||||
<a
|
||||
href
|
||||
@click.prevent.stop="$store.commit('player/looping', 2)"
|
||||
:title="labels.loopingSingle"
|
||||
:aria-label="labels.loopingSingle"
|
||||
v-if="looping === 1"
|
||||
@click="$store.commit('player/looping', 2)"
|
||||
:disabled="!currentTrack"
|
||||
class="repeat secondary icon">
|
||||
<span class="ui circular tiny orange label">1</span>
|
||||
</i>
|
||||
<i
|
||||
:disabled="!currentTrack">
|
||||
<i
|
||||
class="repeat secondary icon">
|
||||
<span class="ui circular tiny orange label">1</span>
|
||||
</i>
|
||||
</a>
|
||||
<a
|
||||
href
|
||||
:title="labels.loopingWhole"
|
||||
:aria-label="labels.loopingWhole"
|
||||
v-if="looping === 2"
|
||||
@click="$store.commit('player/looping', 0)"
|
||||
:disabled="!currentTrack"
|
||||
class="repeat orange secondary icon">
|
||||
</i>
|
||||
@click.prevent.stop="$store.commit('player/looping', 0)">
|
||||
<i
|
||||
class="repeat orange secondary icon">
|
||||
</i>
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
<a
|
||||
href
|
||||
:disabled="queue.tracks.length === 0"
|
||||
:title="labels.shuffle"
|
||||
:aria-label="labels.shuffle"
|
||||
v-if="!showVolume"
|
||||
@click.prevent.stop="shuffle()"
|
||||
class="two wide column control">
|
||||
<div v-if="isShuffling" class="ui inline shuffling inverted tiny active loader"></div>
|
||||
<i v-else @click="shuffle()" :class="['ui', 'random', 'secondary', {'disabled': queue.tracks.length === 0}, 'icon']" ></i>
|
||||
</div>
|
||||
<i v-else :class="['ui', 'random', 'secondary', {'disabled': queue.tracks.length === 0}, 'icon']" ></i>
|
||||
</a>
|
||||
<div class="one wide column" v-if="!showVolume"></div>
|
||||
<div
|
||||
<a
|
||||
href
|
||||
:disabled="queue.tracks.length === 0"
|
||||
:title="labels.clear"
|
||||
:aria-label="labels.clear"
|
||||
v-if="!showVolume"
|
||||
@click.prevent.stop="clean()"
|
||||
class="two wide column control">
|
||||
<i @click="clean()" :class="['ui', 'trash', 'secondary', {'disabled': queue.tracks.length === 0}, 'icon']" ></i>
|
||||
</div>
|
||||
<i :class="['ui', 'trash', 'secondary', {'disabled': queue.tracks.length === 0}, 'icon']" ></i>
|
||||
</a>
|
||||
</div>
|
||||
<GlobalEvents
|
||||
@keydown.space.prevent.exact="togglePlay"
|
||||
|
@ -147,7 +193,6 @@
|
|||
@keydown.ctrl.right.prevent.exact="next"
|
||||
@keydown.ctrl.down.prevent.exact="$store.commit('player/incrementVolume', -0.1)"
|
||||
@keydown.ctrl.up.prevent.exact="$store.commit('player/incrementVolume', 0.1)"
|
||||
@keydown.f.prevent.exact="$store.dispatch('favorites/toggle', currentTrack.id)"
|
||||
@keydown.l.prevent.exact="$store.commit('player/toggleLooping')"
|
||||
@keydown.s.prevent.exact="shuffle"
|
||||
/>
|
||||
|
@ -370,6 +415,9 @@ export default {
|
|||
color: white !important;
|
||||
}
|
||||
}
|
||||
.controls a {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.controls .icon.big {
|
||||
cursor: pointer;
|
||||
|
|
|
@ -3,10 +3,8 @@
|
|||
<h3 class="ui header">
|
||||
<slot name="title"></slot>
|
||||
</h3>
|
||||
<i @click="fetchData(previousPage)" :disabled="!previousPage" :class="['ui', {disabled: !previousPage}, 'circular', 'medium', 'angle left', 'icon']">
|
||||
</i>
|
||||
<i @click="fetchData(nextPage)" :disabled="!nextPage" :class="['ui', {disabled: !nextPage}, 'circular', 'medium', 'angle right', 'icon']">
|
||||
</i>
|
||||
<button :disabled="!previousPage" @click="fetchData(previousPage)" :class="['ui', {disabled: !previousPage}, 'circular', 'icon', 'basic', 'button']"><i :class="['ui', 'angle left', 'icon']"></i></button>
|
||||
<button :disabled="!nextPage" @click="fetchData(nextPage)" :class="['ui', {disabled: !nextPage}, 'circular', 'icon', 'basic', 'button']"><i :class="['ui', 'angle right', 'icon']"></i></button>
|
||||
<div class="ui hidden divider"></div>
|
||||
<div class="ui five cards">
|
||||
<div v-if="isLoading" class="ui inverted active dimmer">
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
<td colspan="4" v-else>
|
||||
<translate>N/A</translate>
|
||||
</td>
|
||||
<td>
|
||||
<td colspan="2">
|
||||
<track-favorite-icon class="favorite-icon" :track="track"></track-favorite-icon>
|
||||
<track-playlist-icon
|
||||
v-if="$store.state.auth.authenticated"
|
||||
|
@ -89,7 +89,7 @@ export default {
|
|||
|
||||
tr:not(:hover) {
|
||||
.favorite-icon:not(.favorited), .playlist-icon {
|
||||
display: none;
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<th colspan="4"><translate>Artist</translate></th>
|
||||
<th colspan="4"><translate>Album</translate></th>
|
||||
<th colspan="4"><translate>Duration</translate></th>
|
||||
<th></th>
|
||||
<th colspan="2"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
|
|
@ -3,12 +3,9 @@
|
|||
<h3 class="ui header">
|
||||
<slot name="title"></slot>
|
||||
</h3>
|
||||
<i @click="fetchData(previousPage)" :disabled="!previousPage" :class="['ui', {disabled: !previousPage}, 'circular', 'medium', 'angle up', 'icon']">
|
||||
</i>
|
||||
<i @click="fetchData(nextPage)" :disabled="!nextPage" :class="['ui', {disabled: !nextPage}, 'circular', 'medium', 'angle down', 'icon']">
|
||||
</i>
|
||||
<i @click="fetchData(url)" :class="['ui', 'circular', 'medium', 'refresh', 'icon']">
|
||||
</i>
|
||||
<button :disabled="!previousPage" @click="fetchData(previousPage)" :class="['ui', {disabled: !previousPage}, 'circular', 'icon', 'basic', 'button']"><i :class="['ui', 'angle up', 'icon']"></i></button>
|
||||
<button :disabled="!nextPage" @click="fetchData(nextPage)" :class="['ui', {disabled: !nextPage}, 'circular', 'icon', 'basic', 'button']"><i :class="['ui', 'angle down', 'icon']"></i></button>
|
||||
<button @click="fetchData(url)" :class="['ui', 'circular', 'icon', 'basic', 'button']"><i :class="['ui', 'refresh', 'icon']"></i></button>
|
||||
<div class="ui divided unstackable items">
|
||||
<div class="item" v-for="object in objects" :key="object.id">
|
||||
<div class="ui tiny image">
|
||||
|
|
|
@ -4,7 +4,14 @@
|
|||
<translate v-if="isFavorite">In favorites</translate>
|
||||
<translate v-else>Add to favorites</translate>
|
||||
</button>
|
||||
<i v-else @click="$store.dispatch('favorites/toggle', track.id)" :class="['favorite-icon', 'heart', {'pink': isFavorite}, {'favorited': isFavorite}, 'link', 'icon']" :title="title"></i>
|
||||
<button
|
||||
v-else
|
||||
@click="$store.dispatch('favorites/toggle', track.id)"
|
||||
:class="['ui', 'favorite-icon', {'pink': isFavorite}, {'favorited': isFavorite}, 'basic', 'circular', 'icon', 'really', 'button']"
|
||||
:aria-label="title"
|
||||
:title="title">
|
||||
<i :class="['heart', {'pink': isFavorite}, 'basic', 'icon']"></i>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
|
@ -6,12 +6,14 @@
|
|||
<i class="list icon"></i>
|
||||
<translate>Add to playlist...</translate>
|
||||
</button>
|
||||
<i
|
||||
<button
|
||||
v-else
|
||||
@click="$store.commit('playlists/chooseTrack', track)"
|
||||
:class="['playlist-icon', 'list', 'link', 'icon']"
|
||||
:class="['ui', 'basic', 'circular', 'icon', 'really', 'button']"
|
||||
:aria-label="labels.addToPlaylist"
|
||||
:title="labels.addToPlaylist">
|
||||
</i>
|
||||
<i :class="['list', 'basic', 'icon']"></i>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
|
@ -3,12 +3,10 @@
|
|||
<h3 class="ui header">
|
||||
<slot name="title"></slot>
|
||||
</h3>
|
||||
<i @click="fetchData(previousPage)" :disabled="!previousPage" :class="['ui', {disabled: !previousPage}, 'circular', 'medium', 'angle up', 'icon']">
|
||||
</i>
|
||||
<i @click="fetchData(nextPage)" :disabled="!nextPage" :class="['ui', {disabled: !nextPage}, 'circular', 'medium', 'angle down', 'icon']">
|
||||
</i>
|
||||
<i @click="fetchData(url)" :class="['ui', 'circular', 'medium', 'refresh', 'icon']">
|
||||
</i>
|
||||
<button :disabled="!previousPage" @click="fetchData(previousPage)" :class="['ui', {disabled: !previousPage}, 'circular', 'icon', 'basic', 'button']"><i :class="['ui', 'angle up', 'icon']"></i></button>
|
||||
<button :disabled="!nextPage" @click="fetchData(nextPage)" :class="['ui', {disabled: !nextPage}, 'circular', 'icon', 'basic', 'button']"><i :class="['ui', 'angle down', 'icon']"></i></button>
|
||||
<button @click="fetchData(url)" :class="['ui', 'circular', 'icon', 'basic', 'button']"><i :class="['ui', 'refresh', 'icon']"></i></button>
|
||||
|
||||
<div v-if="isLoading" class="ui inverted active dimmer">
|
||||
<div class="ui loader"></div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue