From b3954772751607e3b92ed2b0d2b32adb3cfee530 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 13 Feb 2026 13:49:54 +0000 Subject: [PATCH 1/3] fix: chart components reactivity issues in documentation This commit fixes an issue where chart components (BarChart, LineChart, DonutChart, etc.) in the documentation were not reflecting prop changes made via the playground. The fix involves: - Adding missing watchers for several props in each chart component. - Ensuring watchers trigger data/options updates (e.g., calling mergeChartDataNoSelect). - Updating chartOptions reactively by replacing the object instead of direct property mutation, ensuring vue-chartjs detects the changes. - Addressing feedback from code review by adding immediate:true to new watchers in LineChart.vue. Co-authored-by: IhGori <73910233+IhGori@users.noreply.github.com> --- src/components/BarChart.vue | 44 ++++++++-- src/components/DonutChart.vue | 19 ++++- src/components/LineChart.vue | 126 ++++++++++++++++++++++++++++- src/components/PieChart.vue | 12 ++- src/components/PolarAreaChart.vue | 26 +++++- src/components/RadialBarChart.vue | 19 ++++- src/components/StackedBarChart.vue | 24 ++++-- 7 files changed, 247 insertions(+), 23 deletions(-) diff --git a/src/components/BarChart.vue b/src/components/BarChart.vue index 332d29f8..cdc8e02f 100644 --- a/src/components/BarChart.vue +++ b/src/components/BarChart.vue @@ -125,18 +125,21 @@ export default { watch: { labels: { handler(newValue) { - this.localLabels = newValue + this.localLabels = newValue; + this.mergeChartDataNoSelect(this.data); }, immediate: true, }, variant: { - handler(newValue, oldValue) { - if (newValue === 'gray' || newValue === 'dark') { + handler(newValue) { + if (newValue === 'gray' || newValue === 'dark') { this.deleteFirstTwoColors = true; } else { this.deleteFirstTwoColors = false; } + + this.mergeChartDataNoSelect(this.data); }, immediate: true, }, @@ -150,11 +153,36 @@ export default { barWidth: { handler(newValue) { - if (newValue >= 0.1 && newValue <= 1) { - this.chartOptions.categoryPercentage = newValue; - } else { - this.chartOptions.categoryPercentage = 1; - } + const categoryPercentage = (newValue >= 0.1 && newValue <= 1) ? newValue : 1; + this.chartOptions = { + ...this.chartOptions, + categoryPercentage, + }; + }, + immediate: true, + }, + + horizontalBar: { + handler(newValue) { + this.chartOptions = { + ...this.chartOptions, + indexAxis: newValue ? 'y' : 'x', + scales: newValue + ? { + x: { beginAtZero: true }, + } + : { + y: { + beginAtZero: true, + grace: '5%', + ticks: { + precision: 0 + }, + categoryPercentage: 0.6, + barPercentage: 0.8 + }, + }, + }; }, immediate: true, }, diff --git a/src/components/DonutChart.vue b/src/components/DonutChart.vue index 20eee72d..c5d92719 100644 --- a/src/components/DonutChart.vue +++ b/src/components/DonutChart.vue @@ -135,17 +135,34 @@ export default { labels: { handler(newValue) { this.localLabels = newValue; + this.mergeChartDataNoSelect(this.data); }, immediate: true, }, variant: { handler(newValue) { - if (newValue === 'gray' || newValue === 'dark') { + if (newValue === 'gray' || newValue === 'dark') { this.deleteFirstTwoColors = true; } else { this.deleteFirstTwoColors = false; } + + this.mergeChartDataNoSelect(this.data); + }, + immediate: true, + }, + + theme: { + handler() { + this.mergeChartDataNoSelect(this.data); + }, + immediate: true, + }, + + colors: { + handler() { + this.mergeChartDataNoSelect(this.data); }, immediate: true, }, diff --git a/src/components/LineChart.vue b/src/components/LineChart.vue index ca08128f..181d2194 100644 --- a/src/components/LineChart.vue +++ b/src/components/LineChart.vue @@ -232,18 +232,28 @@ export default { watch: { labels: { handler(newValue) { - this.localLabels = newValue + this.localLabels = newValue; + this.mergeChartDataNoSelect(this.data); }, immediate: true, }, variant: { handler(newValue) { - if (newValue === 'gray' || newValue === 'dark') { + if (newValue === 'gray' || newValue === 'dark') { this.deleteFirstTwoColors = true; } else { this.deleteFirstTwoColors = false; } + + this.mergeChartDataNoSelect(this.data); + }, + immediate: true, + }, + + theme: { + handler() { + this.mergeChartDataNoSelect(this.data); }, immediate: true, }, @@ -255,6 +265,24 @@ export default { immediate: true, }, + showLabelName: { + handler() { + this.mergeChartDataNoSelect(this.data); + }, + immediate: true, + }, + + fill: { + handler(newValue) { + this.chartOptions = { + ...this.chartOptions, + fill: newValue, + }; + this.mergeChartDataNoSelect(this.data); + }, + immediate: true, + }, + isDashed: { handler(newValue) { if (newValue === true) { @@ -263,6 +291,95 @@ export default { }, immediate: true, }, + + borderDash: { + handler() { + this.checkDashed(); + }, + immediate: true, + }, + + scales: { + handler(newValue) { + this.chartOptions = { + ...this.chartOptions, + scales: { + ...this.chartOptions.scales, + ...newValue, + }, + }; + }, + immediate: true, + }, + + animation: { + handler(newValue) { + this.chartOptions = { + ...this.chartOptions, + animation: { + ...newValue, + }, + }; + }, + immediate: true, + }, + + plugins: { + handler(newValue) { + this.chartOptions = { + ...this.chartOptions, + plugins: { + ...this.chartOptions.plugins, + ...newValue, + }, + }; + }, + immediate: true, + }, + + xAxisRange: { + handler(newValue) { + this.chartOptions = { + ...this.chartOptions, + scales: { + ...this.chartOptions.scales, + x: { + ...this.chartOptions.scales?.x, + suggestedMin: newValue[0], + suggestedMax: newValue[1], + }, + }, + }; + }, + immediate: true, + }, + + yAxisRange: { + handler(newValue) { + this.chartOptions = { + ...this.chartOptions, + scales: { + ...this.chartOptions.scales, + y: { + ...this.chartOptions.scales?.y, + suggestedMin: newValue[0], + suggestedMax: newValue[1], + }, + }, + }; + }, + immediate: true, + }, + + smoothing: { + handler(newValue) { + this.chartOptions = { + ...this.chartOptions, + tension: newValue, + }; + }, + immediate: true, + }, }, mounted() { @@ -373,7 +490,10 @@ export default { }, checkDashed() { - this.chartOptions.borderDash = [this.borderDash[0], this.borderDash[1]]; + this.chartOptions = { + ...this.chartOptions, + borderDash: [this.borderDash[0], this.borderDash[1]], + }; } } } diff --git a/src/components/PieChart.vue b/src/components/PieChart.vue index 8e995909..63ee3bda 100644 --- a/src/components/PieChart.vue +++ b/src/components/PieChart.vue @@ -136,17 +136,27 @@ export default { labels: { handler(newValue) { this.localLabels = newValue; + this.mergeChartDataNoSelect(this.data); }, immediate: true, }, variant: { handler(newValue) { - if (newValue === 'gray' || newValue === 'dark') { + if (newValue === 'gray' || newValue === 'dark') { this.deleteFirstTwoColors = true; } else { this.deleteFirstTwoColors = false; } + + this.mergeChartDataNoSelect(this.data); + }, + immediate: true, + }, + + colors: { + handler() { + this.mergeChartDataNoSelect(this.data); }, immediate: true, }, diff --git a/src/components/PolarAreaChart.vue b/src/components/PolarAreaChart.vue index 0ac4d399..869fbea7 100644 --- a/src/components/PolarAreaChart.vue +++ b/src/components/PolarAreaChart.vue @@ -125,18 +125,21 @@ export default { watch: { labels: { handler(newValue) { - this.localLabels = newValue + this.localLabels = newValue; + this.mergeChartDataNoSelect(this.data); }, immediate: true, }, variant: { handler(newValue) { - if (newValue === 'gray' || newValue === 'dark') { + if (newValue === 'gray' || newValue === 'dark') { this.deleteFirstTwoColors = true; } else { this.deleteFirstTwoColors = false; } + + this.mergeChartDataNoSelect(this.data); }, immediate: true, }, @@ -147,6 +150,25 @@ export default { }, immediate: true, }, + + isVisiblePointNames: { + handler(newValue) { + this.chartOptions = { + ...this.chartOptions, + scales: { + ...this.chartOptions.scales, + r: { + ...this.chartOptions.scales?.r, + pointLabels: { + ...this.chartOptions.scales?.r?.pointLabels, + display: newValue, + }, + }, + }, + }; + }, + immediate: true, + }, }, methods: { diff --git a/src/components/RadialBarChart.vue b/src/components/RadialBarChart.vue index 442616fe..91a98158 100644 --- a/src/components/RadialBarChart.vue +++ b/src/components/RadialBarChart.vue @@ -173,17 +173,34 @@ export default { labels: { handler(newValue) { this.localLabels = newValue; + this.mergeChartDataNoSelect(this.data); }, immediate: true, }, variant: { handler(newValue) { - if (newValue === 'gray' || newValue === 'dark') { + if (newValue === 'gray' || newValue === 'dark') { this.deleteFirstTwoColors = true; } else { this.deleteFirstTwoColors = false; } + + this.mergeChartDataNoSelect(this.data); + }, + immediate: true, + }, + + theme: { + handler() { + this.mergeChartDataNoSelect(this.data); + }, + immediate: true, + }, + + colors: { + handler() { + this.mergeChartDataNoSelect(this.data); }, immediate: true, }, diff --git a/src/components/StackedBarChart.vue b/src/components/StackedBarChart.vue index 8794f4f0..75377b3e 100644 --- a/src/components/StackedBarChart.vue +++ b/src/components/StackedBarChart.vue @@ -154,18 +154,28 @@ export default { watch: { labels: { handler(newValue) { - this.localLabels = newValue + this.localLabels = newValue; + this.mergeChartDataNoSelect(this.data); }, immediate: true, }, variant: { handler(newValue) { - if (newValue === 'gray' || newValue === 'dark') { + if (newValue === 'gray' || newValue === 'dark') { this.deleteFirstTwoColors = true; } else { this.deleteFirstTwoColors = false; } + + this.mergeChartDataNoSelect(this.data); + }, + immediate: true, + }, + + theme: { + handler() { + this.mergeChartDataNoSelect(this.data); }, immediate: true, }, @@ -179,11 +189,11 @@ export default { barWidth: { handler(newValue) { - if (newValue >= 0.1 && newValue <= 1) { - this.chartOptions.categoryPercentage = newValue; - } else { - this.chartOptions.categoryPercentage = 1; - } + const categoryPercentage = (newValue >= 0.1 && newValue <= 1) ? newValue : 1; + this.chartOptions = { + ...this.chartOptions, + categoryPercentage, + }; }, immediate: true, }, From 907f1b9e48334937c46ab5a6cd53cd2bbf992bd3 Mon Sep 17 00:00:00 2001 From: Igor Vinicius Date: Fri, 13 Feb 2026 11:13:55 -0300 Subject: [PATCH 2/3] refactor: Corige o uso da prop showLabelName mas nao foi declarado --- src/components/PolarAreaChart.vue | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/components/PolarAreaChart.vue b/src/components/PolarAreaChart.vue index 869fbea7..aa6fb3a9 100644 --- a/src/components/PolarAreaChart.vue +++ b/src/components/PolarAreaChart.vue @@ -75,6 +75,16 @@ export default { type: Boolean, default: false, }, + /** + * Defina o texto a ser exibido para a legenda. Quando definido como verdadeiro + * (true), espera-se que exiba o nome do data. Quando definido + * como falso (false), será definido o nome do dataset + */ + showLabelName: { + type: Boolean, + required: true, + default: true, + }, }, data() { @@ -209,7 +219,7 @@ export default { data.forEach(obj => { obj.datasets.forEach(state => { const dataset = { - label: this.showLabelName ? state.name :state.label, + label: this.showLabelName ? state.name : state.label, data: state.data, name: state.name, borderRadius: 6, From 9559dd42601e5374f246cb21709bb27c235c5ba4 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 13 Feb 2026 15:12:31 +0000 Subject: [PATCH 3/3] fix: implement reactivity in chart components for documentation playground - Added watchers for all relevant props in BarChart, LineChart, DonutChart, PieChart, PolarAreaChart, RadialBarChart, and StackedBarChart. - Ensured chartOptions updates are reactive by using object spread to trigger Vue reactivity. - Fixed RadialBarChart prop type and largest value calculation. - Improved LineChart dashed line logic to respect isDashed prop. - Optimized BarChart scale merging to prevent discarding custom configurations. - Verified changes with unit tests and local documentation server. Co-authored-by: IhGori <73910233+IhGori@users.noreply.github.com> --- src/components/BarChart.vue | 18 ++++++++++-------- src/components/LineChart.vue | 2 +- src/components/PolarAreaChart.vue | 12 +----------- src/components/RadialBarChart.vue | 30 +++++++++++++----------------- 4 files changed, 25 insertions(+), 37 deletions(-) diff --git a/src/components/BarChart.vue b/src/components/BarChart.vue index cdc8e02f..cba46593 100644 --- a/src/components/BarChart.vue +++ b/src/components/BarChart.vue @@ -167,12 +167,13 @@ export default { this.chartOptions = { ...this.chartOptions, indexAxis: newValue ? 'y' : 'x', - scales: newValue - ? { - x: { beginAtZero: true }, - } - : { - y: { + scales: { + ...this.chartOptions.scales, + x: newValue + ? { beginAtZero: true } + : { ...this.chartOptions.scales?.x }, + y: !newValue + ? { beginAtZero: true, grace: '5%', ticks: { @@ -180,8 +181,9 @@ export default { }, categoryPercentage: 0.6, barPercentage: 0.8 - }, - }, + } + : { ...this.chartOptions.scales?.y }, + }, }; }, immediate: true, diff --git a/src/components/LineChart.vue b/src/components/LineChart.vue index 181d2194..63e0ecfa 100644 --- a/src/components/LineChart.vue +++ b/src/components/LineChart.vue @@ -492,7 +492,7 @@ export default { checkDashed() { this.chartOptions = { ...this.chartOptions, - borderDash: [this.borderDash[0], this.borderDash[1]], + borderDash: this.isDashed ? [this.borderDash[0], this.borderDash[1]] : [], }; } } diff --git a/src/components/PolarAreaChart.vue b/src/components/PolarAreaChart.vue index aa6fb3a9..44da044c 100644 --- a/src/components/PolarAreaChart.vue +++ b/src/components/PolarAreaChart.vue @@ -75,16 +75,6 @@ export default { type: Boolean, default: false, }, - /** - * Defina o texto a ser exibido para a legenda. Quando definido como verdadeiro - * (true), espera-se que exiba o nome do data. Quando definido - * como falso (false), será definido o nome do dataset - */ - showLabelName: { - type: Boolean, - required: true, - default: true, - }, }, data() { @@ -219,7 +209,7 @@ export default { data.forEach(obj => { obj.datasets.forEach(state => { const dataset = { - label: this.showLabelName ? state.name : state.label, + label: state.label, data: state.data, name: state.name, borderRadius: 6, diff --git a/src/components/RadialBarChart.vue b/src/components/RadialBarChart.vue index 91a98158..1b91f3aa 100644 --- a/src/components/RadialBarChart.vue +++ b/src/components/RadialBarChart.vue @@ -59,16 +59,9 @@ export default { * `data` (array com os valores númericos). */ data: { - type: Object, + type: Array, required: true, - default: () => ({ - datasets: [ - { - label: '', - data: [], - } - ] - }) + default: () => [], }, /** * Personaliza a paleta de cores do gráfico. São 11 variantes implementadas: @@ -207,6 +200,7 @@ export default { data: { handler(newValue) { + this.updateLargestValue(newValue); this.mergeChartDataNoSelect(newValue); }, immediate: true, @@ -214,20 +208,22 @@ export default { }, mounted() { - - this.data.forEach(item => { - if (item.datasets[0].data[0] > this.largestValue) { - this.largestValue = item.datasets[0].data[0]; - } - - }) - + this.updateLargestValue(this.data); this.mergeChartDataNoSelect(this.data); }, methods: { paleteBuilder, + updateLargestValue(chartData) { + this.largestValue = 0; + chartData.forEach(item => { + if (item.datasets[0] && item.datasets[0].data && item.datasets[0].data[0] > this.largestValue) { + this.largestValue = item.datasets[0].data[0]; + } + }); + }, + palete() { this.palletColors = this.paleteBuilder(this.sassColorVariables.palete); this.removeFirstTwoElements();