From 834aebb5ca3635dc960dc817cbb9ee3406f21841 Mon Sep 17 00:00:00 2001 From: graphieros Date: Wed, 25 Mar 2026 12:42:51 +0100 Subject: [PATCH 01/34] chore: add translations --- i18n/locales/en.json | 2 ++ i18n/locales/fr-FR.json | 2 ++ i18n/schema.json | 6 ++++++ 3 files changed, 10 insertions(+) diff --git a/i18n/locales/en.json b/i18n/locales/en.json index b6345ccfd3..b46674e1ce 100644 --- a/i18n/locales/en.json +++ b/i18n/locales/en.json @@ -488,6 +488,8 @@ "table_available": "A data table for this chart is available below.", "table_caption": "Chart data table" }, + "chart_view_combined": "Combined view", + "chart_view_split": "Split view", "granularity": "Granularity", "granularity_daily": "Daily", "granularity_weekly": "Weekly", diff --git a/i18n/locales/fr-FR.json b/i18n/locales/fr-FR.json index 6ac88ca9d3..d971b93abe 100644 --- a/i18n/locales/fr-FR.json +++ b/i18n/locales/fr-FR.json @@ -486,6 +486,8 @@ "table_available": "Un tableau de données pour ce graphique est disponible ci-dessous.", "table_caption": "Tableau de données du graphique" }, + "chart_view_combined": "Vue groupée", + "chart_view_split": "Vue séparée", "granularity": "Granularité", "granularity_daily": "Par Jour", "granularity_weekly": "Par Semaine", diff --git a/i18n/schema.json b/i18n/schema.json index 1be4702dc3..a1cff2a828 100644 --- a/i18n/schema.json +++ b/i18n/schema.json @@ -1468,6 +1468,12 @@ }, "additionalProperties": false }, + "chart_view_combined": { + "type": "string" + }, + "chart_view_split": { + "type": "string" + }, "granularity": { "type": "string" }, From f716bebf283b42a632ff35cc8a1c04379006e61f Mon Sep 17 00:00:00 2001 From: graphieros Date: Wed, 25 Mar 2026 12:43:22 +0100 Subject: [PATCH 02/34] feat: create split parklines component --- app/components/Chart/SplitSparkline.vue | 225 ++++++++++++++++++++++++ test/nuxt/a11y.spec.ts | 55 ++++++ 2 files changed, 280 insertions(+) create mode 100644 app/components/Chart/SplitSparkline.vue diff --git a/app/components/Chart/SplitSparkline.vue b/app/components/Chart/SplitSparkline.vue new file mode 100644 index 0000000000..f4a418bd4f --- /dev/null +++ b/app/components/Chart/SplitSparkline.vue @@ -0,0 +1,225 @@ + + + \ No newline at end of file diff --git a/test/nuxt/a11y.spec.ts b/test/nuxt/a11y.spec.ts index 35df44b805..51de71d5ce 100644 --- a/test/nuxt/a11y.spec.ts +++ b/test/nuxt/a11y.spec.ts @@ -233,6 +233,7 @@ import { PackageSelectionView, PackageSelectionCheckbox, PackageExternalLinks, + ChartSplitSparkline, } from '#components' // Server variant components must be imported directly to test the server-side render @@ -246,6 +247,7 @@ import FacetBarChart from '~/components/Compare/FacetBarChart.vue' import PackageLikeCard from '~/components/Package/LikeCard.vue' import SizeIncrease from '~/components/Package/SizeIncrease.vue' import Likes from '~/components/Package/Likes.vue' +import type { VueUiXyDatasetItem } from 'vue-data-ui' describe('component accessibility audits', () => { describe('DateTime', () => { @@ -941,6 +943,59 @@ describe('component accessibility audits', () => { }) }) + describe('ChartSplitSparkline', () => { + const dataset = [ + { + color: 'oklch(0.7025 0.132 160.37)', + name: 'vue', + series: [100_000, 200_000, 150_000], + type: 'line', + dashIndices: [] + }, + { + color: 'oklch(0.6917 0.1865 35.04)', + name: 'svelte', + series: [100_000, 200_000, 150_000], + type: 'line', + dashIndices: [] + } + ] as Array + const dates = [1743465600000, 1744070400000, 1744675200000] + const datetimeFormatterOptions = { + year: 'yyyy-MM-dd', + month: 'yyyy-MM-dd', + day: 'yyyy-MM-dd' + } + + it('should have no accessibility violations', async () => { + const component = await mountSuspended(ChartSplitSparkline, { + props: { + dataset, + dates, + datetimeFormatterOptions + } + }) + const results = await runAxe(component) + expect(results.violations).toEqual([]) + }) + + it('should have no accessibility violations when empty', async () => { + const component = await mountSuspended(ChartSplitSparkline, { + props: { + dataset: [], + dates: [], + datetimeFormatterOptions + } + }) + const results = await runAxe(component) + expect(results.violations).toEqual([]) + }) + }) + describe('PackagePlaygrounds', () => { it('should have no accessibility violations with single link', async () => { const links = [ From f0e56373fb0b810ec0ac15853b8e66e80f551862 Mon Sep 17 00:00:00 2001 From: graphieros Date: Wed, 25 Mar 2026 12:43:46 +0100 Subject: [PATCH 03/34] feat: implement split view for compare download charts --- app/components/Package/TrendsChart.vue | 59 +++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/app/components/Package/TrendsChart.vue b/app/components/Package/TrendsChart.vue index 21bddcf2f7..ba730e5aaa 100644 --- a/app/components/Package/TrendsChart.vue +++ b/app/components/Package/TrendsChart.vue @@ -1622,6 +1622,10 @@ watch(selectedMetric, value => { if (!isMounted.value) return loadMetric(value) }) + +// Sparkline charts (a11y alternative display for multi series) +const isSparklineLayout = shallowRef(false) +