Improve filter popover accessibility
Signed-off-by: Julius Härtl <jus@bitgrid.net>
This commit is contained in:
@@ -70,107 +70,113 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="board" class="board-action-buttons">
|
<div v-if="board" class="board-action-buttons">
|
||||||
<Popover @show="filterVisible=true" @hide="filterVisible=false">
|
<div class="board-action-buttons__filter">
|
||||||
<Actions slot="trigger" :title="t('deck', 'Apply filter')">
|
<Popover container=".board-action-buttons__filter"
|
||||||
<ActionButton v-if="isFilterActive" icon="icon-filter_set" />
|
:placement="'bottom-end'"
|
||||||
<ActionButton v-else icon="icon-filter" />
|
:aria-label="t('deck', 'Active filters')"
|
||||||
</Actions>
|
@show="filterVisible=true"
|
||||||
|
@hide="filterVisible=false">
|
||||||
|
<Actions slot="trigger" :title="t('deck', 'Apply filter')">
|
||||||
|
<ActionButton v-if="isFilterActive" icon="icon-filter_set" />
|
||||||
|
<ActionButton v-else icon="icon-filter" />
|
||||||
|
</Actions>
|
||||||
|
|
||||||
<div v-if="filterVisible" class="filter">
|
<div v-if="filterVisible" class="filter">
|
||||||
<h3>{{ t('deck', 'Filter by tag') }}</h3>
|
<h3>{{ t('deck', 'Filter by tag') }}</h3>
|
||||||
<div v-for="label in labelsSorted" :key="label.id" class="filter--item">
|
<div v-for="label in labelsSorted" :key="label.id" class="filter--item">
|
||||||
<input :id="label.id"
|
<input :id="label.id"
|
||||||
v-model="filter.tags"
|
v-model="filter.tags"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
class="checkbox"
|
class="checkbox"
|
||||||
:value="label.id"
|
:value="label.id"
|
||||||
@change="setFilter">
|
@change="setFilter">
|
||||||
<label :for="label.id"><span class="label" :style="labelStyle(label)">{{ label.title }}</span></label>
|
<label :for="label.id"><span class="label" :style="labelStyle(label)">{{ label.title }}</span></label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3>{{ t('deck', 'Filter by assigned user') }}</h3>
|
||||||
|
<div class="filter--item">
|
||||||
|
<input id="unassigned"
|
||||||
|
v-model="filter.unassigned"
|
||||||
|
type="checkbox"
|
||||||
|
class="checkbox"
|
||||||
|
value="unassigned"
|
||||||
|
@change="setFilter"
|
||||||
|
@click="beforeSetFilter">
|
||||||
|
<label for="unassigned">{{ t('deck', 'Unassigned') }}</label>
|
||||||
|
</div>
|
||||||
|
<div v-for="user in board.users" :key="user.uid" class="filter--item">
|
||||||
|
<input :id="user.uid"
|
||||||
|
v-model="filter.users"
|
||||||
|
type="checkbox"
|
||||||
|
class="checkbox"
|
||||||
|
:value="user.uid"
|
||||||
|
@change="setFilter">
|
||||||
|
<label :for="user.uid"><Avatar :user="user.uid" :size="24" :disable-menu="true" /> {{ user.displayname }}</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3>{{ t('deck', 'Filter by due date') }}</h3>
|
||||||
|
|
||||||
|
<div class="filter--item">
|
||||||
|
<input id="overdue"
|
||||||
|
v-model="filter.due"
|
||||||
|
type="radio"
|
||||||
|
class="radio"
|
||||||
|
value="overdue"
|
||||||
|
@change="setFilter"
|
||||||
|
@click="beforeSetFilter">
|
||||||
|
<label for="overdue">{{ t('deck', 'Overdue') }}</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="filter--item">
|
||||||
|
<input id="dueToday"
|
||||||
|
v-model="filter.due"
|
||||||
|
type="radio"
|
||||||
|
class="radio"
|
||||||
|
value="dueToday"
|
||||||
|
@change="setFilter"
|
||||||
|
@click="beforeSetFilter">
|
||||||
|
<label for="dueToday">{{ t('deck', 'Next 24 hours') }}</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="filter--item">
|
||||||
|
<input id="dueWeek"
|
||||||
|
v-model="filter.due"
|
||||||
|
type="radio"
|
||||||
|
class="radio"
|
||||||
|
value="dueWeek"
|
||||||
|
@change="setFilter"
|
||||||
|
@click="beforeSetFilter">
|
||||||
|
<label for="dueWeek">{{ t('deck', 'Next 7 days') }}</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="filter--item">
|
||||||
|
<input id="dueMonth"
|
||||||
|
v-model="filter.due"
|
||||||
|
type="radio"
|
||||||
|
class="radio"
|
||||||
|
value="dueMonth"
|
||||||
|
@change="setFilter"
|
||||||
|
@click="beforeSetFilter">
|
||||||
|
<label for="dueMonth">{{ t('deck', 'Next 30 days') }}</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="filter--item">
|
||||||
|
<input id="noDue"
|
||||||
|
v-model="filter.due"
|
||||||
|
type="radio"
|
||||||
|
class="radio"
|
||||||
|
value="noDue"
|
||||||
|
@change="setFilter"
|
||||||
|
@click="beforeSetFilter">
|
||||||
|
<label for="noDue">{{ t('deck', 'No due date') }}</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Button :disabled="!isFilterActive" :wide="true" @click="clearFilter">
|
||||||
|
{{ t('deck', 'Clear filter') }}
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
</Popover>
|
||||||
<h3>{{ t('deck', 'Filter by assigned user') }}</h3>
|
</div>
|
||||||
<div class="filter--item">
|
|
||||||
<input id="unassigned"
|
|
||||||
v-model="filter.unassigned"
|
|
||||||
type="checkbox"
|
|
||||||
class="checkbox"
|
|
||||||
value="unassigned"
|
|
||||||
@change="setFilter"
|
|
||||||
@click="beforeSetFilter">
|
|
||||||
<label for="unassigned">{{ t('deck', 'Unassigned') }}</label>
|
|
||||||
</div>
|
|
||||||
<div v-for="user in board.users" :key="user.uid" class="filter--item">
|
|
||||||
<input :id="user.uid"
|
|
||||||
v-model="filter.users"
|
|
||||||
type="checkbox"
|
|
||||||
class="checkbox"
|
|
||||||
:value="user.uid"
|
|
||||||
@change="setFilter">
|
|
||||||
<label :for="user.uid"><Avatar :user="user.uid" :size="24" :disable-menu="true" /> {{ user.displayname }}</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h3>{{ t('deck', 'Filter by due date') }}</h3>
|
|
||||||
|
|
||||||
<div class="filter--item">
|
|
||||||
<input id="overdue"
|
|
||||||
v-model="filter.due"
|
|
||||||
type="radio"
|
|
||||||
class="radio"
|
|
||||||
value="overdue"
|
|
||||||
@change="setFilter"
|
|
||||||
@click="beforeSetFilter">
|
|
||||||
<label for="overdue">{{ t('deck', 'Overdue') }}</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="filter--item">
|
|
||||||
<input id="dueToday"
|
|
||||||
v-model="filter.due"
|
|
||||||
type="radio"
|
|
||||||
class="radio"
|
|
||||||
value="dueToday"
|
|
||||||
@change="setFilter"
|
|
||||||
@click="beforeSetFilter">
|
|
||||||
<label for="dueToday">{{ t('deck', 'Next 24 hours') }}</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="filter--item">
|
|
||||||
<input id="dueWeek"
|
|
||||||
v-model="filter.due"
|
|
||||||
type="radio"
|
|
||||||
class="radio"
|
|
||||||
value="dueWeek"
|
|
||||||
@change="setFilter"
|
|
||||||
@click="beforeSetFilter">
|
|
||||||
<label for="dueWeek">{{ t('deck', 'Next 7 days') }}</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="filter--item">
|
|
||||||
<input id="dueMonth"
|
|
||||||
v-model="filter.due"
|
|
||||||
type="radio"
|
|
||||||
class="radio"
|
|
||||||
value="dueMonth"
|
|
||||||
@change="setFilter"
|
|
||||||
@click="beforeSetFilter">
|
|
||||||
<label for="dueMonth">{{ t('deck', 'Next 30 days') }}</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="filter--item">
|
|
||||||
<input id="noDue"
|
|
||||||
v-model="filter.due"
|
|
||||||
type="radio"
|
|
||||||
class="radio"
|
|
||||||
value="noDue"
|
|
||||||
@change="setFilter"
|
|
||||||
@click="beforeSetFilter">
|
|
||||||
<label for="noDue">{{ t('deck', 'No due date') }}</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Button :disabled="!isFilterActive" @click="clearFilter">
|
|
||||||
{{ t('deck', 'Clear filter') }}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</Popover>
|
|
||||||
|
|
||||||
<Actions>
|
<Actions>
|
||||||
<ActionButton icon="icon-archive"
|
<ActionButton icon="icon-archive"
|
||||||
@@ -199,14 +205,14 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapState, mapGetters } from 'vuex'
|
import { mapState, mapGetters } from 'vuex'
|
||||||
import { Actions, ActionButton, Popover, Avatar } from '@nextcloud/vue'
|
import { Actions, ActionButton, Avatar, Button, Popover } from '@nextcloud/vue'
|
||||||
import labelStyle from '../mixins/labelStyle'
|
import labelStyle from '../mixins/labelStyle'
|
||||||
import CardCreateDialog from '../CardCreateDialog'
|
import CardCreateDialog from '../CardCreateDialog'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Controls',
|
name: 'Controls',
|
||||||
components: {
|
components: {
|
||||||
Actions, ActionButton, Popover, Avatar, CardCreateDialog,
|
Actions, ActionButton, Avatar, Button, Popover, CardCreateDialog,
|
||||||
},
|
},
|
||||||
mixins: [labelStyle],
|
mixins: [labelStyle],
|
||||||
props: {
|
props: {
|
||||||
@@ -399,12 +405,6 @@ export default {
|
|||||||
|
|
||||||
.board-action-buttons {
|
.board-action-buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
button {
|
|
||||||
border: 0;
|
|
||||||
width: 44px;
|
|
||||||
margin: 0 0 0 -1px;
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.deck-search {
|
.deck-search {
|
||||||
@@ -432,8 +432,9 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.filter {
|
.filter {
|
||||||
width: 250px;
|
width: 240px;
|
||||||
max-height: 80vh;
|
max-height: calc(100vh - 150px);
|
||||||
|
position: relative;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
}
|
}
|
||||||
@@ -444,6 +445,10 @@ export default {
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
.popover:focus {
|
||||||
|
outline: 2px solid var(--color-main-text);
|
||||||
|
}
|
||||||
|
|
||||||
.tooltip-inner.popover-inner {
|
.tooltip-inner.popover-inner {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user