fix/a11y: fix focus server input, double focus on messsages view and show only active channel info button

This commit is contained in:
2025-08-22 06:47:08 +02:00
parent 6585ec2abb
commit b07916309e
4 changed files with 31 additions and 47 deletions

View File

@@ -5,7 +5,7 @@
{ 'message--unsent': isUnsent } { 'message--unsent': isUnsent }
]" ]"
:data-message-id="message.id" :data-message-id="message.id"
:tabindex="tabindex || 0" :tabindex="tabindex || -1"
:aria-label="messageAriaLabel" :aria-label="messageAriaLabel"
role="listitem" role="listitem"
@keydown="handleKeydown" @keydown="handleKeydown"

View File

@@ -1,33 +1,16 @@
<template> <template>
<div <div class="messages-container" ref="containerRef" @keydown="handleKeydown" tabindex="0" role="list"
class="messages-container" :aria-label="messagesAriaLabel">
ref="containerRef"
@keydown="handleKeydown"
tabindex="0"
role="list"
:aria-label="messagesAriaLabel"
>
<div class="messages" role="presentation"> <div class="messages" role="presentation">
<!-- Regular Messages --> <!-- Regular Messages -->
<MessageItem <MessageItem v-for="(message, index) in messages" :key="message.id" :message="message"
v-for="(message, index) in messages" :tabindex="index === focusedMessageIndex ? 0 : -1" :data-message-index="index"
:key="message.id" @focus="focusedMessageIndex = index" />
:message="message"
:tabindex="index === focusedMessageIndex ? 0 : -1"
:data-message-index="index"
@focus="focusedMessageIndex = index"
/>
<!-- Unsent Messages --> <!-- Unsent Messages -->
<MessageItem <MessageItem v-for="(unsentMsg, index) in unsentMessages" :key="unsentMsg.id" :message="unsentMsg"
v-for="(unsentMsg, index) in unsentMessages" :is-unsent="true" :tabindex="(messages.length + index) === focusedMessageIndex ? 0 : -1"
:key="unsentMsg.id" :data-message-index="messages.length + index" @focus="focusedMessageIndex = messages.length + index" />
:message="unsentMsg"
:is-unsent="true"
:tabindex="(messages.length + index) === focusedMessageIndex ? 0 : -1"
:data-message-index="messages.length + index"
@focus="focusedMessageIndex = messages.length + index"
/>
</div> </div>
</div> </div>
</template> </template>
@@ -65,7 +48,7 @@ const messagesAriaLabel = computed(() => {
} else if (total === 1) { } else if (total === 1) {
return 'Messages list, 1 message' return 'Messages list, 1 message'
} else { } else {
return `Messages list, ${total} messages, currently focused on message ${current} of ${total}` return `Messages list, ${total} messages`
} }
}) })

View File

@@ -23,7 +23,7 @@
</span> </span>
</button> </button>
<button <button v-if="isActive"
class="channel-info-button" class="channel-info-button"
@click.stop="$emit('info', channel)" @click.stop="$emit('info', channel)"
:aria-label="`Channel info for ${channel.name}`" :aria-label="`Channel info for ${channel.name}`"

View File

@@ -9,6 +9,7 @@
<form @submit.prevent="handleAuth" class="auth-form"> <form @submit.prevent="handleAuth" class="auth-form">
<BaseInput <BaseInput
v-model="serverUrl" v-model="serverUrl"
ref="serverInput"
type="url" type="url"
label="Server URL (optional)" label="Server URL (optional)"
:placeholder="defaultServerUrl" :placeholder="defaultServerUrl"
@@ -59,7 +60,7 @@ const serverUrl = ref('')
const error = ref('') const error = ref('')
const isLoading = ref(false) const isLoading = ref(false)
const tokenInput = ref() const tokenInput = ref()
const serverInput = ref()
// Get default server URL for placeholder // Get default server URL for placeholder
const defaultServerUrl = authStore.getDefaultServerUrl() const defaultServerUrl = authStore.getDefaultServerUrl()
@@ -80,7 +81,7 @@ const handleAuth = async () => {
router.push('/') router.push('/')
} else { } else {
error.value = 'Invalid authentication token or server URL' error.value = 'Invalid authentication token or server URL'
tokenInput.value?.focus() serverInput.value?.focus()
} }
} catch (err) { } catch (err) {
error.value = 'Authentication failed. Please check your token and server URL.' error.value = 'Authentication failed. Please check your token and server URL.'
@@ -91,7 +92,7 @@ const handleAuth = async () => {
} }
onMounted(() => { onMounted(() => {
tokenInput.value?.focus() serverInput.value?.focus()
playSound('intro') playSound('intro')
}) })
</script> </script>