Improve filter popover accessibility

Signed-off-by: Julius Härtl <jus@bitgrid.net>
This commit is contained in:
Julius Härtl
2022-05-13 12:40:05 +02:00
parent f93772ebc9
commit 41ed0cee1d

View File

@@ -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;
} }