Skip to content

Commit 376ccec

Browse files
feat: charts a11y improvements (#2193)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent deee8f2 commit 376ccec

File tree

9 files changed

+162
-10
lines changed

9 files changed

+162
-10
lines changed

app/components/Compare/FacetBarChart.vue

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,13 @@ function buildExportFilename(extension: string): string {
113113
const config = computed<VueUiHorizontalBarConfig>(() => {
114114
return {
115115
theme: isDarkMode.value ? 'dark' : '',
116+
a11y: {
117+
translations: {
118+
keyboardNavigation: $t('package.trends.chart_assistive_text.keyboard_navigation_vertical'),
119+
tableAvailable: $t('package.trends.chart_assistive_text.table_available'),
120+
tableCaption: $t('package.trends.chart_assistive_text.table_caption'),
121+
},
122+
},
116123
userOptions: {
117124
buttons: {
118125
tooltip: false,
@@ -272,6 +279,12 @@ const config = computed<VueUiHorizontalBarConfig>(() => {
272279
<div class="font-mono facet-bar">
273280
<ClientOnly v-if="dataset.length">
274281
<VueUiHorizontalBar :key="chartKey" :dataset :config class="[direction:ltr]">
282+
<template #hint="{ isVisible }">
283+
<p v-if="isVisible" class="text-accent text-xs pt-2" aria-hidden="true">
284+
{{ $t('compare.packages.bar_chart_nav_hint') }}
285+
</p>
286+
</template>
287+
275288
<template #pattern="{ patternId, seriesIndex }">
276289
<ChartPatternSlot
277290
v-if="seriesIndex != 0"
@@ -349,6 +362,19 @@ const config = computed<VueUiHorizontalBarConfig>(() => {
349362
</div>
350363
</template>
351364

365+
<style scoped>
366+
:deep(.vue-data-ui-component svg:focus-visible) {
367+
outline: 1px solid var(--accent-color) !important;
368+
border-radius: 0.1rem;
369+
outline-offset: 3px !important;
370+
}
371+
:deep(.vue-ui-user-options-button:focus-visible),
372+
:deep(.vue-ui-user-options :first-child:focus-visible) {
373+
outline: 0.1rem solid var(--accent-color) !important;
374+
border-radius: 0.25rem;
375+
}
376+
</style>
377+
352378
<style>
353379
.facet-bar .atom-subtitle {
354380
width: 80% !important;

app/components/Package/TrendsChart.vue

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1388,6 +1388,15 @@ watch(
13881388
const chartConfig = computed<VueUiXyConfig>(() => {
13891389
return {
13901390
theme: isDarkMode.value ? 'dark' : ('' as VueDataUiTheme),
1391+
a11y: {
1392+
translations: {
1393+
keyboardNavigation: $t(
1394+
'package.trends.chart_assistive_text.keyboard_navigation_horizontal',
1395+
),
1396+
tableAvailable: $t('package.trends.chart_assistive_text.table_available'),
1397+
tableCaption: $t('package.trends.chart_assistive_text.table_caption'),
1398+
},
1399+
},
13911400
chart: {
13921401
height: chartHeight.value,
13931402
backgroundColor: colors.value.bg,
@@ -1878,6 +1887,13 @@ watch(selectedMetric, value => {
18781887
@zoomEnd="setIsZoom"
18791888
@zoomReset="isZoomed = false"
18801889
>
1890+
<!-- Keyboard navigation hint -->
1891+
<template #hint="{ isVisible }">
1892+
<p v-if="isVisible" class="text-accent text-xs -mt-6 text-center" aria-hidden="true">
1893+
{{ $t('compare.packages.line_chart_nav_hint') }}
1894+
</p>
1895+
</template>
1896+
18811897
<!-- Injecting custom svg elements -->
18821898
<template #svg="{ svg }">
18831899
<!-- Estimation lines for monthly & yearly granularities when the end date induces a downwards trend -->
@@ -2130,6 +2146,19 @@ watch(selectedMetric, value => {
21302146
</div>
21312147
</template>
21322148

2149+
<style scoped>
2150+
:deep(.vue-data-ui-component svg:focus-visible) {
2151+
outline: 1px solid var(--accent-color) !important;
2152+
border-radius: 0.1rem;
2153+
outline-offset: 0;
2154+
}
2155+
:deep(.vue-ui-user-options-button:focus-visible),
2156+
:deep(.vue-ui-user-options :first-child:focus-visible) {
2157+
outline: 0.1rem solid var(--accent-color) !important;
2158+
border-radius: 0.25rem;
2159+
}
2160+
</style>
2161+
21332162
<style>
21342163
.vue-ui-pen-and-paper-actions {
21352164
background: var(--bg-elevated) !important;

app/components/Package/VersionDistribution.vue

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,15 @@ const hasMinimap = computed<boolean>(() => {
161161
const chartConfig = computed<VueUiXyConfig>(() => {
162162
return {
163163
theme: isDarkMode.value ? 'dark' : '',
164+
a11y: {
165+
translations: {
166+
keyboardNavigation: $t(
167+
'package.trends.chart_assistive_text.keyboard_navigation_horizontal',
168+
),
169+
tableAvailable: $t('package.trends.chart_assistive_text.table_available'),
170+
tableCaption: $t('package.trends.chart_assistive_text.table_caption'),
171+
},
172+
},
164173
chart: {
165174
title: {
166175
text: dateRangeLabel.value,
@@ -447,6 +456,13 @@ const chartConfig = computed<VueUiXyConfig>(() => {
447456
<ClientOnly v-if="xyDataset.length > 0 && !error">
448457
<div class="chart-container w-full" :key="groupingMode">
449458
<VueUiXy :dataset="xyDataset" :config="chartConfig" class="[direction:ltr]">
459+
<!-- Keyboard navigation hint -->
460+
<template #hint="{ isVisible }">
461+
<p v-if="isVisible" class="text-accent text-xs -mt-6 text-center" aria-hidden="true">
462+
{{ $t('compare.packages.line_chart_nav_hint') }}
463+
</p>
464+
</template>
465+
450466
<!-- Injecting custom svg elements -->
451467
<template #svg="{ svg }">
452468
<!-- Inject legend during SVG print only -->
@@ -664,6 +680,18 @@ const chartConfig = computed<VueUiXyConfig>(() => {
664680
:deep(.vue-ui-xy) svg rect {
665681
transition: none !important;
666682
}
683+
684+
:deep(.vue-data-ui-component svg:focus-visible) {
685+
outline: 1px solid var(--accent-color) !important;
686+
border-radius: 0.1rem;
687+
outline-offset: 0 !important;
688+
}
689+
690+
:deep(.vue-ui-user-options-button:focus-visible),
691+
:deep(.vue-ui-user-options :first-child:focus-visible) {
692+
outline: 0.1rem solid var(--accent-color) !important;
693+
border-radius: 0.25rem;
694+
}
667695
</style>
668696

669697
<style>

app/components/Package/WeeklyDownloadStats.vue

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,15 @@ function layEgg() {
313313
314314
const config = computed<VueUiSparklineConfig>(() => {
315315
return {
316+
a11y: {
317+
translations: {
318+
keyboardNavigation: $t(
319+
'package.trends.chart_assistive_text.keyboard_navigation_horizontal',
320+
),
321+
tableAvailable: $t('package.trends.chart_assistive_text.table_available'),
322+
tableCaption: $t('package.trends.chart_assistive_text.table_caption'),
323+
},
324+
},
316325
theme: 'dark',
317326
/**
318327
* The built-in skeleton loader kicks in when the component is mounted but the data is not yet ready.
@@ -416,6 +425,13 @@ const config = computed<VueUiSparklineConfig>(() => {
416425
<template v-if="isLoadingWeeklyDownloads || hasWeeklyDownloads">
417426
<ClientOnly>
418427
<VueUiSparkline class="w-full max-w-xs" :dataset :config>
428+
<!-- Keyboard navigation hint -->
429+
<template #hint="{ isVisible }">
430+
<p v-if="isVisible" class="text-accent text-xs text-center mt-2" aria-hidden="true">
431+
{{ $t('package.downloads.sparkline_nav_hint') }}
432+
</p>
433+
</template>
434+
419435
<template #skeleton>
420436
<!-- This empty div overrides the default built-in scanning animation on load -->
421437
<div />
@@ -493,6 +509,12 @@ const config = computed<VueUiSparklineConfig>(() => {
493509
.opacity-leave-from {
494510
opacity: 1;
495511
}
512+
513+
:deep(.vue-data-ui-component svg:focus-visible) {
514+
outline: 0.1rem solid var(--accent-color) !important;
515+
border-radius: 0.1rem;
516+
outline-offset: 3px;
517+
}
496518
</style>
497519

498520
<style>

i18n/locales/en.json

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,12 @@
482482
"maintainer_template": "{avatar} {char126}{name}"
483483
},
484484
"trends": {
485+
"chart_assistive_text": {
486+
"keyboard_navigation_horizontal": "Use the left and right arrow keys to cycle through data points.",
487+
"keyboard_navigation_vertical": "Use the up and down arrow keys to cycle through data points.",
488+
"table_available": "A data table for this chart is available below.",
489+
"table_caption": "Chart data table"
490+
},
485491
"granularity": "Granularity",
486492
"granularity_daily": "Daily",
487493
"granularity_weekly": "Weekly",
@@ -540,7 +546,8 @@
540546
"downloads": {
541547
"title": "Weekly Downloads",
542548
"community_distribution": "View community adoption distribution",
543-
"subtitle": "Across all versions"
549+
"subtitle": "Across all versions",
550+
"sparkline_nav_hint": "Use ← →"
544551
},
545552
"install_scripts": {
546553
"title": "Install Scripts",
@@ -1105,7 +1112,9 @@
11051112
"empty_title": "Select packages to compare",
11061113
"empty_description": "Search and add at least 2 packages above to see a side-by-side comparison of their metrics.",
11071114
"table_view": "Table",
1108-
"charts_view": "Charts"
1115+
"charts_view": "Charts",
1116+
"bar_chart_nav_hint": "Use ↑ ↓",
1117+
"line_chart_nav_hint": "Use ← →"
11091118
},
11101119
"selector": {
11111120
"search_label": "Search for packages",

i18n/locales/fr-FR.json

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,12 @@
449449
"show_less": "(afficher moins)"
450450
},
451451
"trends": {
452+
"chart_assistive_text": {
453+
"keyboard_navigation_horizontal": "Utilisez les touches fléchées gauche et droite pour parcourir les points de données.",
454+
"keyboard_navigation_vertical": "Utilisez les touches fléchées haut et bas pour parcourir les points de données.",
455+
"table_available": "Un tableau de données pour ce graphique est disponible ci-dessous.",
456+
"table_caption": "Tableau de données du graphique"
457+
},
452458
"granularity": "Granularité",
453459
"granularity_daily": "Par Jour",
454460
"granularity_weekly": "Par Semaine",
@@ -506,7 +512,8 @@
506512
"downloads": {
507513
"title": "Téléchargements hebdo.",
508514
"community_distribution": "Voir la distribution des versions téléchargées par la communauté",
509-
"subtitle": "Toutes versions confondues"
515+
"subtitle": "Toutes versions confondues",
516+
"sparkline_nav_hint": "Utilisez ← →"
510517
},
511518
"install_scripts": {
512519
"title": "Scripts d'installation",
@@ -1058,7 +1065,11 @@
10581065
"loading": "Chargement des données des paquets...",
10591066
"error": "Échec du chargement des données. Veuillez réessayer.",
10601067
"empty_title": "Sélectionnez des paquets à comparer",
1061-
"empty_description": "Recherchez et ajoutez au moins 2 paquets ci-dessus pour voir une comparaison côte à côte de leurs facettes."
1068+
"empty_description": "Recherchez et ajoutez au moins 2 paquets ci-dessus pour voir une comparaison côte à côte de leurs facettes.",
1069+
"table_view": "Tableau",
1070+
"charts_view": "Graphiques",
1071+
"bar_chart_nav_hint": "Utilisez ↑ ↓",
1072+
"line_chart_nav_hint": "Utilisez ← →"
10621073
},
10631074
"selector": {
10641075
"search_label": "Rechercher des paquets",

i18n/schema.json

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1450,6 +1450,24 @@
14501450
"trends": {
14511451
"type": "object",
14521452
"properties": {
1453+
"chart_assistive_text": {
1454+
"type": "object",
1455+
"properties": {
1456+
"keyboard_navigation_horizontal": {
1457+
"type": "string"
1458+
},
1459+
"keyboard_navigation_vertical": {
1460+
"type": "string"
1461+
},
1462+
"table_available": {
1463+
"type": "string"
1464+
},
1465+
"table_caption": {
1466+
"type": "string"
1467+
}
1468+
},
1469+
"additionalProperties": false
1470+
},
14531471
"granularity": {
14541472
"type": "string"
14551473
},
@@ -1626,6 +1644,9 @@
16261644
},
16271645
"subtitle": {
16281646
"type": "string"
1647+
},
1648+
"sparkline_nav_hint": {
1649+
"type": "string"
16291650
}
16301651
},
16311652
"additionalProperties": false
@@ -3321,6 +3342,12 @@
33213342
},
33223343
"charts_view": {
33233344
"type": "string"
3345+
},
3346+
"bar_chart_nav_hint": {
3347+
"type": "string"
3348+
},
3349+
"line_chart_nav_hint": {
3350+
"type": "string"
33243351
}
33253352
},
33263353
"additionalProperties": false

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@
109109
"vite-plugin-pwa": "1.2.0",
110110
"vite-plus": "0.1.12",
111111
"vue": "3.5.30",
112-
"vue-data-ui": "3.15.12"
112+
"vue-data-ui": "3.16.0"
113113
},
114114
"devDependencies": {
115115
"@e18e/eslint-plugin": "0.3.0",

pnpm-lock.yaml

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)