From c9387d0f4427d2995842a6506f2e715ba9d593c7 Mon Sep 17 00:00:00 2001 From: Paul Marbach Date: Fri, 12 Dec 2025 16:30:58 -0500 Subject: [PATCH] remove spotlight, starting to make gradients a bit more predictable --- .../v0alpha1.gauge_tests_new.v42.json | 108 ++++++------- .../v0alpha1.gauge_tests_old_to_new.v42.json | 3 +- ...a1.gauge_tests_old_to_new.v42.v1beta1.json | 7 +- ...1.gauge_tests_old_to_new.v42.v2alpha1.json | 7 +- ...a1.gauge_tests_old_to_new.v42.v2beta1.json | 7 +- .../panel-gauge/gauge_tests_new.v42.json | 103 ++++-------- .../gauge_tests_old_to_new.v42.json | 3 +- .../panel-gauge/gauge_tests_new.json | 153 +++++++----------- .../panel-gauge/gauge_tests_old_to_new.json | 3 +- .../src/themes/colorManipulator.test.ts | 46 ++++++ .../src/themes/colorManipulator.ts | 50 ++++++ .../panelcfg/x/NewGaugePanelCfg_types.gen.ts | 6 +- .../components/RadialGauge/RadialArcPath.tsx | 17 +- .../src/components/RadialGauge/RadialBar.tsx | 52 +----- .../RadialGauge/RadialColorDefs.tsx | 148 ++++++++++++----- .../RadialGauge/RadialGauge.story.tsx | 37 +---- .../components/RadialGauge/RadialGauge.tsx | 20 +-- .../src/components/RadialGauge/effects.tsx | 39 ----- .../plugins/panel/radialbar/EffectsEditor.tsx | 11 -- .../panel/radialbar/RadialBarPanel.tsx | 3 +- public/app/plugins/panel/radialbar/module.tsx | 38 +++-- .../app/plugins/panel/radialbar/panelcfg.cue | 3 +- .../plugins/panel/radialbar/panelcfg.gen.ts | 6 +- 23 files changed, 406 insertions(+), 464 deletions(-) diff --git a/apps/dashboard/pkg/migration/conversion/testdata/input/migrated_dev_dashboards/panel-gauge/v0alpha1.gauge_tests_new.v42.json b/apps/dashboard/pkg/migration/conversion/testdata/input/migrated_dev_dashboards/panel-gauge/v0alpha1.gauge_tests_new.v42.json index 7c7c479199d..091f705ef0b 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/input/migrated_dev_dashboards/panel-gauge/v0alpha1.gauge_tests_new.v42.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/input/migrated_dev_dashboards/panel-gauge/v0alpha1.gauge_tests_new.v42.json @@ -75,10 +75,10 @@ "effects": { "barGlow": false, "centerGlow": false, - "rounded": true, - "spotlight": false, + "gradient": false }, + "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -154,10 +154,10 @@ "effects": { "barGlow": false, "centerGlow": true, - "rounded": true, - "spotlight": false, + "gradient": false }, + "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -233,10 +233,10 @@ "effects": { "barGlow": true, "centerGlow": true, - "rounded": true, - "spotlight": false, + "gradient": false }, + "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -312,10 +312,10 @@ "effects": { "barGlow": true, "centerGlow": true, - "rounded": true, - "spotlight": true, + "gradient": false }, + "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -391,10 +391,10 @@ "effects": { "barGlow": true, "centerGlow": true, - "rounded": true, - "spotlight": true, + "gradient": false }, + "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -470,10 +470,9 @@ "effects": { "barGlow": true, "centerGlow": true, - "rounded": false, - "spotlight": true, "gradient": false }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -549,10 +548,9 @@ "effects": { "barGlow": true, "centerGlow": true, - "rounded": false, - "spotlight": true, "gradient": false }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -641,10 +639,10 @@ "effects": { "barGlow": true, "centerGlow": true, - "rounded": true, - "spotlight": true, + "gradient": false }, + "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -720,10 +718,10 @@ "effects": { "barGlow": true, "centerGlow": true, - "rounded": true, - "spotlight": true, + "gradient": false }, + "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -799,10 +797,10 @@ "effects": { "barGlow": true, "centerGlow": true, - "rounded": true, - "spotlight": true, + "gradient": false }, + "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -878,10 +876,10 @@ "effects": { "barGlow": true, "centerGlow": true, - "rounded": true, - "spotlight": true, + "gradient": false }, + "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -974,10 +972,9 @@ "effects": { "barGlow": false, "centerGlow": false, - "rounded": false, - "spotlight": false, "gradient": false }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -1053,10 +1050,9 @@ "effects": { "barGlow": false, "centerGlow": false, - "rounded": false, - "spotlight": false, "gradient": false }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -1132,10 +1128,9 @@ "effects": { "barGlow": false, "centerGlow": false, - "rounded": false, - "spotlight": false, "gradient": true }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -1211,10 +1206,9 @@ "effects": { "barGlow": false, "centerGlow": false, - "rounded": false, - "spotlight": false, "gradient": false }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -1290,10 +1284,9 @@ "effects": { "barGlow": false, "centerGlow": false, - "rounded": false, - "spotlight": false, "gradient": false }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -1386,10 +1379,9 @@ "effects": { "barGlow": false, "centerGlow": false, - "rounded": false, - "spotlight": false, "gradient": true }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -1469,10 +1461,9 @@ "effects": { "barGlow": false, "centerGlow": false, - "rounded": false, - "spotlight": false, "gradient": true }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -1552,10 +1543,9 @@ "effects": { "barGlow": false, "centerGlow": false, - "rounded": false, - "spotlight": false, "gradient": true }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -1644,10 +1634,10 @@ "effects": { "barGlow": true, "centerGlow": true, - "rounded": true, - "spotlight": true, + "gradient": true }, + "barShape": "rounded", "glow": "both", "orientation": "auto", "reduceOptions": { @@ -1662,8 +1652,7 @@ "shape": "circle", "showThresholdLabels": false, "showThresholdMarkers": false, - "sparkline": false, - "spotlight": true + "sparkline": false }, "pluginVersion": "13.0.0-pre", "targets": [ @@ -1730,10 +1719,10 @@ "effects": { "barGlow": true, "centerGlow": true, - "rounded": true, - "spotlight": true, + "gradient": true }, + "barShape": "rounded", "glow": "both", "orientation": "auto", "reduceOptions": { @@ -1748,8 +1737,7 @@ "shape": "gauge", "showThresholdLabels": false, "showThresholdMarkers": false, - "sparkline": true, - "spotlight": true + "sparkline": true }, "pluginVersion": "13.0.0-pre", "targets": [ @@ -1830,10 +1818,10 @@ "effects": { "barGlow": true, "centerGlow": true, - "rounded": true, - "spotlight": true, + "gradient": true }, + "barShape": "rounded", "glow": "both", "orientation": "auto", "reduceOptions": { @@ -1848,8 +1836,7 @@ "shape": "circle", "showThresholdLabels": false, "showThresholdMarkers": false, - "sparkline": false, - "spotlight": true + "sparkline": false }, "pluginVersion": "13.0.0-pre", "targets": [ @@ -1917,9 +1904,6 @@ "effects": { "barGlow": true, "centerGlow": true, - "rounded": true, - "sparkline": false, - "spotlight": true, "gradient": true }, "glow": "both", @@ -1934,10 +1918,10 @@ "segmentCount": 12, "segmentSpacing": 0.3, "shape": "circle", + "barShape": "rounded", "showThresholdLabels": false, "showThresholdMarkers": false, - "sparkline": false, - "spotlight": true + "sparkline": false }, "pluginVersion": "13.0.0-pre", "targets": [ @@ -2004,10 +1988,10 @@ "effects": { "barGlow": true, "centerGlow": true, - "rounded": true, - "spotlight": true, + "gradient": true }, + "barShape": "rounded", "glow": "both", "orientation": "auto", "reduceOptions": { @@ -2022,8 +2006,7 @@ "shape": "circle", "showThresholdLabels": false, "showThresholdMarkers": false, - "sparkline": false, - "spotlight": true + "sparkline": false }, "pluginVersion": "13.0.0-pre", "targets": [ @@ -2090,10 +2073,10 @@ "effects": { "barGlow": true, "centerGlow": true, - "rounded": true, - "spotlight": true, + "gradient": true }, + "barShape": "rounded", "glow": "both", "orientation": "auto", "reduceOptions": { @@ -2108,8 +2091,7 @@ "shape": "circle", "showThresholdLabels": false, "showThresholdMarkers": false, - "sparkline": false, - "spotlight": true + "sparkline": false }, "pluginVersion": "13.0.0-pre", "targets": [ diff --git a/apps/dashboard/pkg/migration/conversion/testdata/input/migrated_dev_dashboards/panel-gauge/v0alpha1.gauge_tests_old_to_new.v42.json b/apps/dashboard/pkg/migration/conversion/testdata/input/migrated_dev_dashboards/panel-gauge/v0alpha1.gauge_tests_old_to_new.v42.json index a3de6df336a..885966627cd 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/input/migrated_dev_dashboards/panel-gauge/v0alpha1.gauge_tests_old_to_new.v42.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/input/migrated_dev_dashboards/panel-gauge/v0alpha1.gauge_tests_old_to_new.v42.json @@ -955,8 +955,6 @@ "effects": { "barGlow": false, "centerGlow": false, - "rounded": false, - "spotlight": false, "gradient": false }, "orientation": "auto", @@ -969,6 +967,7 @@ }, "segmentCount": 70, "segmentSpacing": 0.3, + "barShape": "flat", "shape": "gauge", "showThresholdLabels": false, "showThresholdMarkers": true, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-gauge/v0alpha1.gauge_tests_old_to_new.v42.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-gauge/v0alpha1.gauge_tests_old_to_new.v42.v1beta1.json index 959f0193ad6..f39e18c77ef 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-gauge/v0alpha1.gauge_tests_old_to_new.v42.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-gauge/v0alpha1.gauge_tests_old_to_new.v42.v1beta1.json @@ -961,9 +961,7 @@ "effects": { "barGlow": false, "centerGlow": false, - "gradient": false, - "rounded": false, - "spotlight": false + "gradient": false }, "orientation": "auto", "reduceOptions": { @@ -976,6 +974,7 @@ "segmentCount": 70, "segmentSpacing": 0.3, "shape": "gauge", + "barShape": "flat", "showThresholdLabels": false, "showThresholdMarkers": true, "sparkline": false @@ -1175,4 +1174,4 @@ "storedVersion": "v0alpha1" } } -} \ No newline at end of file +} diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-gauge/v0alpha1.gauge_tests_old_to_new.v42.v2alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-gauge/v0alpha1.gauge_tests_old_to_new.v42.v2alpha1.json index 66b29e88d13..c1134c2f9d1 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-gauge/v0alpha1.gauge_tests_old_to_new.v42.v2alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-gauge/v0alpha1.gauge_tests_old_to_new.v42.v2alpha1.json @@ -864,9 +864,7 @@ "effects": { "barGlow": false, "centerGlow": false, - "gradient": false, - "rounded": false, - "spotlight": false + "gradient": false }, "orientation": "auto", "reduceOptions": { @@ -879,6 +877,7 @@ "segmentCount": 70, "segmentSpacing": 0.3, "shape": "gauge", + "barShape": "flat", "showThresholdLabels": false, "showThresholdMarkers": true, "sparkline": false @@ -1620,4 +1619,4 @@ "storedVersion": "v0alpha1" } } -} \ No newline at end of file +} diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-gauge/v0alpha1.gauge_tests_old_to_new.v42.v2beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-gauge/v0alpha1.gauge_tests_old_to_new.v42.v2beta1.json index b870d0a91ad..82705e975c2 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-gauge/v0alpha1.gauge_tests_old_to_new.v42.v2beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-gauge/v0alpha1.gauge_tests_old_to_new.v42.v2beta1.json @@ -901,9 +901,7 @@ "effects": { "barGlow": false, "centerGlow": false, - "gradient": false, - "rounded": false, - "spotlight": false + "gradient": false }, "orientation": "auto", "reduceOptions": { @@ -916,6 +914,7 @@ "segmentCount": 70, "segmentSpacing": 0.3, "shape": "gauge", + "barShape": "flat", "showThresholdLabels": false, "showThresholdMarkers": true, "sparkline": false @@ -1672,4 +1671,4 @@ "storedVersion": "v0alpha1" } } -} \ No newline at end of file +} diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-gauge/gauge_tests_new.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-gauge/gauge_tests_new.v42.json index 9f8cf76c9f7..c4cdddc4ac7 100644 --- a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-gauge/gauge_tests_new.v42.json +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-gauge/gauge_tests_new.v42.json @@ -75,10 +75,9 @@ "effects": { "barGlow": false, "centerGlow": false, - "rounded": true, - "spotlight": false, "gradient": false }, + "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -154,10 +153,9 @@ "effects": { "barGlow": false, "centerGlow": true, - "rounded": true, - "spotlight": false, "gradient": false }, + "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -233,10 +231,9 @@ "effects": { "barGlow": true, "centerGlow": true, - "rounded": true, - "spotlight": false, "gradient": false }, + "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -312,10 +309,9 @@ "effects": { "barGlow": true, "centerGlow": true, - "rounded": true, - "spotlight": true, "gradient": false }, + "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -391,10 +387,9 @@ "effects": { "barGlow": true, "centerGlow": true, - "rounded": true, - "spotlight": true, "gradient": false }, + "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -470,10 +465,9 @@ "effects": { "barGlow": true, "centerGlow": true, - "rounded": false, - "spotlight": true, "gradient": false }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -549,10 +543,9 @@ "effects": { "barGlow": true, "centerGlow": true, - "rounded": false, - "spotlight": true, "gradient": false }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -641,10 +634,9 @@ "effects": { "barGlow": true, "centerGlow": true, - "rounded": true, - "spotlight": true, "gradient": false }, + "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -720,10 +712,9 @@ "effects": { "barGlow": true, "centerGlow": true, - "rounded": true, - "spotlight": true, "gradient": false }, + "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -799,10 +790,9 @@ "effects": { "barGlow": true, "centerGlow": true, - "rounded": true, - "spotlight": true, "gradient": false }, + "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -878,10 +868,9 @@ "effects": { "barGlow": true, "centerGlow": true, - "rounded": true, - "spotlight": true, "gradient": false }, + "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -974,10 +963,9 @@ "effects": { "barGlow": false, "centerGlow": false, - "rounded": false, - "spotlight": false, "gradient": false }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -1053,10 +1041,9 @@ "effects": { "barGlow": false, "centerGlow": false, - "rounded": false, - "spotlight": false, "gradient": false }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -1132,10 +1119,9 @@ "effects": { "barGlow": false, "centerGlow": false, - "rounded": false, - "spotlight": false, "gradient": true }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -1211,10 +1197,9 @@ "effects": { "barGlow": false, "centerGlow": false, - "rounded": false, - "spotlight": false, "gradient": false }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -1290,10 +1275,9 @@ "effects": { "barGlow": false, "centerGlow": false, - "rounded": false, - "spotlight": false, "gradient": false }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -1386,10 +1370,9 @@ "effects": { "barGlow": false, "centerGlow": false, - "rounded": false, - "spotlight": false, "gradient": true }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -1469,10 +1452,9 @@ "effects": { "barGlow": false, "centerGlow": false, - "rounded": false, - "spotlight": false, "gradient": true }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -1552,10 +1534,9 @@ "effects": { "barGlow": false, "centerGlow": false, - "rounded": false, - "spotlight": false, "gradient": true }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -1643,10 +1624,9 @@ "effects": { "barGlow": true, "centerGlow": true, - "rounded": true, - "spotlight": true, "gradient": true }, + "barShape": "rounded", "glow": "both", "orientation": "auto", "reduceOptions": { @@ -1661,8 +1641,7 @@ "shape": "circle", "showThresholdLabels": false, "showThresholdMarkers": false, - "sparkline": false, - "spotlight": true + "sparkline": false }, "pluginVersion": "13.0.0-pre", "targets": [ @@ -1727,10 +1706,9 @@ "effects": { "barGlow": true, "centerGlow": true, - "rounded": true, - "spotlight": true, "gradient": true }, + "barShape": "rounded", "glow": "both", "orientation": "auto", "reduceOptions": { @@ -1745,8 +1723,7 @@ "shape": "gauge", "showThresholdLabels": false, "showThresholdMarkers": false, - "sparkline": true, - "spotlight": true + "sparkline": true }, "pluginVersion": "13.0.0-pre", "targets": [ @@ -1825,10 +1802,9 @@ "effects": { "barGlow": true, "centerGlow": true, - "rounded": true, - "spotlight": true, "gradient": true }, + "barShape": "rounded", "glow": "both", "orientation": "auto", "reduceOptions": { @@ -1843,8 +1819,7 @@ "shape": "circle", "showThresholdLabels": false, "showThresholdMarkers": false, - "sparkline": false, - "spotlight": true + "sparkline": false }, "pluginVersion": "13.0.0-pre", "targets": [ @@ -1910,10 +1885,9 @@ "effects": { "barGlow": true, "centerGlow": true, - "rounded": true, - "spotlight": true, "gradient": true }, + "barShape": "rounded", "glow": "both", "orientation": "auto", "reduceOptions": { @@ -1928,8 +1902,7 @@ "shape": "circle", "showThresholdLabels": false, "showThresholdMarkers": false, - "sparkline": false, - "spotlight": true + "sparkline": false }, "pluginVersion": "13.0.0-pre", "targets": [ @@ -1994,10 +1967,9 @@ "effects": { "barGlow": true, "centerGlow": true, - "rounded": true, - "spotlight": true, "gradient": true }, + "barShape": "rounded", "glow": "both", "orientation": "auto", "reduceOptions": { @@ -2012,8 +1984,7 @@ "shape": "circle", "showThresholdLabels": false, "showThresholdMarkers": false, - "sparkline": false, - "spotlight": true + "sparkline": false }, "pluginVersion": "13.0.0-pre", "targets": [ @@ -2078,10 +2049,9 @@ "effects": { "barGlow": true, "centerGlow": true, - "rounded": true, - "spotlight": true, "gradient": true }, + "barShape": "rounded", "glow": "both", "orientation": "auto", "reduceOptions": { @@ -2096,8 +2066,7 @@ "shape": "circle", "showThresholdLabels": false, "showThresholdMarkers": false, - "sparkline": false, - "spotlight": true + "sparkline": false }, "pluginVersion": "13.0.0-pre", "targets": [ @@ -2166,10 +2135,9 @@ "effects": { "barGlow": false, "centerGlow": false, - "gradient": true, - "rounded": false, - "spotlight": false + "gradient": true }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": ["lastNotNull"], @@ -2232,10 +2200,9 @@ "effects": { "barGlow": false, "centerGlow": false, - "gradient": true, - "rounded": false, - "spotlight": false + "gradient": true }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": ["lastNotNull"], diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-gauge/gauge_tests_old_to_new.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-gauge/gauge_tests_old_to_new.v42.json index a3de6df336a..446ba107f19 100644 --- a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-gauge/gauge_tests_old_to_new.v42.json +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-gauge/gauge_tests_old_to_new.v42.json @@ -955,8 +955,6 @@ "effects": { "barGlow": false, "centerGlow": false, - "rounded": false, - "spotlight": false, "gradient": false }, "orientation": "auto", @@ -970,6 +968,7 @@ "segmentCount": 70, "segmentSpacing": 0.3, "shape": "gauge", + "barShape": "flat", "showThresholdLabels": false, "showThresholdMarkers": true, "sparkline": false diff --git a/devenv/dev-dashboards/panel-gauge/gauge_tests_new.json b/devenv/dev-dashboards/panel-gauge/gauge_tests_new.json index b3c47c9aa7a..530dcf8d63f 100644 --- a/devenv/dev-dashboards/panel-gauge/gauge_tests_new.json +++ b/devenv/dev-dashboards/panel-gauge/gauge_tests_new.json @@ -75,10 +75,9 @@ "effects": { "barGlow": false, "centerGlow": false, - "gradient": false, - "rounded": true, - "spotlight": false + "gradient": false }, + "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": ["lastNotNull"], @@ -152,10 +151,9 @@ "effects": { "barGlow": false, "centerGlow": true, - "gradient": false, - "rounded": true, - "spotlight": false + "gradient": false }, + "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": ["lastNotNull"], @@ -229,10 +227,9 @@ "effects": { "barGlow": true, "centerGlow": true, - "gradient": false, - "rounded": true, - "spotlight": false + "gradient": false }, + "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": ["lastNotNull"], @@ -306,10 +303,9 @@ "effects": { "barGlow": true, "centerGlow": true, - "gradient": false, - "rounded": true, - "spotlight": true + "gradient": false }, + "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": ["lastNotNull"], @@ -383,10 +379,9 @@ "effects": { "barGlow": true, "centerGlow": true, - "gradient": false, - "rounded": true, - "spotlight": true + "gradient": false }, + "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": ["lastNotNull"], @@ -460,10 +455,9 @@ "effects": { "barGlow": true, "centerGlow": true, - "gradient": false, - "rounded": false, - "spotlight": true + "gradient": false }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": ["lastNotNull"], @@ -537,10 +531,9 @@ "effects": { "barGlow": true, "centerGlow": true, - "gradient": false, - "rounded": false, - "spotlight": true + "gradient": false }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": ["lastNotNull"], @@ -627,10 +620,9 @@ "effects": { "barGlow": true, "centerGlow": true, - "gradient": false, - "rounded": true, - "spotlight": true + "gradient": false }, + "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": ["lastNotNull"], @@ -704,10 +696,9 @@ "effects": { "barGlow": true, "centerGlow": true, - "gradient": false, - "rounded": true, - "spotlight": true + "gradient": false }, + "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": ["lastNotNull"], @@ -781,10 +772,9 @@ "effects": { "barGlow": true, "centerGlow": true, - "gradient": false, - "rounded": true, - "spotlight": true + "gradient": false }, + "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": ["lastNotNull"], @@ -858,10 +848,9 @@ "effects": { "barGlow": true, "centerGlow": true, - "gradient": false, - "rounded": true, - "spotlight": true + "gradient": false }, + "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": ["lastNotNull"], @@ -952,10 +941,9 @@ "effects": { "barGlow": false, "centerGlow": false, - "gradient": false, - "rounded": false, - "spotlight": false + "gradient": false }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": ["lastNotNull"], @@ -1029,10 +1017,9 @@ "effects": { "barGlow": false, "centerGlow": false, - "gradient": false, - "rounded": false, - "spotlight": false + "gradient": false }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": ["lastNotNull"], @@ -1106,10 +1093,9 @@ "effects": { "barGlow": false, "centerGlow": false, - "gradient": true, - "rounded": false, - "spotlight": false + "gradient": true }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": ["lastNotNull"], @@ -1183,10 +1169,9 @@ "effects": { "barGlow": false, "centerGlow": false, - "gradient": false, - "rounded": false, - "spotlight": false + "gradient": false }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": ["lastNotNull"], @@ -1260,10 +1245,9 @@ "effects": { "barGlow": false, "centerGlow": false, - "gradient": false, - "rounded": false, - "spotlight": false + "gradient": false }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": ["lastNotNull"], @@ -1354,10 +1338,9 @@ "effects": { "barGlow": false, "centerGlow": false, - "gradient": true, - "rounded": false, - "spotlight": false + "gradient": true }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": ["lastNotNull"], @@ -1435,10 +1418,9 @@ "effects": { "barGlow": false, "centerGlow": false, - "gradient": true, - "rounded": false, - "spotlight": false + "gradient": true }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": ["lastNotNull"], @@ -1516,10 +1498,9 @@ "effects": { "barGlow": false, "centerGlow": false, - "gradient": true, - "rounded": false, - "spotlight": false + "gradient": true }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": ["lastNotNull"], @@ -1605,10 +1586,9 @@ "effects": { "barGlow": true, "centerGlow": true, - "gradient": true, - "rounded": true, - "spotlight": true + "gradient": true }, + "barShape": "rounded", "glow": "both", "orientation": "auto", "reduceOptions": { @@ -1621,8 +1601,7 @@ "shape": "circle", "showThresholdLabels": false, "showThresholdMarkers": false, - "sparkline": false, - "spotlight": true + "sparkline": false }, "pluginVersion": "13.0.0-pre", "targets": [ @@ -1687,10 +1666,9 @@ "effects": { "barGlow": true, "centerGlow": true, - "gradient": true, - "rounded": true, - "spotlight": true + "gradient": true }, + "barShape": "rounded", "glow": "both", "orientation": "auto", "reduceOptions": { @@ -1703,8 +1681,7 @@ "shape": "gauge", "showThresholdLabels": false, "showThresholdMarkers": false, - "sparkline": true, - "spotlight": true + "sparkline": true }, "pluginVersion": "13.0.0-pre", "targets": [ @@ -1783,10 +1760,9 @@ "effects": { "barGlow": true, "centerGlow": true, - "gradient": true, - "rounded": true, - "spotlight": true + "gradient": true }, + "barShape": "rounded", "glow": "both", "orientation": "auto", "reduceOptions": { @@ -1799,8 +1775,7 @@ "shape": "circle", "showThresholdLabels": false, "showThresholdMarkers": false, - "sparkline": false, - "spotlight": true + "sparkline": false }, "pluginVersion": "13.0.0-pre", "targets": [ @@ -1866,10 +1841,9 @@ "effects": { "barGlow": true, "centerGlow": true, - "gradient": true, - "rounded": true, - "spotlight": true + "gradient": true }, + "barShape": "rounded", "glow": "both", "orientation": "auto", "reduceOptions": { @@ -1882,8 +1856,7 @@ "shape": "circle", "showThresholdLabels": false, "showThresholdMarkers": false, - "sparkline": false, - "spotlight": true + "sparkline": false }, "pluginVersion": "13.0.0-pre", "targets": [ @@ -1948,10 +1921,9 @@ "effects": { "barGlow": true, "centerGlow": true, - "gradient": true, - "rounded": true, - "spotlight": true + "gradient": true }, + "barShape": "rounded", "glow": "both", "orientation": "auto", "reduceOptions": { @@ -1964,8 +1936,7 @@ "shape": "circle", "showThresholdLabels": false, "showThresholdMarkers": false, - "sparkline": false, - "spotlight": true + "sparkline": false }, "pluginVersion": "13.0.0-pre", "targets": [ @@ -2030,10 +2001,9 @@ "effects": { "barGlow": true, "centerGlow": true, - "gradient": true, - "rounded": true, - "spotlight": true + "gradient": true }, + "barShape": "rounded", "glow": "both", "orientation": "auto", "reduceOptions": { @@ -2046,8 +2016,7 @@ "shape": "circle", "showThresholdLabels": false, "showThresholdMarkers": false, - "sparkline": false, - "spotlight": true + "sparkline": false }, "pluginVersion": "13.0.0-pre", "targets": [ @@ -2116,10 +2085,9 @@ "effects": { "barGlow": false, "centerGlow": false, - "gradient": true, - "rounded": false, - "spotlight": false + "gradient": true }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": ["lastNotNull"], @@ -2182,10 +2150,9 @@ "effects": { "barGlow": false, "centerGlow": false, - "gradient": true, - "rounded": false, - "spotlight": false + "gradient": true }, + "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": ["lastNotNull"], diff --git a/devenv/dev-dashboards/panel-gauge/gauge_tests_old_to_new.json b/devenv/dev-dashboards/panel-gauge/gauge_tests_old_to_new.json index b071ddff802..bb8d5309116 100644 --- a/devenv/dev-dashboards/panel-gauge/gauge_tests_old_to_new.json +++ b/devenv/dev-dashboards/panel-gauge/gauge_tests_old_to_new.json @@ -953,11 +953,10 @@ "sparkline": false, "showThresholdMarkers": true, "showThresholdLabels": false, + "barShape": "flat", "effects": { "barGlow": false, "centerGlow": false, - "rounded": false, - "spotlight": false, "gradient": false } } diff --git a/packages/grafana-data/src/themes/colorManipulator.test.ts b/packages/grafana-data/src/themes/colorManipulator.test.ts index 5619ddc4928..b003e4baf63 100644 --- a/packages/grafana-data/src/themes/colorManipulator.test.ts +++ b/packages/grafana-data/src/themes/colorManipulator.test.ts @@ -12,6 +12,7 @@ import { lighten, asRgbString, onBackground, + colorAtGradientPercent, } from './colorManipulator'; describe('utils/colorManipulator', () => { @@ -436,4 +437,49 @@ describe('utils/colorManipulator', () => { expect(onBackground('rgba(0,0,255,1)', 'rgba(0,0,0,0.5)').toRgbString()).toBe('rgb(0, 0, 255)'); }); }); + + describe('colorAtGradientPercent', () => { + it('should calculate the color at a given percent in a gradient of two colors', () => { + const gradient = [ + { color: '#ff0000', percent: 0 }, + { color: '#0000ff', percent: 1 }, + ]; + expect(colorAtGradientPercent(gradient, 0).toHexString()).toBe('#ff0000'); + expect(colorAtGradientPercent(gradient, 0.25).toHexString()).toBe('#bf0040'); + expect(colorAtGradientPercent(gradient, 0.5).toHexString()).toBe('#800080'); + expect(colorAtGradientPercent(gradient, 0.75).toHexString()).toBe('#4000bf'); + expect(colorAtGradientPercent(gradient, 1).toHexString()).toBe('#0000ff'); + }); + + it('should calculate the color at a given percent in a gradient of multiple colors', () => { + const gradient = [ + { color: '#ff0000', percent: 0 }, + { color: '#00ff00', percent: 0.5 }, + { color: '#0000ff', percent: 1 }, + ]; + expect(colorAtGradientPercent(gradient, 0).toHexString()).toBe('#ff0000'); + expect(colorAtGradientPercent(gradient, 0.25).toHexString()).toBe('#808000'); + expect(colorAtGradientPercent(gradient, 0.5).toHexString()).toBe('#00ff00'); + expect(colorAtGradientPercent(gradient, 0.75).toHexString()).toBe('#008080'); + expect(colorAtGradientPercent(gradient, 1).toHexString()).toBe('#0000ff'); + }); + + it('should not throw an error when percent is outside 0-1 range', () => { + const gradient = [ + { color: '#ff0000', percent: 0 }, + { color: '#0000ff', percent: 1 }, + ]; + expect(colorAtGradientPercent(gradient, -0.5).toHexString()).toBe('#ff0000'); + expect(colorAtGradientPercent(gradient, 1.5).toHexString()).toBe('#0000ff'); + }); + + it('should throw an error when less than two stops are provided', () => { + expect(() => { + colorAtGradientPercent([], 0.5); + }).toThrow('colorAtGradientPercent requires at least two color stops'); + expect(() => { + colorAtGradientPercent([{ color: '#ff0000', percent: 0 }], 0.5); + }).toThrow('colorAtGradientPercent requires at least two color stops'); + }); + }); }); diff --git a/packages/grafana-data/src/themes/colorManipulator.ts b/packages/grafana-data/src/themes/colorManipulator.ts index eccb661b7d8..42bbf454b1a 100644 --- a/packages/grafana-data/src/themes/colorManipulator.ts +++ b/packages/grafana-data/src/themes/colorManipulator.ts @@ -392,6 +392,55 @@ export const onBackground = ( }); }; +/** + * Given color stops (each with a color and percentage 0..1) returns the color at a given percentage. + * Uses tinycolor.mix for interpolation. + * @params stops - array of color stops (percentages 0..1) + * @params percent - percentage 0..1 + * @returns color at the given percentage + */ +export function colorAtGradientPercent( + stops: Array<{ color: string; percent: number }>, + percent: number +): tinycolor.Instance { + if (!stops || stops.length < 2) { + throw new Error('colorAtGradientPercent requires at least two color stops'); + } + + // normalize and sort stops by percent + const sorted = stops + .map((s) => ({ color: s.color, percent: clamp(s.percent, 0, 1) })) + .sort((a, b) => a.percent - b.percent); + + // percent outside range + if (percent <= sorted[0].percent) { + return tinycolor(sorted[0].color); + } + if (percent >= sorted[sorted.length - 1].percent) { + return tinycolor(sorted[sorted.length - 1].color); + } + + // find surrounding stops + let left = sorted[0]; + let right = sorted[sorted.length - 1]; + for (let i = 1; i < sorted.length; i++) { + if (percent <= sorted[i].percent) { + left = sorted[i - 1]; + right = sorted[i]; + break; + } + } + + const range = right.percent - left.percent; + const t = range === 0 ? 0 : (percent - left.percent) / range; // 0..1 + + // tinycolor.mix expects amount as percentage of the second color + const mixed = tinycolor.mix(left.color, right.color, t * 100); + + // return hex6 if opaque, hex8 if has alpha + return mixed; +} + interface DecomposeColor { type: string; values: any; @@ -414,4 +463,5 @@ export const colorManipulator = { darken, lighten, onBackground, + colorAtGradientPercent, }; diff --git a/packages/grafana-schema/src/raw/composable/newgauge/panelcfg/x/NewGaugePanelCfg_types.gen.ts b/packages/grafana-schema/src/raw/composable/newgauge/panelcfg/x/NewGaugePanelCfg_types.gen.ts index aedc041cf71..3c9853535e8 100644 --- a/packages/grafana-schema/src/raw/composable/newgauge/panelcfg/x/NewGaugePanelCfg_types.gen.ts +++ b/packages/grafana-schema/src/raw/composable/newgauge/panelcfg/x/NewGaugePanelCfg_types.gen.ts @@ -16,19 +16,16 @@ export interface GaugePanelEffects { barGlow?: boolean; centerGlow?: boolean; gradient?: boolean; - rounded?: boolean; - spotlight?: boolean; } export const defaultGaugePanelEffects: Partial = { barGlow: false, centerGlow: false, gradient: true, - rounded: false, - spotlight: false, }; export interface Options extends common.SingleStatBaseOptions { + barShape: ('flat' | 'rounded'); barWidthFactor: number; effects: GaugePanelEffects; segmentCount: number; @@ -40,6 +37,7 @@ export interface Options extends common.SingleStatBaseOptions { } export const defaultOptions: Partial = { + barShape: 'flat', barWidthFactor: 0.5, effects: {}, segmentCount: 1, diff --git a/packages/grafana-ui/src/components/RadialGauge/RadialArcPath.tsx b/packages/grafana-ui/src/components/RadialGauge/RadialArcPath.tsx index d9a79143c9b..a6278294029 100644 --- a/packages/grafana-ui/src/components/RadialGauge/RadialArcPath.tsx +++ b/packages/grafana-ui/src/components/RadialGauge/RadialArcPath.tsx @@ -8,16 +8,20 @@ export interface RadialArcPathPropsBase { arcLengthDeg: number; roundedBars?: boolean; showGuideDots?: boolean; - guideDotColor?: string; + guideDotStartColor?: string; + guideDotEndColor?: string; } interface RadialArcPathPropsWithGuideDot extends RadialArcPathPropsBase { showGuideDots: true; - guideDotColor: string; + guideDotStartColor: string; + guideDotEndColor: string; } type RadialArcPathProps = RadialArcPathPropsBase | RadialArcPathPropsWithGuideDot; +const MAX_DOT_RADIUS = 8; + export function RadialArcPath({ startAngle: angle, dimensions, @@ -26,7 +30,8 @@ export function RadialArcPath({ arcLengthDeg, roundedBars, showGuideDots, - guideDotColor, + guideDotStartColor, + guideDotEndColor, }: RadialArcPathProps) { const { radius, centerX, centerY, barWidth } = dimensions; @@ -46,7 +51,7 @@ export function RadialArcPath({ const largeArc = arcLengthDeg > 180 ? 1 : 0; const path = ['M', x1, y1, 'A', radius, radius, 0, largeArc, 1, x2, y2].join(' '); - const dotRadius = (barWidth / 2) * 0.3; + const dotRadius = Math.min((barWidth / 2) * 0.4, MAX_DOT_RADIUS); return ( <> @@ -63,8 +68,8 @@ export function RadialArcPath({ /> {showGuideDots && ( <> - {arcLengthDeg > 5 && } - + {arcLengthDeg > 5 && } + )} diff --git a/packages/grafana-ui/src/components/RadialGauge/RadialBar.tsx b/packages/grafana-ui/src/components/RadialGauge/RadialBar.tsx index 2d9d0fbe80d..c5552ad5bab 100644 --- a/packages/grafana-ui/src/components/RadialGauge/RadialBar.tsx +++ b/packages/grafana-ui/src/components/RadialGauge/RadialBar.tsx @@ -1,10 +1,8 @@ -import { GrafanaTheme2 } from '@grafana/data'; - import { useTheme2 } from '../../themes/ThemeContext'; import { RadialArcPath } from './RadialArcPath'; import { RadialColorDefs } from './RadialColorDefs'; -import { GaugeDimensions, toRad } from './utils'; +import { GaugeDimensions } from './utils'; export interface RadialBarProps { dimensions: GaugeDimensions; @@ -13,7 +11,6 @@ export interface RadialBarProps { angle: number; startAngle: number; roundedBars?: boolean; - spotlightStroke: string; glowFilter?: string; } export function RadialBar({ @@ -23,10 +20,10 @@ export function RadialBar({ angle, startAngle, roundedBars, - spotlightStroke, glowFilter, }: RadialBarProps) { const theme = useTheme2(); + const [startDotColor, endDotColor] = colorDefs.getGuideDotColors(); return ( <> @@ -48,52 +45,11 @@ export function RadialBar({ roundedBars={roundedBars} glowFilter={glowFilter} showGuideDots={roundedBars} - guideDotColor={colorDefs.getGuideDotColor()} + guideDotStartColor={startDotColor} + guideDotEndColor={endDotColor} /> - {spotlightStroke && angle > 8 && ( - - )} {colorDefs.getDefs()} ); } - -interface SpotlightEffectProps { - dimensions: GaugeDimensions; - angle: number; - glowFilter?: string; - spotlightStroke: string; - theme: GrafanaTheme2; - roundedBars?: boolean; -} - -function SpotlightSquareEffect({ dimensions, angle, glowFilter, spotlightStroke, roundedBars }: SpotlightEffectProps) { - const { radius, centerX, centerY, barWidth } = dimensions; - - const angleRadian = toRad(angle); - const x1 = centerX + radius * Math.cos(angleRadian - 0.2); - const y1 = centerY + radius * Math.sin(angleRadian - 0.2); - const x2 = centerX + radius * Math.cos(angleRadian); - const y2 = centerY + radius * Math.sin(angleRadian); - - const path = ['M', x1, y1, 'A', radius, radius, 0, 0, 1, x2, y2].join(' '); - - return ( - - ); -} diff --git a/packages/grafana-ui/src/components/RadialGauge/RadialColorDefs.tsx b/packages/grafana-ui/src/components/RadialGauge/RadialColorDefs.tsx index 9ce23cc9a38..abef48720b4 100644 --- a/packages/grafana-ui/src/components/RadialGauge/RadialColorDefs.tsx +++ b/packages/grafana-ui/src/components/RadialGauge/RadialColorDefs.tsx @@ -1,6 +1,13 @@ import tinycolor from 'tinycolor2'; -import { DisplayProcessor, FALLBACK_COLOR, FieldDisplay, getFieldColorMode, GrafanaTheme2 } from '@grafana/data'; +import { + colorManipulator, + DisplayProcessor, + FALLBACK_COLOR, + FieldDisplay, + getFieldColorMode, + GrafanaTheme2, +} from '@grafana/data'; import { RadialGradientMode, RadialShape } from './RadialGauge'; import { GaugeDimensions } from './utils'; @@ -15,6 +22,13 @@ export interface RadialColorDefsOptions { displayProcessor: DisplayProcessor; } +const CONTRAST_THRESHOLD_MAX = 7.5; +const getGuideDotColor = (color: string): string => { + const darkColor = '#111217'; // gray05 + const lightColor = '#fbfbfb'; // gray90 + return colorManipulator.getContrastRatio(darkColor, color) >= CONTRAST_THRESHOLD_MAX ? darkColor : lightColor; +}; + export class RadialColorDefs { private colorToIds: Record = {}; private defs: React.ReactNode[] = []; @@ -48,17 +62,17 @@ export class RadialColorDefs { const colorMode = getFieldColorMode(colorModeId); const valuePercent = fieldDisplay.display.percent ?? 0; + const gradientStops = this.getGradient(); + const stops = gradientStops.map((stop, i) => ( + + )); + // Handle continusous color modes first // If it's a segment color we don't want to do continuous gradients if (colorMode.isContinuous && colorMode.getColors && !forSegment) { - const colors = colorMode.getColors(theme); - const count = colors.length; - this.defs.push( - - {colors.map((stopColor, i) => ( - - ))} + + {stops} ); @@ -68,21 +82,9 @@ export class RadialColorDefs { // For value based colors we want to stay more true to the specific color // So a radial gradient that adds a bit of light and shade works best if (colorMode.isByValue) { - const color1 = tinycolor(baseColor).darken(5); - this.defs.push( - - - - + + {stops} ); @@ -91,13 +93,11 @@ export class RadialColorDefs { // For fixed / palette based color scales we can create a more fun // hue and light based linear gradient that we rotate/move with the value - const x2 = shape === 'circle' ? 0 : dimensions.centerX + dimensions.radius; const y2 = shape === 'circle' ? dimensions.centerY + dimensions.radius : 0; - const color1 = tinycolor(baseColor).spin(-20).darken(5); - const color2 = tinycolor(baseColor).saturate(20).spin(20).brighten(10); // this makes it so the gradient is always brightest at the current value + // this makes the point color math much more annoying so it's currently disabled. const transform = shape === 'circle' ? `rotate(${360 * valuePercent - 180} ${dimensions.centerX} ${dimensions.centerY})` @@ -114,31 +114,95 @@ export class RadialColorDefs { gradientUnits="userSpaceOnUse" gradientTransform={transform} > - {theme.isDark ? ( - <> - - - - ) : ( - <> - - - - )} + {stops} ); return returnColor; } - getMainBarColor(): string { - return this.getColor(this.options.fieldDisplay.display.color ?? FALLBACK_COLOR); + getFieldBaseColor(): string { + return this.options.fieldDisplay.display.color ?? FALLBACK_COLOR; } - getGuideDotColor(): string { - return this.getColor( - this.options.theme.colors.getContrastText(this.options.fieldDisplay.display.color ?? FALLBACK_COLOR) - ); + getMainBarColor(): string { + return this.getColor(this.getFieldBaseColor()); + } + + getGradient(): Array<{ color: string; percent: number }> { + const { gradient, fieldDisplay, theme } = this.options; + const baseColor = this.getFieldBaseColor(); + if (gradient === 'none') { + return [ + { color: baseColor, percent: 0 }, + { color: baseColor, percent: 1 }, + ]; + } + + const colorModeId = fieldDisplay.field.color?.mode; + const colorMode = getFieldColorMode(colorModeId); + + // Handle continusous color modes first + if (colorMode.isContinuous && colorMode.getColors) { + const colors = colorMode.getColors(theme); + return colors.map((color, idx) => ({ color, percent: idx / (colors.length - 1) })); + } else if (colorMode.isByValue) { + // For value based colors we want to stay more true to the specific color + // So a radial gradient that adds a bit of light and shade works best + const darkerColor = tinycolor(baseColor).darken(5); + const lighterColor = tinycolor(baseColor).spin(20).lighten(10); + + const color1 = theme.isDark ? lighterColor : darkerColor; + const color2 = theme.isDark ? darkerColor : lighterColor; + + return [ + { color: color1.toString(), percent: 0 }, + { color: color2.toString(), percent: 0.6 }, + { color: color2.toString(), percent: 1 }, + ]; + } + + // For value based colors we want to stay more true to the specific color + // So a radial gradient that adds a bit of light and shade works best + // we set the highest contrast color second based on the theme. + const darkerColor = tinycolor(baseColor).spin(-20).darken(5); + const lighterColor = tinycolor(baseColor).saturate(20).spin(20).brighten(10); + return theme.isDark + ? [ + { color: darkerColor.darken(10).toString(), percent: 0 }, + { color: lighterColor.lighten(10).toString(), percent: 1 }, + ] + : [ + { color: lighterColor.lighten(10).toString(), percent: 0 }, + { color: darkerColor.toString(), percent: 1 }, + ]; + } + + getGuideDotColors(): [string, string] { + const { fieldDisplay } = this.options; + + const gradient = this.getGradient(); + let valuePercent = fieldDisplay.display.percent ?? 0; + + let startColor = gradient[0].color; + let endColor = gradient[gradient.length - 1].color; + + const colorMode = getFieldColorMode(fieldDisplay.field.color?.mode); + if (colorMode.isContinuous) { + } else if (colorMode.isByValue) { + } else { + } + + // if we have a percentageFilled, use it to get a the correct end color based on where the bar terminates + if (gradient.length >= 2) { + const endColorByPercentage = colorManipulator.colorAtGradientPercent(gradient, valuePercent); + endColor = + endColorByPercentage.getAlpha() === 1 + ? endColorByPercentage.toHexString() + : endColorByPercentage.toHex8String(); + } + + return [getGuideDotColor(startColor), getGuideDotColor(endColor)]; } getDefs(): React.ReactNode[] { diff --git a/packages/grafana-ui/src/components/RadialGauge/RadialGauge.story.tsx b/packages/grafana-ui/src/components/RadialGauge/RadialGauge.story.tsx index c098beda886..79d8b9444e7 100644 --- a/packages/grafana-ui/src/components/RadialGauge/RadialGauge.story.tsx +++ b/packages/grafana-ui/src/components/RadialGauge/RadialGauge.story.tsx @@ -34,7 +34,6 @@ const meta: Meta = { }, args: { barWidthFactor: 0.2, - spotlight: false, glowBar: false, glowCenter: false, sparkline: false, @@ -56,7 +55,6 @@ const meta: Meta = { width: { control: { type: 'range', min: 50, max: 600 } }, height: { control: { type: 'range', min: 50, max: 600 } }, value: { control: { type: 'range', min: 0, max: 110 } }, - spotlight: { control: 'boolean' }, roundedBars: { control: 'boolean' }, sparkline: { control: 'boolean' }, thresholdsBar: { control: 'boolean' }, @@ -133,26 +131,10 @@ export const Examples: StoryFn = (args) => {
Effects
- - - - + + + +
Shape: Gauge & color scale
@@ -185,7 +167,6 @@ export const Examples: StoryFn = (args) => { shape="gauge" gradient="auto" sparkline={true} - spotlight glowBar={true} glowCenter={true} barWidthFactor={0.2} @@ -196,7 +177,6 @@ export const Examples: StoryFn = (args) => { shape="gauge" gradient="auto" sparkline={true} - spotlight glowBar={true} glowCenter={true} barWidthFactor={0.8} @@ -208,7 +188,6 @@ export const Examples: StoryFn = (args) => { width={250} gradient="auto" sparkline={true} - spotlight glowBar={true} glowCenter={true} barWidthFactor={0.2} @@ -220,7 +199,6 @@ export const Examples: StoryFn = (args) => { shape="gauge" gradient="auto" sparkline={true} - spotlight glowBar={true} glowCenter={true} barWidthFactor={0.8} @@ -260,7 +238,6 @@ export const Examples: StoryFn = (args) => { = (args) => { value={args.value ?? 80} width={250} colorScheme={FieldColorModeId.ContinuousGrYlRd} - spotlight shape="gauge" gradient="auto" glowBar={true} @@ -288,7 +264,6 @@ export const Examples: StoryFn = (args) => { gradient="auto" thresholdsBar={true} roundedBars={false} - spotlight glowCenter={true} barWidthFactor={0.7} /> @@ -347,7 +322,6 @@ export const Temp: StoryFn = (args) => { shape="gauge" roundedBars={false} barWidthFactor={0.8} - spotlight /> ); @@ -363,7 +337,6 @@ interface ExampleProps { max?: number; width?: number; height?: number; - spotlight?: boolean; glowBar?: boolean; glowCenter?: boolean; barWidthFactor?: number; @@ -390,7 +363,6 @@ export function RadialGaugeExample({ max = 100, width = 200, height = 200, - spotlight = false, glowBar = false, glowCenter = false, barWidthFactor = 0.4, @@ -480,7 +452,6 @@ export function RadialGaugeExample({ barWidthFactor={barWidthFactor} gradient={gradient} shape={shape} - spotlight={spotlight} glowBar={glowBar} glowCenter={glowCenter} textMode={textMode} diff --git a/packages/grafana-ui/src/components/RadialGauge/RadialGauge.tsx b/packages/grafana-ui/src/components/RadialGauge/RadialGauge.tsx index fadabf8ec72..d20665872c7 100644 --- a/packages/grafana-ui/src/components/RadialGauge/RadialGauge.tsx +++ b/packages/grafana-ui/src/components/RadialGauge/RadialGauge.tsx @@ -21,7 +21,7 @@ import { RadialScaleLabels } from './RadialScaleLabels'; import { RadialSparkline } from './RadialSparkline'; import { RadialText } from './RadialText'; import { ThresholdsBar } from './ThresholdsBar'; -import { GlowGradient, MiddleCircleGlow, SpotlightGradient } from './effects'; +import { GlowGradient, MiddleCircleGlow } from './effects'; import { calculateDimensions, getValueAngleForValue } from './utils'; export interface RadialGaugeProps { @@ -40,8 +40,6 @@ export interface RadialGaugeProps { * Defaults to 0.4 **/ barWidthFactor?: number; - /** Adds a white spotlight for the end position */ - spotlight?: boolean; glowBar?: boolean; glowCenter?: boolean; roundedBars?: boolean; @@ -89,7 +87,6 @@ export function RadialGauge(props: RadialGaugeProps) { shape = 'circle', gradient = 'none', barWidthFactor = 0.4, - spotlight = false, glowBar = false, glowCenter = false, textMode = 'auto', @@ -135,7 +132,6 @@ export function RadialGauge(props: RadialGaugeProps) { ); const displayProcessor = getFieldDisplayProcessor(displayValue); - const spotlightGradientId = `spotlight-${barIndex}-${gaugeId}`; const glowFilterId = `glow-${gaugeId}`; const colorDefs = new RadialColorDefs({ gradient, @@ -147,19 +143,6 @@ export function RadialGauge(props: RadialGaugeProps) { displayProcessor, }); - if (spotlight && theme.isDark) { - defs.push( - - ); - } - if (segmentCount > 1) { graphics.push( ); diff --git a/packages/grafana-ui/src/components/RadialGauge/effects.tsx b/packages/grafana-ui/src/components/RadialGauge/effects.tsx index 354a68a25ba..09bbc46e349 100644 --- a/packages/grafana-ui/src/components/RadialGauge/effects.tsx +++ b/packages/grafana-ui/src/components/RadialGauge/effects.tsx @@ -22,45 +22,6 @@ export function GlowGradient({ id, barWidth }: GlowGradientProps) { ); } -export function SpotlightGradient({ - id, - dimensions, - roundedBars, - angle, - theme, -}: { - id: string; - dimensions: GaugeDimensions; - angle: number; - roundedBars: boolean; - theme: GrafanaTheme2; -}) { - const angleRadian = ((angle - 90) * Math.PI) / 180; - - let x1 = dimensions.centerX + dimensions.radius * Math.cos(angleRadian - 0.2); - let y1 = dimensions.centerY + dimensions.radius * Math.sin(angleRadian - 0.2); - let x2 = dimensions.centerX + dimensions.radius * Math.cos(angleRadian); - let y2 = dimensions.centerY + dimensions.radius * Math.sin(angleRadian); - - if (theme.isLight) { - return ( - - - - - - ); - } - - return ( - - - - {roundedBars && } - - ); -} - export function CenterGlowGradient({ gaugeId, color }: { gaugeId: string; color: string }) { return ( diff --git a/public/app/plugins/panel/radialbar/EffectsEditor.tsx b/public/app/plugins/panel/radialbar/EffectsEditor.tsx index d7a0f03cbc7..a3c26beca90 100644 --- a/public/app/plugins/panel/radialbar/EffectsEditor.tsx +++ b/public/app/plugins/panel/radialbar/EffectsEditor.tsx @@ -44,11 +44,6 @@ export function EffectsEditor(props: StandardEditorProps) { value={!!props.value?.gradient} onChange={(e) => props.onChange({ ...props.value, gradient: e.currentTarget.checked })} /> - props.onChange({ ...props.value, rounded: e.currentTarget.checked })} - /> ) { value={!!props.value?.centerGlow} onChange={(e) => props.onChange({ ...props.value, centerGlow: e.currentTarget.checked })} /> - props.onChange({ ...props.value, spotlight: e.currentTarget.checked })} - /> ); } diff --git a/public/app/plugins/panel/radialbar/RadialBarPanel.tsx b/public/app/plugins/panel/radialbar/RadialBarPanel.tsx index 86235a3bf68..7c2a0cc9081 100644 --- a/public/app/plugins/panel/radialbar/RadialBarPanel.tsx +++ b/public/app/plugins/panel/radialbar/RadialBarPanel.tsx @@ -38,10 +38,9 @@ export function RadialBarPanel({ height={height} barWidthFactor={options.barWidthFactor} gradient={options.effects?.gradient ? 'auto' : 'none'} - spotlight={options.effects?.spotlight} glowBar={options.effects?.barGlow} glowCenter={options.effects?.centerGlow} - roundedBars={options.effects?.rounded} + roundedBars={options.barShape === 'rounded'} vizCount={valueProps.count} shape={options.shape} segmentCount={options.segmentCount} diff --git a/public/app/plugins/panel/radialbar/module.tsx b/public/app/plugins/panel/radialbar/module.tsx index 12aff4966f7..f7cd5fb043f 100644 --- a/public/app/plugins/panel/radialbar/module.tsx +++ b/public/app/plugins/panel/radialbar/module.tsx @@ -32,18 +32,6 @@ export const plugin = new PanelPlugin(RadialBarPanel) }, }); - builder.addSliderInput({ - path: 'barWidthFactor', - name: t('radialbar.config.bar-width', 'Bar width'), - category, - defaultValue: defaultOptions.barWidthFactor, - settings: { - min: 0.1, - max: 1, - step: 0.01, - }, - }); - builder.addSliderInput({ path: 'segmentCount', name: t('radialbar.config.segment-count', 'Segments'), @@ -69,6 +57,32 @@ export const plugin = new PanelPlugin(RadialBarPanel) }, }); + builder.addRadio({ + path: 'barShape', + name: t('radialbar.config.bar-shape', 'Bar Style'), + category, + defaultValue: defaultOptions.barShape, + settings: { + options: [ + { value: 'flat', label: t('radialbar.config.bar-shape-flat', 'Flat') }, + { value: 'rounded', label: t('radialbar.config.bar-shape-rounded', 'Rounded') }, + ], + }, + showIf: (options) => options.segmentCount === 1, + }); + + builder.addSliderInput({ + path: 'barWidthFactor', + name: t('radialbar.config.bar-width', 'Bar width'), + category, + defaultValue: defaultOptions.barWidthFactor, + settings: { + min: 0.1, + max: 1, + step: 0.01, + }, + }); + builder.addBooleanSwitch({ path: 'sparkline', name: t('radialbar.config.sparkline', 'Show sparkline'), diff --git a/public/app/plugins/panel/radialbar/panelcfg.cue b/public/app/plugins/panel/radialbar/panelcfg.cue index a37982dcfe1..89df6eddc26 100644 --- a/public/app/plugins/panel/radialbar/panelcfg.cue +++ b/public/app/plugins/panel/radialbar/panelcfg.cue @@ -27,8 +27,6 @@ composableKinds: PanelCfg: { schema: { GaugePanelEffects: { barGlow?: bool | *false - spotlight?: bool | *false - rounded?: bool | *false centerGlow?: bool | *false gradient?: bool | *true } @cuetsy(kind="interface") @@ -42,6 +40,7 @@ composableKinds: PanelCfg: { sparkline?: bool | *true shape: "circle" | *"gauge" barWidthFactor: number | *0.5 + barShape: "flat" | "rounded" | *"flat" effects: GaugePanelEffects | *{} } @cuetsy(kind="interface") } diff --git a/public/app/plugins/panel/radialbar/panelcfg.gen.ts b/public/app/plugins/panel/radialbar/panelcfg.gen.ts index 24915c62ef1..ddb7b522365 100644 --- a/public/app/plugins/panel/radialbar/panelcfg.gen.ts +++ b/public/app/plugins/panel/radialbar/panelcfg.gen.ts @@ -14,19 +14,16 @@ export interface GaugePanelEffects { barGlow?: boolean; centerGlow?: boolean; gradient?: boolean; - rounded?: boolean; - spotlight?: boolean; } export const defaultGaugePanelEffects: Partial = { barGlow: false, centerGlow: false, gradient: true, - rounded: false, - spotlight: false, }; export interface Options extends common.SingleStatBaseOptions { + barShape: ('flat' | 'rounded'); barWidthFactor: number; effects: GaugePanelEffects; segmentCount: number; @@ -38,6 +35,7 @@ export interface Options extends common.SingleStatBaseOptions { } export const defaultOptions: Partial = { + barShape: 'flat', barWidthFactor: 0.5, effects: {}, segmentCount: 1,