This is an automated email from the ASF dual-hosted git repository.

yao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/spark.git


The following commit(s) were added to refs/heads/master by this push:
     new 0d0cce1bf021 [SPARK-55853][UI] Migrate hardcoded CSS colors to 
Bootstrap 5 CSS custom properties
0d0cce1bf021 is described below

commit 0d0cce1bf021a33db35ec061702cb83c21d7f152
Author: Kent Yao <[email protected]>
AuthorDate: Fri Mar 6 11:23:04 2026 +0800

    [SPARK-55853][UI] Migrate hardcoded CSS colors to Bootstrap 5 CSS custom 
properties
    
    ### What changes were proposed in this pull request?
    
    Replace hardcoded hex colors and rgb() values in CSS/JS files with 
Bootstrap 5 CSS custom properties so the Spark UI automatically adapts to 
`data-bs-theme="dark"`.
    
    ### Why are the changes needed?
    
    The Spark UI currently uses hardcoded color values throughout its CSS and 
JS files. To support dark mode via Bootstrap 5's `data-bs-theme` attribute, 
these colors need to use CSS custom properties that automatically adapt.
    
    ### Does this PR introduce _any_ user-facing change?
    
    No visual change in light mode. Enables future dark mode support by making 
all colors theme-aware.
    
    ### How was this patch tested?
    
    - `./dev/lint-js` passes
    - `./build/sbt core/compile sql/compile` succeeds
    - Manual verification that all hardcoded colors outside `:root` blocks have 
been replaced
    
    ### Was this patch authored or co-authored using generative AI tooling?
    
    Yes, GitHub Copilot CLI was used.
    
    Closes #54640 from yaooqinn/SPARK-55853.
    
    Authored-by: Kent Yao <[email protected]>
    Signed-off-by: Kent Yao <[email protected]>
---
 .../org/apache/spark/ui/static/historypage.js      |   2 +-
 .../org/apache/spark/ui/static/spark-dag-viz.css   | 107 ++++++++----
 .../resources/org/apache/spark/ui/static/table.js  |   4 +-
 .../org/apache/spark/ui/static/timeline-view.css   | 185 ++++++++++++++-------
 .../resources/org/apache/spark/ui/static/webui.css | 127 ++++++++------
 .../sql/execution/ui/static/spark-sql-viz.css      |  45 +++--
 6 files changed, 302 insertions(+), 168 deletions(-)

diff --git a/core/src/main/resources/org/apache/spark/ui/static/historypage.js 
b/core/src/main/resources/org/apache/spark/ui/static/historypage.js
index 20734eb69e57..b8d7cf2154f5 100644
--- a/core/src/main/resources/org/apache/spark/ui/static/historypage.js
+++ b/core/src/main/resources/org/apache/spark/ui/static/historypage.js
@@ -233,7 +233,7 @@ $(document).ready(function() {
             aTargets: [0, 1, 2],
             fnCreatedCell: (nTd, _ignored_sData, _ignored_oData, 
_ignored_iRow, _ignored_iCol) => {
               if (hasMultipleAttempts) {
-                $(nTd).css('background-color', '#fff');
+                $(nTd).css('background-color', 'var(--bs-body-bg)');
               }
             }
           },
diff --git 
a/core/src/main/resources/org/apache/spark/ui/static/spark-dag-viz.css 
b/core/src/main/resources/org/apache/spark/ui/static/spark-dag-viz.css
index d6ddb860389b..38d4b6cf50bc 100644
--- a/core/src/main/resources/org/apache/spark/ui/static/spark-dag-viz.css
+++ b/core/src/main/resources/org/apache/spark/ui/static/spark-dag-viz.css
@@ -15,6 +15,47 @@
  * limitations under the License.
  */
 
+:root, [data-bs-theme="light"] {
+  --spark-dag-edge: #444;
+  --spark-dag-cluster-fill: #A0DFFF;
+  --spark-dag-cluster-stroke: #3EC0FF;
+  --spark-dag-skipped-fill: #D6D6D6;
+  --spark-dag-skipped-stroke: #B7B7B7;
+  --spark-dag-stage-stroke-job: #FF99AC;
+  --spark-dag-stage-stroke-stage: #FFA6B6;
+  --spark-dag-stage-skipped-stroke: #ADADAD;
+  --spark-dag-cached-fill-job: #A3F545;
+  --spark-dag-cached-fill-stage: #B3F5C5;
+  --spark-dag-cached-stroke: #52C366;
+  --spark-dag-barrier-fill-job: #B4E9E2;
+  --spark-dag-barrier-fill-stage: #84E9E2;
+  --spark-dag-barrier-stroke: #32DBC6;
+  --spark-dag-indeterminate-fill-job: #f6b187;
+  --spark-dag-indeterminate-fill-stage: #F09c67;
+  --spark-dag-indeterminate-stroke: #D97536;
+  --spark-dag-node-fill: #C3EBFF;
+}
+[data-bs-theme="dark"] {
+  --spark-dag-edge: #adb5bd;
+  --spark-dag-cluster-fill: #1a5276;
+  --spark-dag-cluster-stroke: #5dade2;
+  --spark-dag-skipped-fill: #4a4a4a;
+  --spark-dag-skipped-stroke: #6c6c6c;
+  --spark-dag-stage-stroke-job: #e74c3c;
+  --spark-dag-stage-stroke-stage: #e74c3c;
+  --spark-dag-stage-skipped-stroke: #6c6c6c;
+  --spark-dag-cached-fill-job: #1e7a34;
+  --spark-dag-cached-fill-stage: #1e6e38;
+  --spark-dag-cached-stroke: #27ae60;
+  --spark-dag-barrier-fill-job: #117a65;
+  --spark-dag-barrier-fill-stage: #0e6655;
+  --spark-dag-barrier-stroke: #1abc9c;
+  --spark-dag-indeterminate-fill-job: #935116;
+  --spark-dag-indeterminate-fill-stage: #7d4512;
+  --spark-dag-indeterminate-stroke: #e67e22;
+  --spark-dag-node-fill: #1b4f72;
+}
+
 #dag-viz-graph a, #dag-viz-graph a:hover {
   text-decoration: none;
 }
@@ -22,11 +63,11 @@
 #dag-viz-graph .label {
   font-weight: normal;
   text-shadow: none;
-  color: #333;
+  color: var(--bs-body-color);
 }
 
 #dag-viz-graph svg path {
-  stroke: #444;
+  stroke: var(--spark-dag-edge);
   stroke-width: 1.5px;
 }
 
@@ -41,30 +82,30 @@
 /* Job page specific styles */
 
 #dag-viz-graph svg.job marker#marker-arrow path {
-  fill: #333;
+  fill: var(--bs-body-color);
   stroke-width: 0px;
 }
 
 #dag-viz-graph svg.job g.cluster rect {
-  fill: #A0DFFF;
-  stroke: #3EC0FF;
+  fill: var(--spark-dag-cluster-fill);
+  stroke: var(--spark-dag-cluster-stroke);
   stroke-width: 1px;
 }
 
 #dag-viz-graph svg.job g.cluster.skipped rect {
-  fill: #D6D6D6;
-  stroke: #B7B7B7;
+  fill: var(--spark-dag-skipped-fill);
+  stroke: var(--spark-dag-skipped-stroke);
   stroke-width: 1px;
 }
 
 #dag-viz-graph svg.job g.cluster.stage rect {
-  fill: #FFFFFF;
-  stroke: #FF99AC;
+  fill: var(--bs-body-bg);
+  stroke: var(--spark-dag-stage-stroke-job);
   stroke-width: 1px;
 }
 
 #dag-viz-graph svg.job g.cluster.stage.skipped rect {
-  stroke: #ADADAD;
+  stroke: var(--spark-dag-stage-skipped-stroke);
   stroke-width: 1px;
 }
 
@@ -73,78 +114,78 @@
 }
 
 #dag-viz-graph svg.job g.cluster text {
-  fill: #333;
+  fill: var(--bs-body-color);
 }
 
 #dag-viz-graph svg.job g.cluster.skipped text {
-  fill: #666;
+  fill: var(--bs-secondary-color);
 }
 
 #dag-viz-graph svg.job g.node circle {
-  fill: #444;
+  fill: var(--spark-dag-edge);
 }
 
 #dag-viz-graph svg.job g.node.cached circle {
-  fill: #A3F545;
-  stroke: #52C366;
+  fill: var(--spark-dag-cached-fill-job);
+  stroke: var(--spark-dag-cached-stroke);
   stroke-width: 2px;
 }
 
 #dag-viz-graph svg.job g.cluster.barrier rect {
-  fill: #B4E9E2;
-  stroke: #32DBC6;
+  fill: var(--spark-dag-barrier-fill-job);
+  stroke: var(--spark-dag-barrier-stroke);
   stroke-width: 2px;
 }
 
 #dag-viz-graph svg.job g.node.indeterminate circle {
-  fill: #f6b187;
-  stroke: #D97536;
+  fill: var(--spark-dag-indeterminate-fill-job);
+  stroke: var(--spark-dag-indeterminate-stroke);
   stroke-width: 2px;
 }
 
 /* Stage page specific styles */
 
 #dag-viz-graph svg.stage g.cluster rect {
-  fill: #A0DFFF;
-  stroke: #3EC0FF;
+  fill: var(--spark-dag-cluster-fill);
+  stroke: var(--spark-dag-cluster-stroke);
   stroke-width: 1px;
 }
 
 #dag-viz-graph svg.stage g.cluster.stage rect {
-  fill: #FFFFFF;
-  stroke: #FFA6B6;
+  fill: var(--bs-body-bg);
+  stroke: var(--spark-dag-stage-stroke-stage);
   stroke-width: 1px;
 }
 
 #dag-viz-graph svg.stage g.node g.label text tspan {
-  fill: #333;
+  fill: var(--bs-body-color);
 }
 
 #dag-viz-graph svg.stage g.cluster text {
-  fill: #333;
+  fill: var(--bs-body-color);
 }
 
 #dag-viz-graph svg.stage g.node rect {
-  fill: #C3EBFF;
-  stroke: #3EC0FF;
+  fill: var(--spark-dag-node-fill);
+  stroke: var(--spark-dag-cluster-stroke);
   stroke-width: 1px;
 }
 
 #dag-viz-graph svg.stage g.node.cached rect {
-  fill: #B3F5C5;
-  stroke: #52C366;
+  fill: var(--spark-dag-cached-fill-stage);
+  stroke: var(--spark-dag-cached-stroke);
   stroke-width: 2px;
 }
 
 #dag-viz-graph svg.stage g.cluster.barrier rect {
-  fill: #84E9E2;
-  stroke: #32DBC6;
+  fill: var(--spark-dag-barrier-fill-stage);
+  stroke: var(--spark-dag-barrier-stroke);
   stroke-width: 2px;
 }
 
 #dag-viz-graph svg.stage g.node.indeterminate rect {
-  fill: #F09c67;
-  stroke: #D97536;
+  fill: var(--spark-dag-indeterminate-fill-stage);
+  stroke: var(--spark-dag-indeterminate-stroke);
   stroke-width: 2px;
 }
 
diff --git a/core/src/main/resources/org/apache/spark/ui/static/table.js 
b/core/src/main/resources/org/apache/spark/ui/static/table.js
index 34155c817cee..493acd989323 100644
--- a/core/src/main/resources/org/apache/spark/ui/static/table.js
+++ b/core/src/main/resources/org/apache/spark/ui/static/table.js
@@ -26,9 +26,9 @@
 function stripeSummaryTable() {
   $("#task-summary-table").find("tr:not(:hidden)").each(function (index) {
     if (index % 2 == 1) {
-      $(this).css("background-color", "#f9f9f9");
+      $(this).css("background-color", "var(--bs-tertiary-bg)");
     } else {
-      $(this).css("background-color", "#ffffff");
+      $(this).css("background-color", "var(--bs-body-bg)");
     }
   });
 }
diff --git 
a/core/src/main/resources/org/apache/spark/ui/static/timeline-view.css 
b/core/src/main/resources/org/apache/spark/ui/static/timeline-view.css
index c9bf83ca98b4..d9cb0b8f8192 100644
--- a/core/src/main/resources/org/apache/spark/ui/static/timeline-view.css
+++ b/core/src/main/resources/org/apache/spark/ui/static/timeline-view.css
@@ -15,6 +15,63 @@
  * limitations under the License.
  */
 
+:root, [data-bs-theme="light"] {
+  --spark-scheduler-delay-fill: #80B1D3;
+  --spark-scheduler-delay-stroke: #6B94B0;
+  --spark-deserialization-fill: #FB8072;
+  --spark-deserialization-stroke: #D26B5F;
+  --spark-shuffle-read-fill: #FDB462;
+  --spark-shuffle-read-stroke: #D39651;
+  --spark-executor-runtime-fill: #B3DE69;
+  --spark-executor-runtime-stroke: #95B957;
+  --spark-shuffle-write-fill: #FFED6F;
+  --spark-shuffle-write-stroke: #D5C65C;
+  --spark-serialization-fill: #BC80BD;
+  --spark-serialization-stroke: #9D6B9E;
+  --spark-getting-result-fill: #8DD3C7;
+  --spark-getting-result-stroke: #75B0A6;
+  --spark-timeline-complete-bg: #A0DFFF;
+  --spark-timeline-complete-border: #3EC0FF;
+  --spark-timeline-failed-bg: #FFA1B0;
+  --spark-timeline-failed-border: #FF4D6D;
+  --spark-timeline-active-bg: #A2FCC0;
+  --spark-timeline-active-border: #36F572;
+  --spark-timeline-executor-added-selected-bg: #00AAFF;
+  --spark-timeline-executor-added-selected-border: #184C66;
+  --spark-timeline-executor-removed-selected-bg: #FF6680;
+  --spark-timeline-executor-removed-selected-border: #661F2C;
+  --spark-timeline-hover-bg: #D6FFE4;
+  --spark-timeline-legend-text: #4D4D4D;
+}
+[data-bs-theme="dark"] {
+  --spark-scheduler-delay-fill: #5a8aad;
+  --spark-scheduler-delay-stroke: #4a7494;
+  --spark-deserialization-fill: #d9695e;
+  --spark-deserialization-stroke: #b55a50;
+  --spark-shuffle-read-fill: #d4964f;
+  --spark-shuffle-read-stroke: #b37e43;
+  --spark-executor-runtime-fill: #8fb84e;
+  --spark-executor-runtime-stroke: #779c42;
+  --spark-shuffle-write-fill: #d4c654;
+  --spark-shuffle-write-stroke: #b3a849;
+  --spark-serialization-fill: #9c689e;
+  --spark-serialization-stroke: #825784;
+  --spark-getting-result-fill: #6fb3a5;
+  --spark-getting-result-stroke: #5d9488;
+  --spark-timeline-complete-bg: #1a5276;
+  --spark-timeline-complete-border: #5dade2;
+  --spark-timeline-failed-bg: #7a2535;
+  --spark-timeline-failed-border: #cc3344;
+  --spark-timeline-active-bg: #1a7a3a;
+  --spark-timeline-active-border: #27ae60;
+  --spark-timeline-executor-added-selected-bg: #2e86c1;
+  --spark-timeline-executor-added-selected-border: #1a3c4e;
+  --spark-timeline-executor-removed-selected-bg: #cc334d;
+  --spark-timeline-executor-removed-selected-border: #4a1520;
+  --spark-timeline-hover-bg: #1a4a2e;
+  --spark-timeline-legend-text: #adb5bd;
+}
+
 div#application-timeline, div#job-timeline {
   margin-bottom: 30px;
 }
@@ -52,38 +109,38 @@ div#application-timeline, div#job-timeline {
 }
 
 rect.scheduler-delay-proportion {
-  fill: #80B1D3;
-  stroke: #6B94B0;
+  fill: var(--spark-scheduler-delay-fill);
+  stroke: var(--spark-scheduler-delay-stroke);
 }
 
 rect.deserialization-time-proportion {
-  fill: #FB8072;
-  stroke: #D26B5F;
+  fill: var(--spark-deserialization-fill);
+  stroke: var(--spark-deserialization-stroke);
 }
 
 rect.shuffle-read-time-proportion {
-  fill: #FDB462;
-  stroke: #D39651;
+  fill: var(--spark-shuffle-read-fill);
+  stroke: var(--spark-shuffle-read-stroke);
 }
 
 rect.executor-runtime-proportion {
-  fill: #B3DE69;
-  stroke: #95B957;
+  fill: var(--spark-executor-runtime-fill);
+  stroke: var(--spark-executor-runtime-stroke);
 }
 
 rect.shuffle-write-time-proportion {
-  fill: #FFED6F;
-  stroke: #D5C65C;
+  fill: var(--spark-shuffle-write-fill);
+  stroke: var(--spark-shuffle-write-stroke);
 }
 
 rect.serialization-time-proportion {
-  fill: #BC80BD;
-  stroke: #9D6B9E;
+  fill: var(--spark-serialization-fill);
+  stroke: var(--spark-serialization-stroke);
 }
 
 rect.getting-result-time-proportion {
-  fill: #8DD3C7;
-  stroke: #75B0A6;
+  fill: var(--spark-getting-result-fill);
+  stroke: var(--spark-getting-result-stroke);
 }
 
 .vis-timeline {
@@ -99,51 +156,51 @@ rect.getting-result-time-proportion {
 }
 
 .vis-timeline .vis-item.stage.complete {
-  background-color: #A0DFFF;
-  border-color: #3EC0FF;
+  background-color: var(--spark-timeline-complete-bg);
+  border-color: var(--spark-timeline-complete-border);
 }
 
 .vis-timeline .vis-item.stage.complete.vis-selected {
-  background-color: #A0DFFF;
-  border-color: #3EC0FF;
+  background-color: var(--spark-timeline-complete-bg);
+  border-color: var(--spark-timeline-complete-border);
   z-index: auto;
 }
 
 .legend-area rect.completed-stage-legend {
-  fill: #A0DFFF;
-  stroke: #3EC0FF;
+  fill: var(--spark-timeline-complete-bg);
+  stroke: var(--spark-timeline-complete-border);
 }
 
 .vis-timeline .vis-item.stage.failed {
-  background-color: #FFA1B0;
-  border-color: #FF4D6D;
+  background-color: var(--spark-timeline-failed-bg);
+  border-color: var(--spark-timeline-failed-border);
 }
 
 .vis-timeline .vis-item.stage.failed.vis-selected {
-  background-color: #FFA1B0;
-  border-color: #FF4D6D;
+  background-color: var(--spark-timeline-failed-bg);
+  border-color: var(--spark-timeline-failed-border);
   z-index: auto;
 }
 
 .legend-area rect.failed-stage-legend {
-  fill: #FFA1B0;
-  stroke: #FF4D6D;
+  fill: var(--spark-timeline-failed-bg);
+  stroke: var(--spark-timeline-failed-border);
 }
 
 .vis-timeline .vis-item.stage.active {
-  background-color: #A2FCC0;
-  border-color: #36F572;
+  background-color: var(--spark-timeline-active-bg);
+  border-color: var(--spark-timeline-active-border);
 }
 
 .vis-timeline .vis-item.stage.active.vis-selected {
-  background-color: #A2FCC0;
-  border-color: #36F572;
+  background-color: var(--spark-timeline-active-bg);
+  border-color: var(--spark-timeline-active-border);
   z-index: auto;
 }
 
 .legend-area rect.active-stage-legend {
-  fill: #A2FCC0;
-  stroke: #36F572;
+  fill: var(--spark-timeline-active-bg);
+  stroke: var(--spark-timeline-active-border);
 }
 
 .vis-timeline .vis-foreground {
@@ -155,87 +212,87 @@ rect.getting-result-time-proportion {
 }
 
 .vis-timeline .vis-item.job.succeeded {
-  background-color: #A0DFFF;
-  border-color: #3EC0FF;
+  background-color: var(--spark-timeline-complete-bg);
+  border-color: var(--spark-timeline-complete-border);
 }
 
 .vis-timeline .vis-item.job.succeeded.vis-selected {
-  background-color: #A0DFFF;
-  border-color: #3EC0FF;
+  background-color: var(--spark-timeline-complete-bg);
+  border-color: var(--spark-timeline-complete-border);
   z-index: auto;
 }
 
 .legend-area rect.succeeded-job-legend {
-  fill: #A0DFFF;
-  stroke: #3EC0FF;
+  fill: var(--spark-timeline-complete-bg);
+  stroke: var(--spark-timeline-complete-border);
 }
 
 .vis-timeline .vis-item.job.failed {
-  background-color: #FFA1B0;
-  border-color: #FF4D6D;
+  background-color: var(--spark-timeline-failed-bg);
+  border-color: var(--spark-timeline-failed-border);
 }
 
 .vis-timeline .vis-item.job.failed.vis-selected {
-  background-color: #FFA1B0;
-  border-color: #FF4D6D;
+  background-color: var(--spark-timeline-failed-bg);
+  border-color: var(--spark-timeline-failed-border);
   z-index: auto;
 }
 
 .legend-area rect.failed-job-legend {
-  fill: #FFA1B0;
-  stroke: #FF4D6D;
+  fill: var(--spark-timeline-failed-bg);
+  stroke: var(--spark-timeline-failed-border);
 }
 
 .vis-timeline .vis-item.job.running {
-  background-color: #A2FCC0;
-  border-color: #36F572;
+  background-color: var(--spark-timeline-active-bg);
+  border-color: var(--spark-timeline-active-border);
 }
 
 .vis-timeline .vis-item.job.running.vis-selected {
-  background-color: #A2FCC0;
-  border-color: #36F572;
+  background-color: var(--spark-timeline-active-bg);
+  border-color: var(--spark-timeline-active-border);
   z-index: auto;
 }
 
 .legend-area rect.running-job-legend {
-  fill: #A2FCC0;
-  stroke: #36F572;
+  fill: var(--spark-timeline-active-bg);
+  stroke: var(--spark-timeline-active-border);
 }
 
 .vis-timeline .vis-item.executor.added {
-  background-color: #A0DFFF;
-  border-color: #3EC0FF;
+  background-color: var(--spark-timeline-complete-bg);
+  border-color: var(--spark-timeline-complete-border);
 }
 
 .vis-timeline .vis-item.executor.added.vis-selected {
-  background-color: #00AAFF;
-  border-color: #184C66;
+  background-color: var(--spark-timeline-executor-added-selected-bg);
+  border-color: var(--spark-timeline-executor-added-selected-border);
   z-index: 2;
 }
 
 .legend-area rect.executor-added-legend {
-  fill: #A0DFFF;
-  stroke: #3EC0FF;
+  fill: var(--spark-timeline-complete-bg);
+  stroke: var(--spark-timeline-complete-border);
 }
 
 .vis-timeline .vis-item.executor.removed {
-  background-color: #FFA1B0;
-  border-color: #FF4D6D;
+  background-color: var(--spark-timeline-failed-bg);
+  border-color: var(--spark-timeline-failed-border);
 }
 
 .vis-timeline .vis-item.executor.removed.vis-selected {
-  background-color: #FF6680;
-  border-color: #661F2C;
+  background-color: var(--spark-timeline-executor-removed-selected-bg);
+  border-color: var(--spark-timeline-executor-removed-selected-border);
   z-index: 2;
 }
 
 .legend-area rect.executor-removed-legend {
-  fill: #FFA1B0;
-  stroke: #FF4D6D;
+  fill: var(--spark-timeline-failed-bg);
+  stroke: var(--spark-timeline-failed-border);
 }
 
 tr.corresponding-item-hover > td, tr.corresponding-item-hover > th {
-  background-color: #D6FFE4 !important;
+  background-color: var(--spark-timeline-hover-bg) !important;
 }
 
 .control-panel {
@@ -269,7 +326,7 @@ span.expand-task-assignment-timeline {
 }
 
 .legend-area text {
-  fill: #4D4D4D;
+  fill: var(--spark-timeline-legend-text);
 }
 
 .additional-metrics ul {
diff --git a/core/src/main/resources/org/apache/spark/ui/static/webui.css 
b/core/src/main/resources/org/apache/spark/ui/static/webui.css
index 1f4d324cf246..a5a9965c02c0 100755
--- a/core/src/main/resources/org/apache/spark/ui/static/webui.css
+++ b/core/src/main/resources/org/apache/spark/ui/static/webui.css
@@ -15,6 +15,23 @@
  * limitations under the License.
  */
 
+:root, [data-bs-theme="light"] {
+  --spark-progress-started-from: #A4EDFF;
+  --spark-progress-started-to: #94DDFF;
+  --spark-progress-completed-from: #64CBFF;
+  --spark-progress-completed-to: #54B0EE;
+  --spark-threaddump-hover-bg: #49535a;
+  --spark-threaddump-hover-color: #fff;
+}
+[data-bs-theme="dark"] {
+  --spark-progress-started-from: #2a8faa;
+  --spark-progress-started-to: #1f7f9a;
+  --spark-progress-completed-from: #1a6f8f;
+  --spark-progress-completed-to: #105f7f;
+  --spark-threaddump-hover-bg: #6c757d;
+  --spark-threaddump-hover-color: #fff;
+}
+
 /* Utility: cursor pointer (not in BS5) */
 .cursor-pointer { cursor: pointer; }
 
@@ -34,14 +51,14 @@ h4 {
 
 a,
 a:not([href]):not([class]) {
-  color: #0088cc;
+  color: var(--bs-link-color);
   text-decoration: none;
 }
 
 
 a:hover,
 a:not([href]):not([class]):hover {
-  color: #005580;
+  color: var(--bs-link-hover-color);
   text-decoration:underline
 }
 
@@ -53,11 +70,11 @@ a:not([href]):not([class]):hover {
 }
 
 .navbar {
-  background-color: #fafafa;
-  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);
+  background-color: var(--bs-tertiary-bg);
+  background-image: linear-gradient(to bottom, var(--bs-body-bg), 
var(--bs-secondary-bg));
   background-repeat: repeat-x;
   box-shadow: 0 1px 10px rgba(0,0,0,.1);
-  border-bottom-color: #d4d4d4;
+  border-bottom-color: var(--bs-border-color);
   border-bottom-style: solid;
   border-bottom-width: 1px;
   font-size: 15px;
@@ -82,9 +99,9 @@ a:not([href]):not([class]):hover {
 }
 
 .navbar .navbar-nav .nav-item.active .nav-link {
-  background-color: #e5e5e5;
+  background-color: var(--bs-secondary-bg);
   box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);
-  color: #555555;
+  color: var(--bs-secondary-color);
   white-space: nowrap;
 }
 
@@ -109,17 +126,17 @@ table.sortable td {
 }
 
 .progress-stacked .progress-bar.progress-started {
-  background: linear-gradient(to bottom, #A4EDFF, #94DDFF);
+  background: linear-gradient(to bottom, var(--spark-progress-started-from), 
var(--spark-progress-started-to));
 }
 
 .progress-stacked .progress-bar.progress-completed {
-  background: linear-gradient(to bottom, #64CBFF, #54B0EE);
+  background: linear-gradient(to bottom, var(--spark-progress-completed-from), 
var(--spark-progress-completed-to));
 }
 
 a.kill-link {
   margin-right: 2px;
   margin-left: 20px;
-  color: gray;
+  color: var(--bs-secondary-color);
 }
 
 a.name-link {
@@ -129,23 +146,23 @@ a.name-link {
 span.expand-details {
   font-size: 10pt;
   cursor: pointer;
-  color: grey;
+  color: var(--bs-secondary-color);
 }
 
 span.rest-uri {
   font-size: 10pt;
   font-style: italic;
-  color: gray;
+  color: var(--bs-secondary-color);
 }
 
 pre {
-  background-color: rgba(0, 0, 0, .05);
+  background-color: var(--bs-tertiary-bg);
   font-size: 12px;
   line-height: 18px;
   padding: 6px;
   margin: 0;
   word-break: break-word;
-  border: 1px solid rgba(0, 0, 0, 0.15);
+  border: 1px solid var(--bs-border-color);
   border-radius: 3px;
   white-space: pre-wrap;
 }
@@ -225,8 +242,8 @@ span.expand-dag-viz, .collapse-table {
   display: inline-block;
   width: 0.5em;
   height: 0.5em;
-  border-right: 2px solid #08c;
-  border-bottom: 2px solid #08c;
+  border-right: 2px solid var(--bs-link-color);
+  border-bottom: 2px solid var(--bs-link-color);
   transition: transform 0.2s ease;
 }
 
@@ -248,11 +265,11 @@ span.expand-dag-viz, .collapse-table {
   padding: 0;
   margin: 0;
   font-weight: bold;
-  color: #777;
+  color: var(--bs-secondary-color);
 }
 
 .accordion-inner {
-  background: #f5f5f5;
+  background: var(--bs-tertiary-bg);
 }
 
 .accordion-inner pre {
@@ -272,8 +289,8 @@ a.downloadbutton {
 }
 
 .threaddump-td-mouseover {
-  background-color: #49535a !important;
-  color: white;
+  background-color: var(--spark-threaddump-hover-bg) !important;
+  color: var(--spark-threaddump-hover-color);
   cursor:pointer;
 }
 
@@ -282,7 +299,7 @@ a.downloadbutton {
   display: block;
   width: 100%;
   /* Suppress the default link styling */
-  color: #333;
+  color: var(--bs-body-color);
   text-decoration: none;
 }
 
@@ -301,12 +318,12 @@ a.downloadbutton {
 }
 
 .page-link {
-  color: #0088cc;
+  color: var(--bs-link-color);
 }
 
 .page-item.active .page-link {
-  background-color: #0088cc;
-  border-color: #0088cc;
+  background-color: var(--bs-link-color);
+  border-color: var(--bs-link-color);
 }
 
 .title-table {
@@ -355,73 +372,73 @@ a.downloadbutton {
 }
 
 #active-tasks-table th {
-  border-top: 1px solid #dddddd;
-  border-bottom: 1px solid #dddddd;
-  border-right: 1px solid #dddddd;
+  border-top: 1px solid var(--bs-border-color);
+  border-bottom: 1px solid var(--bs-border-color);
+  border-right: 1px solid var(--bs-border-color);
 }
 
 #active-tasks-table th:first-child {
-  border-left: 1px solid #dddddd;
+  border-left: 1px solid var(--bs-border-color);
 }
 
 #accumulator-table th {
-  border-top: 1px solid #dddddd;
-  border-bottom: 1px solid #dddddd;
-  border-right: 1px solid #dddddd;
+  border-top: 1px solid var(--bs-border-color);
+  border-bottom: 1px solid var(--bs-border-color);
+  border-right: 1px solid var(--bs-border-color);
 }
 
 #accumulator-table th:first-child {
-  border-left: 1px solid #dddddd;
+  border-left: 1px solid var(--bs-border-color);
 }
 
 #summary-executor-table th {
-  border-top: 1px solid #dddddd;
-  border-bottom: 1px solid #dddddd;
-  border-right: 1px solid #dddddd;
+  border-top: 1px solid var(--bs-border-color);
+  border-bottom: 1px solid var(--bs-border-color);
+  border-right: 1px solid var(--bs-border-color);
 }
 
 #summary-executor-table th:first-child {
-  border-left: 1px solid #dddddd;
+  border-left: 1px solid var(--bs-border-color);
 }
 
 #speculation-metrics-table th {
-  border-top: 1px solid #dddddd;
-  border-bottom: 1px solid #dddddd;
-  border-right: 1px solid #dddddd;
+  border-top: 1px solid var(--bs-border-color);
+  border-bottom: 1px solid var(--bs-border-color);
+  border-right: 1px solid var(--bs-border-color);
 }
 
 #speculation-metrics-table th:first-child {
-  border-left: 1px solid #dddddd;
+  border-left: 1px solid var(--bs-border-color);
 }
 
 #summary-metrics-table th {
-  border-top: 1px solid #dddddd;
-  border-bottom: 1px solid #dddddd;
-  border-right: 1px solid #dddddd;
+  border-top: 1px solid var(--bs-border-color);
+  border-bottom: 1px solid var(--bs-border-color);
+  border-right: 1px solid var(--bs-border-color);
 }
 
 #summary-metrics-table th:first-child {
-  border-left: 1px solid #dddddd;
+  border-left: 1px solid var(--bs-border-color);
 }
 
 #summary-execs-table th {
-  border-top: 1px solid #dddddd;
-  border-bottom: 1px solid #dddddd;
-  border-right: 1px solid #dddddd;
+  border-top: 1px solid var(--bs-border-color);
+  border-bottom: 1px solid var(--bs-border-color);
+  border-right: 1px solid var(--bs-border-color);
 }
 
 #summary-execs-table th:first-child {
-  border-left: 1px solid #dddddd;
+  border-left: 1px solid var(--bs-border-color);
 }
 
 #active-executors-table th {
-  border-top: 1px solid #dddddd;
-  border-bottom: 1px solid #dddddd;
-  border-right: 1px solid #dddddd;
+  border-top: 1px solid var(--bs-border-color);
+  border-bottom: 1px solid var(--bs-border-color);
+  border-right: 1px solid var(--bs-border-color);
 }
 
 #active-executors-table th:first-child {
-  border-left: 1px solid #dddddd;
+  border-left: 1px solid var(--bs-border-color);
 }
 
 .scroll-btn-container {
@@ -431,7 +448,7 @@ a.downloadbutton {
   width: 48px;
   height: 80px;
   border-radius: 8px;
-  background-color: rgba(0, 136, 204, 0.5);;
+  background-color: rgba(var(--bs-primary-rgb), 0.5);
   display: flex;
   flex-direction: column;
   overflow: hidden;
@@ -449,7 +466,7 @@ a.downloadbutton {
 }
 
 .scroll-btn-half:hover {
-  background-color: rgba(0, 136, 204, 1);
+  background-color: var(--bs-primary);
 }
 
 .scroll-btn-top::before {
@@ -490,7 +507,7 @@ a.downloadbutton {
 }
 .offcanvas-resize-handle:hover,
 .offcanvas-resize-handle.resizing {
-  background-color: rgba(13, 110, 253, 0.3);
+  background-color: rgba(var(--bs-primary-rgb), 0.3);
 }
 
 .tab-content {
diff --git 
a/sql/core/src/main/resources/org/apache/spark/sql/execution/ui/static/spark-sql-viz.css
 
b/sql/core/src/main/resources/org/apache/spark/sql/execution/ui/static/spark-sql-viz.css
index 1b03c36ae0f2..66d15dd1d30b 100644
--- 
a/sql/core/src/main/resources/org/apache/spark/sql/execution/ui/static/spark-sql-viz.css
+++ 
b/sql/core/src/main/resources/org/apache/spark/sql/execution/ui/static/spark-sql-viz.css
@@ -15,16 +15,35 @@
  * limitations under the License.
  */
 
+:root, [data-bs-theme="light"] {
+  --spark-sql-cluster-fill: #A0DFFF;
+  --spark-sql-cluster-stroke: #3EC0FF;
+  --spark-sql-node-fill: #C3EBFF;
+  --spark-sql-edge: #444;
+  --spark-sql-selected-fill: #E25A1CFF;
+  --spark-sql-selected-stroke: #317EACFF;
+  --spark-sql-linked-fill: #FFC106FF;
+}
+[data-bs-theme="dark"] {
+  --spark-sql-cluster-fill: #1a5276;
+  --spark-sql-cluster-stroke: #5dade2;
+  --spark-sql-node-fill: #1b4f72;
+  --spark-sql-edge: #adb5bd;
+  --spark-sql-selected-fill: #c0470fff;
+  --spark-sql-selected-stroke: #5dade2ff;
+  --spark-sql-linked-fill: #d4a00aff;
+}
+
 svg g.label {
   font-size: 0.85rem;
   font-weight: normal;
   text-shadow: none;
-  color: #333;
+  color: var(--bs-body-color);
 }
 
 svg g.cluster rect {
-  fill: #A0DFFF;
-  stroke: #3EC0FF;
+  fill: var(--spark-sql-cluster-fill);
+  stroke: var(--spark-sql-cluster-stroke);
   stroke-width: 1px;
 }
 
@@ -34,8 +53,8 @@ svg g.cluster > g.label {
 }
 
 svg g.node rect {
-  fill: #C3EBFF;
-  stroke: #3EC0FF;
+  fill: var(--spark-sql-node-fill);
+  stroke: var(--spark-sql-cluster-stroke);
   stroke-width: 1px;
 }
 
@@ -46,11 +65,11 @@ svg text :first-child:not(.stageId-and-taskId-metrics) {
 }
 
 svg text {
-  fill: #333;
+  fill: var(--bs-body-color);
 }
 
 svg path {
-  stroke: #444;
+  stroke: var(--spark-sql-edge);
   stroke-width: 1.5px;
 }
 
@@ -65,20 +84,20 @@ svg path {
 }
 
 svg g.node rect.selected {
-  fill: #E25A1CFF;
-  stroke: #317EACFF;
+  fill: var(--spark-sql-selected-fill);
+  stroke: var(--spark-sql-selected-stroke);
   stroke-width: 2px;
 }
 
 svg g.node rect.linked {
-  fill: #FFC106FF;
-  stroke: #317EACFF;
+  fill: var(--spark-sql-linked-fill);
+  stroke: var(--spark-sql-selected-stroke);
   stroke-width: 2px;
 }
 
 svg path.linked {
-  fill: #317EACFF;
-  stroke: #317EACFF;
+  fill: var(--spark-sql-selected-stroke);
+  stroke: var(--spark-sql-selected-stroke);
   stroke-width: 2px;
 }
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to