chore: accessibility of filters

This commit is contained in:
2024-05-03 19:29:10 +02:00
parent ff041b9aaf
commit 7dd1c06f3f
4 changed files with 281 additions and 288 deletions
@@ -9,7 +9,7 @@
ref="button" ref="button"
> >
<img src="/images/icon-filter2.svg" alt="Open filters" /> <img src="/images/icon-filter2.svg" alt="Open filters" />
{{ $t('options.filters') }} [F] [F] {{ $t('options.filters') }}
<span class="active-indicator" v-if="currentOptionsActive"></span> <span class="active-indicator" v-if="currentOptionsActive"></span>
</button> </button>
@@ -3,7 +3,7 @@
<div class="card_controls"> <div class="card_controls">
<button class="btn--filled btn--image" @click="toggleCard"> <button class="btn--filled btn--image" @click="toggleCard">
<img class="button_icon" src="/images/icon-filter2.svg" alt="filter icon" /> <img class="button_icon" src="/images/icon-filter2.svg" alt="filter icon" />
{{ $t('options.filters') }} [F] [F] {{ $t('options.filters') }}
<span class="active-indicator" v-if="!filterStore.areFiltersAtDefault"></span> <span class="active-indicator" v-if="!filterStore.areFiltersAtDefault"></span>
</button> </button>
@@ -28,8 +28,8 @@
</div> </div>
<transition name="card-anim"> <transition name="card-anim">
<div class="card" v-if="isVisible" tabindex="0" ref="cardEl"> <div class="card" v-if="isVisible" tabindex="0" ref="cardRef" @keydown.r="resetFilters">
<div class="card_content"> <div class="card_content" @scroll="onScroll" ref="cardContentRef">
<div class="card_title flex">{{ $t('filters.title') }}</div> <div class="card_title flex">{{ $t('filters.title') }}</div>
<p class="card_info" v-html="$t('filters.desc')"></p> <p class="card_info" v-html="$t('filters.desc')"></p>
@@ -137,7 +137,7 @@
:disabled="filterStore.areFiltersAtDefault" :disabled="filterStore.areFiltersAtDefault"
:data-disabled="filterStore.areFiltersAtDefault" :data-disabled="filterStore.areFiltersAtDefault"
> >
{{ $t('filters.reset') }} [R] {{ $t('filters.reset') }}
</button> </button>
<button class="btn--action" @click="closeCard">{{ $t('filters.close') }}</button> <button class="btn--action" @click="closeCard">{{ $t('filters.close') }}</button>
</div> </div>
@@ -171,7 +171,10 @@ export default defineComponent({
currentRegion: { id: '', value: '' }, currentRegion: { id: '', value: '' },
delayInputTimer: -1, delayInputTimer: -1,
chosenSearchScenery: '' chosenSearchScenery: '',
scrollTop: 0,
lastFocusedEl: null as HTMLElement | null
}), }),
setup() { setup() {
@@ -237,7 +240,10 @@ export default defineComponent({
isVisible(value: boolean) { isVisible(value: boolean) {
this.$nextTick(() => { this.$nextTick(() => {
if (value) (this.$refs['cardEl'] as HTMLDivElement).focus(); if (value) {
(this.$refs['cardRef'] as HTMLDivElement).focus();
(this.$refs['cardContentRef'] as HTMLDivElement).scrollTop = this.scrollTop;
}
}); });
} }
}, },
@@ -248,6 +254,10 @@ export default defineComponent({
this.isVisible = !this.isVisible; this.isVisible = !this.isVisible;
}, },
onScroll(e: Event) {
this.scrollTop = (e.target as HTMLElement).scrollTop;
},
handleInput(e: Event) { handleInput(e: Event) {
const target = e.target as HTMLInputElement; const target = e.target as HTMLInputElement;
+263 -280
View File
@@ -1,301 +1,295 @@
<template> <template>
<section class="station_table"> <section class="station_table">
<transition name="status-anim" mode="out-in"> <div class="table_wrapper">
<div class="table_wrapper" :key="apiStore.dataStatuses.connection"> <table>
<table> <thead>
<thead> <tr>
<tr> <th
<th v-for="headerName in headIds"
v-for="headerName in headIds" :key="headerName"
:key="headerName" @click="changeSorter(headerName)"
@click="changeSorter(headerName)" class="header-text"
class="header-text" :class="headerName"
:class="headerName"
>
<span class="header_wrapper">
<div v-html="$t(`sceneries.headers.${headerName}`)"></div>
<img
class="sort-icon"
v-if="sorterActive.headerName == headerName"
:src="`/images/icon-arrow-${sorterActive.dir == 1 ? 'asc' : 'desc'}.svg`"
alt="sort icon"
/>
</span>
</th>
<th
v-for="headerName in headIconsIds"
:key="headerName"
@click="changeSorter(headerName)"
class="header-image"
:class="headerName"
>
<span class="header_wrapper">
<img
:src="`/images/icon-${headerName}.svg`"
:alt="headerName"
:title="$t(`sceneries.headers.${headerName}`)"
/>
<img
class="sort-icon"
v-if="sorterActive.headerName == headerName"
:src="`/images/icon-arrow-${sorterActive.dir == 1 ? 'asc' : 'desc'}.svg`"
alt="sort icon"
/>
</span>
</th>
</tr>
</thead>
<tbody>
<tr
v-for="station in stations"
:class="{ 'last-selected': lastSelectedStationName == station.name }"
:key="station.name"
@click.left="setScenery(station.name)"
@click.right="openForumSite($event, station.generalInfo?.url)"
@keydown.enter="setScenery(station.name)"
@keydown.space="openForumSite($event, station.generalInfo?.url)"
tabindex="0"
> >
<td class="station-name" :class="station.generalInfo?.availability"> <span class="header_wrapper">
<b v-if="station.generalInfo?.project" style="color: salmon">{{ <div v-html="$t(`sceneries.headers.${headerName}`)"></div>
station.generalInfo.project
}}</b>
{{ station.name }}
</td>
<td class="station-level"> <img
<span v-if="station.generalInfo"> class="sort-icon"
<span v-if="sorterActive.headerName == headerName"
v-if=" :src="`/images/icon-arrow-${sorterActive.dir == 1 ? 'asc' : 'desc'}.svg`"
station.generalInfo.reqLevel > -1 && alt="sort icon"
station.generalInfo.availability != 'nonPublic' &&
station.generalInfo.availability != 'unavailable'
"
:style="calculateExpStyle(station.generalInfo.reqLevel)"
>
{{ station.generalInfo.reqLevel >= 2 ? station.generalInfo.reqLevel : 'L' }}
</span>
<span v-else-if="station.generalInfo.availability == 'abandoned'">
<img
src="/images/icon-abandoned.svg"
alt="non-public"
:title="$t('sceneries.info.abandoned')"
/>
</span>
<span v-else-if="station.generalInfo.availability == 'nonPublic'">
<img
src="/images/icon-lock.svg"
alt="non-public"
:title="$t('sceneries.info.non-public')"
/>
</span>
<span v-else>
<img
src="/images/icon-unavailable.svg"
alt="unavailable"
:title="$t('sceneries.info.unavailable')"
/>
</span>
</span>
<span v-else> ? </span>
</td>
<td class="station-status">
<StationStatusBadge
:isOnline="station.onlineInfo ? true : false"
:dispatcherStatus="station.onlineInfo?.dispatcherStatus"
/> />
</td> </span>
</th>
<td class="station-dispatcher-name"> <th
<span v-if="station.onlineInfo?.dispatcherName"> v-for="headerName in headIconsIds"
<b :key="headerName"
v-if="apiStore.donatorsData.includes(station.onlineInfo.dispatcherName)" @click="changeSorter(headerName)"
@click.stop="openDonationModal" class="header-image"
data-popup-key="DonatorPopUp" :class="headerName"
:data-popup-content="$t('donations.dispatcher-message')" >
> <span class="header_wrapper">
<img src="/images/icon-diamond.svg" alt="" /> <img
{{ station.onlineInfo.dispatcherName }} :src="`/images/icon-${headerName}.svg`"
</b> :alt="headerName"
:title="$t(`sceneries.headers.${headerName}`)"
/>
<div v-else> <img
{{ station.onlineInfo.dispatcherName }} class="sort-icon"
</div> v-if="sorterActive.headerName == headerName"
</span> :src="`/images/icon-arrow-${sorterActive.dir == 1 ? 'asc' : 'desc'}.svg`"
</td> alt="sort icon"
/>
</span>
</th>
</tr>
</thead>
<td class="station-dispatcher-exp"> <tbody>
<tr
v-for="station in stations"
:class="{ 'last-selected': lastSelectedStationName == station.name }"
:key="station.name"
@click.left="setScenery(station.name)"
@click.right="openForumSite($event, station.generalInfo?.url)"
@keydown.enter="setScenery(station.name)"
@keydown.space="openForumSite($event, station.generalInfo?.url)"
tabindex="0"
>
<td class="station-name" :class="station.generalInfo?.availability">
<b v-if="station.generalInfo?.project" style="color: salmon">{{
station.generalInfo.project
}}</b>
{{ station.name }}
</td>
<td class="station-level">
<span v-if="station.generalInfo">
<span <span
v-if="station.onlineInfo && station.onlineInfo?.dispatcherExp != -1" v-if="
:style=" station.generalInfo.reqLevel > -1 &&
calculateExpStyle( station.generalInfo.availability != 'nonPublic' &&
station.onlineInfo.dispatcherExp, station.generalInfo.availability != 'unavailable'
station.onlineInfo.dispatcherIsSupporter
)
" "
:style="calculateExpStyle(station.generalInfo.reqLevel)"
> >
{{ {{ station.generalInfo.reqLevel >= 2 ? station.generalInfo.reqLevel : 'L' }}
station.onlineInfo.dispatcherExp < 2 ? 'L' : station.onlineInfo.dispatcherExp
}}
</span> </span>
</td>
<td class="station-tracks"> <span v-else-if="station.generalInfo.availability == 'abandoned'">
<div v-if="station.generalInfo"> <img
<span src="/images/icon-abandoned.svg"
v-if="station.generalInfo.routes.singleElectrifiedNames.length != 0" alt="non-public"
class="track catenary" :title="$t('sceneries.info.abandoned')"
:title="`${$t('sceneries.info.single-track-routes-catenary')}${ />
station.generalInfo.routes.singleElectrifiedNames.length </span>
}`"
>
{{ station.generalInfo.routes.singleElectrifiedNames.length }}
</span>
<span <span v-else-if="station.generalInfo.availability == 'nonPublic'">
v-if="station.generalInfo.routes.singleOtherNames.length != 0" <img
class="track no-catenary" src="/images/icon-lock.svg"
:title="`${$t('sceneries.info.single-track-routes-other')}${ alt="non-public"
station.generalInfo.routes.singleOtherNames.length :title="$t('sceneries.info.non-public')"
}`" />
> </span>
{{ station.generalInfo.routes.singleOtherNames.length }}
</span> <span v-else>
<img
src="/images/icon-unavailable.svg"
alt="unavailable"
:title="$t('sceneries.info.unavailable')"
/>
</span>
</span>
<span v-else> ? </span>
</td>
<td class="station-status">
<StationStatusBadge
:isOnline="station.onlineInfo ? true : false"
:dispatcherStatus="station.onlineInfo?.dispatcherStatus"
/>
</td>
<td class="station-dispatcher-name">
<span v-if="station.onlineInfo?.dispatcherName">
<b
v-if="apiStore.donatorsData.includes(station.onlineInfo.dispatcherName)"
@click.stop="openDonationModal"
data-popup-key="DonatorPopUp"
:data-popup-content="$t('donations.dispatcher-message')"
>
<img src="/images/icon-diamond.svg" alt="" />
{{ station.onlineInfo.dispatcherName }}
</b>
<div v-else>
{{ station.onlineInfo.dispatcherName }}
</div> </div>
</td> </span>
</td>
<td class="station-tracks"> <td class="station-dispatcher-exp">
<div v-if="station.generalInfo"> <span
<span v-if="station.onlineInfo && station.onlineInfo?.dispatcherExp != -1"
v-if="station.generalInfo.routes.doubleElectrifiedNames.length != 0" :style="
class="track catenary" calculateExpStyle(
:title="`${$t('sceneries.info.double-track-routes-catenary')}${ station.onlineInfo.dispatcherExp,
station.generalInfo.routes.doubleElectrifiedNames.length station.onlineInfo.dispatcherIsSupporter
}`" )
> "
{{ station.generalInfo.routes.doubleElectrifiedNames.length }} >
</span> {{ station.onlineInfo.dispatcherExp < 2 ? 'L' : station.onlineInfo.dispatcherExp }}
</span>
</td>
<span <td class="station-tracks">
v-if="station.generalInfo.routes.doubleOtherNames.length != 0" <div v-if="station.generalInfo">
class="track no-catenary"
:title="`${$t('sceneries.info.double-track-routes-other')}${
station.generalInfo.routes.doubleOtherNames.length
}`"
>
{{ station.generalInfo.routes.doubleOtherNames.length }}
</span>
</div>
</td>
<td class="station-info">
<span <span
v-if="station.generalInfo?.signalType" v-if="station.generalInfo.routes.singleElectrifiedNames.length != 0"
class="scenery-icon icon-info" class="track catenary"
:class="station.generalInfo?.controlType.replace('+', '-')" :title="`${$t('sceneries.info.single-track-routes-catenary')}${
:title=" station.generalInfo.routes.singleElectrifiedNames.length
$t('sceneries.info.control-type') + }`"
$t(`controls.${station.generalInfo?.controlType}`)
"
> >
{{ $t(`controls.abbrevs.${station.generalInfo.controlType}`) }} {{ station.generalInfo.routes.singleElectrifiedNames.length }}
</span> </span>
<img <span
v-if="station.generalInfo?.signalType" v-if="station.generalInfo.routes.singleOtherNames.length != 0"
class="icon-info" class="track no-catenary"
:src="`/images/icon-${station.generalInfo.signalType}.svg`" :title="`${$t('sceneries.info.single-track-routes-other')}${
:alt="station.generalInfo.signalType" station.generalInfo.routes.singleOtherNames.length
:title=" }`"
$t('sceneries.info.signals-type') + >
$t(`signals.${station.generalInfo.signalType}`) {{ station.generalInfo.routes.singleOtherNames.length }}
" </span>
/> </div>
</td>
<img <td class="station-tracks">
v-if="station.generalInfo?.SUP" <div v-if="station.generalInfo">
class="icon-info" <span
src="/images/icon-SUP.svg" v-if="station.generalInfo.routes.doubleElectrifiedNames.length != 0"
alt="SUP (RASP-UZK)" class="track catenary"
:title="$t('sceneries.info.SUP')" :title="`${$t('sceneries.info.double-track-routes-catenary')}${
/> station.generalInfo.routes.doubleElectrifiedNames.length
}`"
>
{{ station.generalInfo.routes.doubleElectrifiedNames.length }}
</span>
<img <span
v-if="station.generalInfo?.ASDEK" v-if="station.generalInfo.routes.doubleOtherNames.length != 0"
class="icon-info" class="track no-catenary"
src="/images/icon-ASDEK.svg" :title="`${$t('sceneries.info.double-track-routes-other')}${
alt="dSAT ASDEK" station.generalInfo.routes.doubleOtherNames.length
:title="$t('sceneries.info.ASDEK')" }`"
/> >
{{ station.generalInfo.routes.doubleOtherNames.length }}
</span>
</div>
</td>
<img <td class="station-info">
v-if="!station.generalInfo" <span
class="icon-info" v-if="station.generalInfo?.signalType"
src="/images/icon-unknown.svg" class="scenery-icon icon-info"
alt="icon-unknown" :class="station.generalInfo?.controlType.replace('+', '-')"
:title="$t('sceneries.info.unknown')" :title="
/> $t('sceneries.info.control-type') +
</td> $t(`controls.${station.generalInfo?.controlType}`)
"
<td class="station-users" :class="{ inactive: !station.onlineInfo }">
<span class="text--primary">{{ station.onlineInfo?.currentUsers ?? '-' }}</span>
/
<span class="text--primary">{{ station.onlineInfo?.maxUsers ?? '-' }}</span>
</td>
<td class="station-likes" :class="{ inactive: !station.onlineInfo }">
<span>{{ station.onlineInfo?.dispatcherRate ?? '-' }}</span>
</td>
<td class="station-spawns" :class="{ inactive: !station.onlineInfo }">
<span>{{ station.onlineInfo?.spawns.length ?? '-' }}</span>
</td>
<td
class="station-schedules all"
style="width: 30px"
:class="{ inactive: !station.onlineInfo }"
> >
{{ station.onlineInfo?.scheduledTrainCount.all ?? '-' }} {{ $t(`controls.abbrevs.${station.generalInfo.controlType}`) }}
</td> </span>
<td <img
class="station-schedules unconfirmed" v-if="station.generalInfo?.signalType"
style="width: 30px" class="icon-info"
:class="{ inactive: !station.onlineInfo }" :src="`/images/icon-${station.generalInfo.signalType}.svg`"
> :alt="station.generalInfo.signalType"
{{ station.onlineInfo?.scheduledTrainCount.unconfirmed ?? '-' }} :title="
</td> $t('sceneries.info.signals-type') +
$t(`signals.${station.generalInfo.signalType}`)
"
/>
<td <img
class="station-schedules confirmed" v-if="station.generalInfo?.SUP"
style="width: 30px" class="icon-info"
:class="{ inactive: !station.onlineInfo }" src="/images/icon-SUP.svg"
> alt="SUP (RASP-UZK)"
{{ station.onlineInfo?.scheduledTrainCount.confirmed ?? '-' }} :title="$t('sceneries.info.SUP')"
</td> />
</tr>
</tbody>
</table>
<Loading <img
v-if="apiStore.dataStatuses.connection == Status.Loading && stations.length == 0" v-if="station.generalInfo?.ASDEK"
/> class="icon-info"
src="/images/icon-ASDEK.svg"
alt="dSAT ASDEK"
:title="$t('sceneries.info.ASDEK')"
/>
<div class="no-stations" v-else-if="stations.length == 0"> <img
{{ $t('sceneries.no-stations') }} v-if="!station.generalInfo"
</div> class="icon-info"
src="/images/icon-unknown.svg"
alt="icon-unknown"
:title="$t('sceneries.info.unknown')"
/>
</td>
<td class="station-users" :class="{ inactive: !station.onlineInfo }">
<span class="text--primary">{{ station.onlineInfo?.currentUsers ?? '-' }}</span>
/
<span class="text--primary">{{ station.onlineInfo?.maxUsers ?? '-' }}</span>
</td>
<td class="station-likes" :class="{ inactive: !station.onlineInfo }">
<span>{{ station.onlineInfo?.dispatcherRate ?? '-' }}</span>
</td>
<td class="station-spawns" :class="{ inactive: !station.onlineInfo }">
<span>{{ station.onlineInfo?.spawns.length ?? '-' }}</span>
</td>
<td
class="station-schedules all"
style="width: 30px"
:class="{ inactive: !station.onlineInfo }"
>
{{ station.onlineInfo?.scheduledTrainCount.all ?? '-' }}
</td>
<td
class="station-schedules unconfirmed"
style="width: 30px"
:class="{ inactive: !station.onlineInfo }"
>
{{ station.onlineInfo?.scheduledTrainCount.unconfirmed ?? '-' }}
</td>
<td
class="station-schedules confirmed"
style="width: 30px"
:class="{ inactive: !station.onlineInfo }"
>
{{ station.onlineInfo?.scheduledTrainCount.confirmed ?? '-' }}
</td>
</tr>
</tbody>
</table>
<Loading v-if="apiStore.dataStatuses.connection == Status.Loading && stations.length == 0" />
<div class="no-stations" v-else-if="stations.length == 0">
{{ $t('sceneries.no-stations') }}
</div> </div>
</transition> </div>
</section> </section>
</template> </template>
@@ -395,20 +389,9 @@ export default defineComponent({
$rowCol: #424242; $rowCol: #424242;
.change-anim {
&-enter-active,
&-leave-active {
transition: opacity 100ms ease-in;
}
&-enter,
&-leave-to {
opacity: 0;
}
}
.table_wrapper { .table_wrapper {
overflow: auto; overflow: auto;
overflow-y: scroll;
font-weight: 500; font-weight: 500;
height: 90vh; height: 90vh;
min-height: 550px; min-height: 550px;
+1 -1
View File
@@ -4,7 +4,7 @@
<button class="filter-button btn--filled btn--image" @click="toggleShowOptions" ref="button"> <button class="filter-button btn--filled btn--image" @click="toggleShowOptions" ref="button">
<img src="/images/icon-filter2.svg" alt="Open filters icon" /> <img src="/images/icon-filter2.svg" alt="Open filters icon" />
{{ $t('options.filters') }} [F] [F] {{ $t('options.filters') }}
<span class="active-indicator" v-if="currentOptionsActive"></span> <span class="active-indicator" v-if="currentOptionsActive"></span>
</button> </button>