Maintenance: Desktop view - Beta UI: column headers SERP not accessible to screen readers
This commit is contained in:
@@ -412,11 +412,11 @@ const endOfListMessage = computed(() => {
|
||||
|
||||
return props.totalItemsCount > props.maxItems
|
||||
? i18n.t(
|
||||
'You reached the table limit of %s tickets (%s remaining).',
|
||||
'You reached the table limit of %s items (%s remaining).',
|
||||
props.maxItems,
|
||||
props.totalItemsCount - loadedItems.value.length,
|
||||
)
|
||||
: i18n.t("You don't have more tickets to load.")
|
||||
: i18n.t("You don't have more items to load.")
|
||||
})
|
||||
|
||||
const getLinkColorClasses = (item: TableAdvancedItem) => {
|
||||
@@ -622,7 +622,7 @@ watch(
|
||||
<slot :name="`item-suffix-${tableAttribute.name}`" :item="item" />
|
||||
</div>
|
||||
</td>
|
||||
<td v-if="actions" class="h-10 p-2.5 text-center">
|
||||
<td v-if="actions" headers="actions-header" class="h-10 p-2.5 text-center">
|
||||
<slot name="actions" v-bind="{ actions, item }">
|
||||
<CommonActionMenu
|
||||
class="flex! items-center justify-center"
|
||||
|
||||
@@ -4,10 +4,12 @@ import { useActiveElement, useEventListener } from '@vueuse/core'
|
||||
import { computed, ref, useTemplateRef } from 'vue'
|
||||
|
||||
import { EnumTextDirection } from '#shared/graphql/types.ts'
|
||||
import { i18n } from '#shared/i18n.ts'
|
||||
import { useLocaleStore } from '#shared/stores/locale.ts'
|
||||
import getUuid from '#shared/utils/getUuid.ts'
|
||||
|
||||
import { useResizeLine } from '#desktop/components/ResizeLine/useResizeLine.ts'
|
||||
import { useAnnouncer } from '#desktop/composables/accessibility/useAnnouncer.ts'
|
||||
|
||||
import { MINIMUM_COLUMN_WIDTH } from './types.ts'
|
||||
|
||||
@@ -51,6 +53,8 @@ const setHeaderWidths = (diff: number) => {
|
||||
|
||||
const activeElement = useActiveElement()
|
||||
|
||||
const { announce, messageNodeId } = useAnnouncer()
|
||||
|
||||
const handleKeyStroke = (e: KeyboardEvent, diff: number) => {
|
||||
if (activeElement.value !== resizeLine.value) return
|
||||
|
||||
@@ -59,6 +63,11 @@ const handleKeyStroke = (e: KeyboardEvent, diff: number) => {
|
||||
setCurrentHeaderWidths()
|
||||
setHeaderWidths(diff)
|
||||
emit('resize')
|
||||
|
||||
// Announce the resulting width via the live region, so screen reader users
|
||||
// get feedback while adjusting the column with the arrow keys.
|
||||
if (currentHeader.value)
|
||||
announce(i18n.t('Column width: %s pixels', currentHeader.value.clientWidth))
|
||||
}
|
||||
|
||||
const resizeStartX = ref(0)
|
||||
@@ -123,24 +132,19 @@ const id = getUuid()
|
||||
<button
|
||||
ref="resize-line"
|
||||
v-tooltip="$t('Resize column')"
|
||||
:aria-describedby="id"
|
||||
:aria-describedby="`${id} ${messageNodeId}`"
|
||||
tabindex="0"
|
||||
class="absolute end-0 top-1/2 h-5 w-1 -translate-y-2.5 cursor-col-resize! rounded-xs bg-neutral-100 hover:bg-blue-600 focus:outline-none focus-visible:bg-blue-800! dark:bg-gray-200 dark:hover:bg-blue-900"
|
||||
class="absolute inset-e-0 top-1/2 h-5 w-1 -translate-y-2.5 cursor-col-resize! rounded-xs bg-neutral-100 hover:bg-blue-600 focus:outline-none focus-visible:bg-blue-800! dark:bg-gray-200 dark:hover:bg-blue-900"
|
||||
:class="{
|
||||
'!bg-blue-800': resizing,
|
||||
'bg-blue-800': resizing,
|
||||
}"
|
||||
@mousedown="handleMousedown"
|
||||
@blur="resizing = false"
|
||||
@touchstart="handleTouchstart"
|
||||
@dblclick="handleDoubleClick"
|
||||
>
|
||||
<span
|
||||
:id="id"
|
||||
role="separator"
|
||||
class="invisible absolute -z-20"
|
||||
aria-orientation="horizontal"
|
||||
:aria-valuenow="currentHeader?.clientWidth"
|
||||
:aria-valuemin="MINIMUM_COLUMN_WIDTH"
|
||||
/>
|
||||
<span :id="id" class="sr-only">
|
||||
{{ $t('Use the left and right arrow keys to resize the column.') }}
|
||||
</span>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
@@ -293,7 +293,13 @@ useOnEmitter('primary-sidebar-transition', () => initializeHeaderWidths())
|
||||
<template>
|
||||
<thead ref="thead">
|
||||
<tr>
|
||||
<th v-if="hasBulkAction" id="select-header" :aria-label="$t('Select')" class="size-10">
|
||||
<th
|
||||
v-if="hasBulkAction"
|
||||
id="select-header"
|
||||
scope="col"
|
||||
:aria-label="$t('Select')"
|
||||
class="size-10"
|
||||
>
|
||||
<BulkCheckbox
|
||||
:items="items"
|
||||
:item-ids="itemIds"
|
||||
@@ -306,6 +312,7 @@ useOnEmitter('primary-sidebar-transition', () => initializeHeaderWidths())
|
||||
v-for="(tableAttribute, index) in tableAttributes"
|
||||
:id="`${tableAttribute.name}-header`"
|
||||
:key="tableAttribute.name"
|
||||
scope="col"
|
||||
class="relative h-10 p-2.5 text-xs"
|
||||
:class="[tableAttribute.headerPreferences?.headerClass]"
|
||||
:aria-label="$t(tableAttribute.label, ...(tableAttribute.labelPlaceholder || []))"
|
||||
@@ -377,7 +384,7 @@ useOnEmitter('primary-sidebar-transition', () => initializeHeaderWidths())
|
||||
@reset="resetHeaderWidths"
|
||||
/>
|
||||
</th>
|
||||
<th v-if="actions" class="h-10 w-0 p-2.5 text-center">
|
||||
<th v-if="actions" id="actions-header" scope="col" class="h-10 w-0 p-2.5 text-center">
|
||||
<CommonLabel class="font-normal text-stone-200! dark:text-neutral-500!" size="small"
|
||||
>{{ $t('Actions') }}
|
||||
</CommonLabel>
|
||||
|
||||
@@ -915,7 +915,7 @@ describe('CommonAdvancedTable', () => {
|
||||
})
|
||||
|
||||
expect(
|
||||
wrapper.getByText('You reached the table limit of 20 tickets (10 remaining).'),
|
||||
wrapper.getByText('You reached the table limit of 20 items (10 remaining).'),
|
||||
).toBeInTheDocument()
|
||||
|
||||
scrollContainer.remove()
|
||||
@@ -943,7 +943,7 @@ describe('CommonAdvancedTable', () => {
|
||||
orderBy: 'label',
|
||||
})
|
||||
|
||||
expect(wrapper.getByText("You don't have more tickets to load.")).toBeInTheDocument()
|
||||
expect(wrapper.getByText("You don't have more items to load.")).toBeInTheDocument()
|
||||
|
||||
scrollContainer.remove()
|
||||
})
|
||||
|
||||
@@ -662,7 +662,7 @@ setOnSuccessCallback(() => {
|
||||
:is="searchPlugin.detailSearchComponent"
|
||||
:key="selectedEntity"
|
||||
:table-id="`search-${selectedEntity}-table`"
|
||||
:caption="`Search result for: ${searchPlugin.label}`"
|
||||
:caption="$t('Search result for: %s', searchPlugin.label)"
|
||||
:items="searchResultItems"
|
||||
:headers="detailSearchHeaders"
|
||||
:total-count="searchResultTotalCount"
|
||||
|
||||
@@ -348,11 +348,11 @@ msgstr ""
|
||||
msgid "%s required!"
|
||||
msgstr ""
|
||||
|
||||
#: app/frontend/apps/desktop/components/CommonTable/TableHeader.vue:392
|
||||
#: app/frontend/apps/desktop/components/CommonTable/TableHeader.vue:399
|
||||
msgid "%s result(s) selected"
|
||||
msgstr ""
|
||||
|
||||
#: app/frontend/apps/desktop/components/CommonTable/TableHeader.vue:392
|
||||
#: app/frontend/apps/desktop/components/CommonTable/TableHeader.vue:399
|
||||
msgid "%s result(s) selected, selection limit reached"
|
||||
msgstr ""
|
||||
|
||||
@@ -1052,7 +1052,7 @@ msgstr ""
|
||||
#: app/assets/javascripts/app/views/integration/smime_list.jst.eco:15
|
||||
#: app/assets/javascripts/app/views/ssl_certificates_list.jst.eco:16
|
||||
#: app/frontend/apps/desktop/components/CommonTable/CommonSimpleTable.vue:100
|
||||
#: app/frontend/apps/desktop/components/CommonTable/TableHeader.vue:382
|
||||
#: app/frontend/apps/desktop/components/CommonTable/TableHeader.vue:389
|
||||
msgid "Actions"
|
||||
msgstr ""
|
||||
|
||||
@@ -1533,7 +1533,7 @@ msgstr ""
|
||||
msgid "Alarm"
|
||||
msgstr ""
|
||||
|
||||
#: app/frontend/apps/desktop/components/CommonTable/TableHeader.vue:393
|
||||
#: app/frontend/apps/desktop/components/CommonTable/TableHeader.vue:400
|
||||
msgid "All %s result(s) selected"
|
||||
msgstr ""
|
||||
|
||||
@@ -3413,7 +3413,7 @@ msgid "Clear search"
|
||||
msgstr ""
|
||||
|
||||
#: app/frontend/apps/desktop/components/CommonTable/CellContent/BulkCheckbox.vue:61
|
||||
#: app/frontend/apps/desktop/components/CommonTable/TableHeader.vue:416
|
||||
#: app/frontend/apps/desktop/components/CommonTable/TableHeader.vue:423
|
||||
#: app/frontend/apps/desktop/components/Form/fields/FieldAutoComplete/FieldAutoCompleteInput.vue:649
|
||||
#: app/frontend/apps/desktop/components/Form/fields/FieldDate/FieldDateTimeInput.vue:386
|
||||
#: app/frontend/apps/desktop/components/Form/fields/FieldSelect/FieldSelectInput.vue:314
|
||||
@@ -3596,6 +3596,10 @@ msgstr ""
|
||||
msgid "Color representation of the open ticket indicator in the sidebar."
|
||||
msgstr ""
|
||||
|
||||
#: app/frontend/apps/desktop/components/CommonTable/HeaderResizeLine.vue:70
|
||||
msgid "Column width: %s pixels"
|
||||
msgstr ""
|
||||
|
||||
#: app/frontend/apps/desktop/pages/personal-setting/views/PersonalSettingCalendar.vue:290
|
||||
msgid "Combined subscription URL"
|
||||
msgstr ""
|
||||
@@ -13966,7 +13970,7 @@ msgstr ""
|
||||
msgid "Resize article panel"
|
||||
msgstr ""
|
||||
|
||||
#: app/frontend/apps/desktop/components/CommonTable/HeaderResizeLine.vue:125
|
||||
#: app/frontend/apps/desktop/components/CommonTable/HeaderResizeLine.vue:134
|
||||
msgid "Resize column"
|
||||
msgstr ""
|
||||
|
||||
@@ -14564,6 +14568,10 @@ msgstr ""
|
||||
msgid "Search or enter phone number…"
|
||||
msgstr ""
|
||||
|
||||
#: app/frontend/apps/desktop/pages/search/components/SearchContent.vue:665
|
||||
msgid "Search result for: %s"
|
||||
msgstr ""
|
||||
|
||||
#: lib/external_data_source/errors.rb:114
|
||||
msgid "Search result label is not a string, a number or a boolean. Please provide search result label key."
|
||||
msgstr ""
|
||||
@@ -14766,11 +14774,11 @@ msgstr ""
|
||||
msgid "See your tickets from within your favorite calendar by adding the subscription URL to your calendar app."
|
||||
msgstr ""
|
||||
|
||||
#: app/frontend/apps/desktop/components/CommonTable/TableHeader.vue:296
|
||||
#: app/frontend/apps/desktop/components/CommonTable/TableHeader.vue:300
|
||||
msgid "Select"
|
||||
msgstr ""
|
||||
|
||||
#: app/frontend/apps/desktop/components/CommonTable/TableHeader.vue:406
|
||||
#: app/frontend/apps/desktop/components/CommonTable/TableHeader.vue:413
|
||||
msgid "Select %s result(s)"
|
||||
msgstr ""
|
||||
|
||||
@@ -14791,7 +14799,7 @@ msgstr ""
|
||||
msgid "Select Template"
|
||||
msgstr ""
|
||||
|
||||
#: app/frontend/apps/desktop/components/CommonTable/TableHeader.vue:407
|
||||
#: app/frontend/apps/desktop/components/CommonTable/TableHeader.vue:414
|
||||
msgid "Select all %s results"
|
||||
msgstr ""
|
||||
|
||||
@@ -19667,6 +19675,10 @@ msgstr ""
|
||||
msgid "Use the camera to take a photo for the avatar."
|
||||
msgstr ""
|
||||
|
||||
#: app/frontend/apps/desktop/components/CommonTable/HeaderResizeLine.vue:147
|
||||
msgid "Use the left and right arrow keys to resize the column."
|
||||
msgstr ""
|
||||
|
||||
#: db/seeds/settings.rb:2372
|
||||
msgid "Use the start time of the last customer thread (which may consist of multiple articles)."
|
||||
msgstr ""
|
||||
@@ -20666,7 +20678,7 @@ msgid "You do not have permission to update"
|
||||
msgstr ""
|
||||
|
||||
#: app/frontend/apps/desktop/components/CommonTable/CommonAdvancedTable.vue:419
|
||||
msgid "You don't have more tickets to load."
|
||||
msgid "You don't have more items to load."
|
||||
msgstr ""
|
||||
|
||||
#: app/frontend/shared/router/guards/before/permission.ts:27
|
||||
@@ -20771,7 +20783,7 @@ msgid "You need to configure the Zammad endpoints in the %s:"
|
||||
msgstr ""
|
||||
|
||||
#: app/frontend/apps/desktop/components/CommonTable/CommonAdvancedTable.vue:415
|
||||
msgid "You reached the table limit of %s tickets (%s remaining)."
|
||||
msgid "You reached the table limit of %s items (%s remaining)."
|
||||
msgstr ""
|
||||
|
||||
#: app/assets/javascripts/app/controllers/agent_ticket_create.coffee:772
|
||||
|
||||
Reference in New Issue
Block a user