Client - fix keyboard navigation when modal is displayed
This commit is contained in:
parent
651d2204b2
commit
94274a5ea2
@ -16,14 +16,15 @@
|
||||
<div class="modal-buttons">
|
||||
<button
|
||||
class="confirm"
|
||||
id="confirm-button"
|
||||
v-if="!errorMessages"
|
||||
@click="emit('confirmAction')"
|
||||
>
|
||||
{{ $t('buttons.YES') }}
|
||||
</button>
|
||||
<button
|
||||
:tabindex="0"
|
||||
:id="`${name}-cancel-button`"
|
||||
tabindex="0"
|
||||
id="cancel-button"
|
||||
class="cancel"
|
||||
@click="emit('cancelAction')"
|
||||
>
|
||||
@ -37,7 +38,14 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ComputedRef, computed, toRefs, withDefaults, onUnmounted } from 'vue'
|
||||
import {
|
||||
ComputedRef,
|
||||
computed,
|
||||
onUnmounted,
|
||||
onMounted,
|
||||
toRefs,
|
||||
withDefaults,
|
||||
} from 'vue'
|
||||
|
||||
import { ROOT_STORE } from '@/store/constants'
|
||||
import { useStore } from '@/use/useStore'
|
||||
@ -46,11 +54,9 @@
|
||||
title: string
|
||||
message: string
|
||||
strongMessage?: string | null
|
||||
name?: string | null
|
||||
}
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
strongMessage: () => null,
|
||||
name: 'modal',
|
||||
})
|
||||
|
||||
const emit = defineEmits(['cancelAction', 'confirmAction'])
|
||||
@ -61,7 +67,35 @@
|
||||
const errorMessages: ComputedRef<string | string[] | null> = computed(
|
||||
() => store.getters[ROOT_STORE.GETTERS.ERROR_MESSAGES]
|
||||
)
|
||||
onUnmounted(() => store.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES))
|
||||
let confirmButton: HTMLElement | null = null
|
||||
let cancelButton: HTMLElement | null = null
|
||||
let previousFocusedElement: Element | null = null
|
||||
|
||||
function focusTrap(e: KeyboardEvent) {
|
||||
if (e.key === 'Tab' || e.keyCode === 9) {
|
||||
e.preventDefault()
|
||||
if (document.activeElement?.id === 'cancel-button') {
|
||||
confirmButton?.focus()
|
||||
} else {
|
||||
cancelButton?.focus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
previousFocusedElement = document.activeElement
|
||||
cancelButton = document.getElementById('cancel-button')
|
||||
confirmButton = document.getElementById('confirm-button')
|
||||
if (cancelButton) {
|
||||
cancelButton.focus()
|
||||
}
|
||||
document.addEventListener('keydown', focusTrap)
|
||||
})
|
||||
onUnmounted(() => {
|
||||
store.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES)
|
||||
document.removeEventListener('keydown', focusTrap)
|
||||
previousFocusedElement?.focus()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<header id="nav">
|
||||
<Modal
|
||||
v-show="displayModal"
|
||||
v-if="displayModal"
|
||||
:title="$t('common.CONFIRMATION')"
|
||||
:message="$t('user.LOGOUT_CONFIRMATION')"
|
||||
@confirmAction="logout"
|
||||
@ -138,12 +138,6 @@
|
||||
}
|
||||
function updateDisplayModal(display: boolean) {
|
||||
displayModal.value = display
|
||||
if (display) {
|
||||
const button = document.getElementById('modal-cancel-button')
|
||||
if (button) {
|
||||
button.focus()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
<div id="user-infos" class="description-list">
|
||||
<Modal
|
||||
v-if="displayModal"
|
||||
name="user"
|
||||
:title="$t('common.CONFIRMATION')"
|
||||
:message="
|
||||
displayModal === 'delete'
|
||||
@ -192,10 +191,6 @@
|
||||
function updateDisplayModal(value: string) {
|
||||
displayModal.value = value
|
||||
if (value !== '') {
|
||||
const button = document.getElementById('user-cancel-button')
|
||||
if (button) {
|
||||
button.focus()
|
||||
}
|
||||
store.commit(USERS_STORE.MUTATIONS.UPDATE_IS_SUCCESS, false)
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
<div id="user-infos-edition">
|
||||
<Modal
|
||||
v-if="displayModal"
|
||||
name="account"
|
||||
:title="$t('common.CONFIRMATION')"
|
||||
:message="$t('user.CONFIRM_ACCOUNT_DELETION')"
|
||||
@confirmAction="deleteAccount(user.username)"
|
||||
@ -215,12 +214,6 @@
|
||||
}
|
||||
function updateDisplayModal(value: boolean) {
|
||||
displayModal.value = value
|
||||
if (displayModal.value) {
|
||||
const button = document.getElementById('account-cancel-button')
|
||||
if (button) {
|
||||
button.focus()
|
||||
}
|
||||
}
|
||||
}
|
||||
function deleteAccount(username: string) {
|
||||
store.dispatch(AUTH_USER_STORE.ACTIONS.DELETE_ACCOUNT, { username })
|
||||
|
@ -2,7 +2,6 @@
|
||||
<div id="oauth2-app" class="description-list">
|
||||
<Modal
|
||||
v-if="displayModal"
|
||||
name="app"
|
||||
:title="$t('common.CONFIRMATION')"
|
||||
:message="$t(messageToDisplay)"
|
||||
@confirmAction="confirmAction(client.id)"
|
||||
@ -180,11 +179,6 @@
|
||||
displayModal.value = value
|
||||
if (!value) {
|
||||
messageToDisplay.value = null
|
||||
} else {
|
||||
const button = document.getElementById('app-cancel-button')
|
||||
if (button) {
|
||||
button.focus()
|
||||
}
|
||||
}
|
||||
}
|
||||
function confirmAction(clientId: number) {
|
||||
|
@ -45,13 +45,13 @@
|
||||
<button
|
||||
id="delete-workout-button"
|
||||
class="transparent icon-button"
|
||||
@click="displayDeleteModal"
|
||||
@click.prevent="displayDeleteModal"
|
||||
:aria-label="$t(`workouts.DELETE_WORKOUT`)"
|
||||
>
|
||||
<i class="fa fa-trash" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
<div class="workout-title" v-else>
|
||||
<div class="workout-title" v-else-if="workoutObject.segmentId">
|
||||
{{ workoutObject.title }}
|
||||
<span class="workout-segment">
|
||||
—
|
||||
@ -69,7 +69,7 @@
|
||||
v-if="workoutObject.type === 'SEGMENT'"
|
||||
:to="{
|
||||
name: 'Workout',
|
||||
params: { workoutId: workoutObject.workoutId }
|
||||
params: { workoutId: workoutObject.workoutId },
|
||||
}"
|
||||
>
|
||||
> {{ $t('workouts.BACK_TO_WORKOUT') }}
|
||||
@ -129,8 +129,7 @@
|
||||
gpxLink.click()
|
||||
})
|
||||
}
|
||||
function displayDeleteModal(event: Event & { target: HTMLInputElement }) {
|
||||
event.target.blur()
|
||||
function displayDeleteModal() {
|
||||
emit('displayModal', true)
|
||||
}
|
||||
</script>
|
||||
|
@ -2,7 +2,6 @@
|
||||
<div class="workout-detail">
|
||||
<Modal
|
||||
v-if="displayModal"
|
||||
name="workout"
|
||||
:title="$t('common.CONFIRMATION')"
|
||||
:message="$t('workouts.WORKOUT_DELETION_CONFIRMATION')"
|
||||
@confirmAction="deleteWorkout(workoutObject.workoutId)"
|
||||
@ -37,7 +36,6 @@
|
||||
ComputedRef,
|
||||
Ref,
|
||||
computed,
|
||||
nextTick,
|
||||
ref,
|
||||
toRefs,
|
||||
watch,
|
||||
@ -164,21 +162,9 @@
|
||||
}
|
||||
function updateDisplayModal(value: boolean) {
|
||||
displayModal.value = value
|
||||
if (displayModal.value) {
|
||||
nextTick(() => {
|
||||
const button = document.getElementById('workout-cancel-button')
|
||||
if (button) {
|
||||
button.focus()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
function cancelDelete() {
|
||||
updateDisplayModal(false)
|
||||
const button = document.getElementById('delete-workout-button')
|
||||
if (button) {
|
||||
button.focus()
|
||||
}
|
||||
}
|
||||
function deleteWorkout(workoutId: string) {
|
||||
updateDisplayModal(false)
|
||||
|
Loading…
Reference in New Issue
Block a user