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 392dd8dc39b2 [SPARK-55753][UI] Upgrade Bootstrap from 4.6.2 to 5.3.8
392dd8dc39b2 is described below

commit 392dd8dc39b2d6bb3fb341901cb27d4d7103dc34
Author: Kent Yao <[email protected]>
AuthorDate: Sun Mar 1 14:55:41 2026 +0800

    [SPARK-55753][UI] Upgrade Bootstrap from 4.6.2 to 5.3.8
    
    ### What changes were proposed in this pull request?
    
    Upgrade the Spark Web UI from Bootstrap 4.6.2 (EOL Jan 2024) to Bootstrap 
5.3.8:
    
    - Replace `bootstrap.bundle.min.js` and `bootstrap.min.css` with v5.3.8
    - Replace `dataTables.bootstrap4` files with `dataTables.bootstrap5`
    - Migrate 
`data-toggle`/`data-target`/`data-placement`/`data-html`/`data-container` to 
`data-bs-*` prefix across all Scala, JS, and HTML template files
    - Migrate CSS classes: `mr-auto`→`me-auto`, `mr-2`→`me-2`, 
`float-right`→`float-end`, `form-inline`→`d-flex`, `form-group`→`mb-3`
    - Update tooltip initialization to use Bootstrap 5 `Tooltip` constructor 
instead of jQuery `.tooltip()` plugin
    - Update `docs/_layouts/global.html` for BS5 data attributes
    - jQuery is retained as it is still required by DataTables, dagre-d3, and 
custom Spark JS
    
    ### Why are the changes needed?
    
    Bootstrap 4.6.2 reached end-of-life in January 2024 and no longer receives 
security patches or bug fixes. Bootstrap 5 is the current LTS with active 
maintenance.
    
    ### Does this PR introduce _any_ user-facing change?
    
    No. The UI should look and behave identically. Bootstrap 5 is visually 
backward-compatible with Bootstrap 4.
    
    ### How was this patch tested?
    
    - All 12 Jest UI tests pass
    - Scalastyle passes
    - `core/compile` and `streaming/compile` succeed
    - `UIUtilsSuite` (8 tests) and `StoragePageSuite` (5 tests) pass
    - Live verification via spark-shell: all 4 main pages (`/`, `/jobs/`, 
`/stages/`, `/executors/`) serve correct BS5 markup with zero old BS4 
attributes or CSS classes
    
    ### Was this patch authored or co-authored using generative AI tooling?
    
    Yes, GitHub Copilot was used.
    
    Closes #54552 from yaooqinn/ui-upgrade-bootstrap5.
    
    Authored-by: Kent Yao <[email protected]>
    Signed-off-by: Kent Yao <[email protected]>
---
 .../apache/spark/ui/static/bootstrap.bundle.min.js |  6 +-
 .../org/apache/spark/ui/static/bootstrap.min.css   |  9 ++-
 .../spark/ui/static/dataTables.bootstrap4.min.css  |  1 -
 .../spark/ui/static/dataTables.bootstrap4.min.js   |  4 --
 .../spark/ui/static/dataTables.bootstrap5.min.css  |  5 ++
 .../spark/ui/static/dataTables.bootstrap5.min.js   |  4 ++
 .../spark/ui/static/executorspage-template.html    | 48 +++++++--------
 .../org/apache/spark/ui/static/executorspage.js    |  4 +-
 .../spark/ui/static/historypage-template.html      | 20 +++----
 .../org/apache/spark/ui/static/historypage.js      |  2 +-
 .../apache/spark/ui/static/initialize-tooltips.js  |  8 +--
 .../org/apache/spark/ui/static/spark-dag-viz.js    |  2 +-
 .../org/apache/spark/ui/static/stagepage.js        | 60 +++++++++----------
 .../spark/ui/static/stagespage-template.html       |  2 +-
 .../org/apache/spark/ui/static/streaming-page.js   |  9 ++-
 .../org/apache/spark/ui/static/timeline-view.js    | 34 +++++++----
 .../spark/deploy/master/ui/ApplicationPage.scala   |  4 +-
 .../scala/org/apache/spark/ui/PagedTable.scala     | 69 +++++++++++-----------
 .../main/scala/org/apache/spark/ui/UIUtils.scala   | 18 +++---
 .../spark/ui/exec/ExecutorThreadDumpPage.scala     | 10 ++--
 .../org/apache/spark/ui/jobs/AllJobsPage.scala     | 14 ++---
 .../scala/org/apache/spark/ui/jobs/JobPage.scala   | 14 ++---
 .../scala/org/apache/spark/ui/jobs/PoolTable.scala |  5 +-
 .../scala/org/apache/spark/ui/jobs/StagePage.scala | 10 ++--
 .../org/apache/spark/ui/jobs/StageTable.scala      |  2 +-
 .../apache/spark/ui/jobs/TaskThreadDumpPage.scala  |  2 +-
 .../org/apache/spark/ui/storage/RDDPage.scala      |  2 +-
 .../scala/org/apache/spark/ui/UIUtilsSuite.scala   |  2 +-
 .../apache/spark/ui/storage/StoragePageSuite.scala |  2 +-
 dev/.rat-excludes                                  |  4 +-
 dev/eslint.js                                      |  3 +
 docs/_layouts/global.html                          | 12 ++--
 .../sql/connect/ui/SparkConnectServerPage.scala    |  4 +-
 .../connect/ui/SparkConnectServerSessionPage.scala |  2 +-
 .../connect/ui/SparkConnectServerPageSuite.scala   |  4 +-
 .../spark/sql/execution/ui/AllExecutionsPage.scala |  2 +-
 .../sql/streaming/ui/StreamingQueryPage.scala      |  2 +-
 .../hive/thriftserver/ui/ThriftServerPage.scala    |  4 +-
 .../thriftserver/ui/ThriftServerSessionPage.scala  |  2 +-
 .../thriftserver/ui/ThriftServerPageSuite.scala    |  4 +-
 .../apache/spark/streaming/ui/StreamingPage.scala  |  4 +-
 41 files changed, 220 insertions(+), 199 deletions(-)

diff --git 
a/core/src/main/resources/org/apache/spark/ui/static/bootstrap.bundle.min.js 
b/core/src/main/resources/org/apache/spark/ui/static/bootstrap.bundle.min.js
index d7524d105616..0b873693aec0 100644
--- a/core/src/main/resources/org/apache/spark/ui/static/bootstrap.bundle.min.js
+++ b/core/src/main/resources/org/apache/spark/ui/static/bootstrap.bundle.min.js
@@ -1,7 +1,7 @@
 /*!
-  * Bootstrap v4.6.2 (https://getbootstrap.com/)
-  * Copyright 2011-2022 The Bootstrap Authors 
(https://github.com/twbs/bootstrap/graphs/contributors)
+  * Bootstrap v5.3.8 (https://getbootstrap.com/)
+  * Copyright 2011-2025 The Bootstrap Authors 
(https://github.com/twbs/bootstrap/graphs/contributors)
   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
   */
-!function(t,e){"object"==typeof exports&&"undefined"!=typeof 
module?e(exports,require("jquery")):"function"==typeof 
define&&define.amd?define(["exports","jquery"],e):e((t="undefined"!=typeof 
globalThis?globalThis:t||self).bootstrap={},t.jQuery)}(this,(function(t,e){"use 
strict";function n(t){return t&&"object"==typeof t&&"default"in 
t?t:{default:t}}var i=n(e);function o(t,e){for(var n=0;n<e.length;n++){var 
i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in 
i&&(i.writable=!0 [...]
+!function(t,e){"object"==typeof exports&&"undefined"!=typeof 
module?module.exports=e():"function"==typeof 
define&&define.amd?define(e):(t="undefined"!=typeof 
globalThis?globalThis:t||self).bootstrap=e()}(this,function(){"use 
strict";const t=new Map,e={set(e,i,n){t.has(e)||t.set(e,new Map);const 
s=t.get(e);s.has(i)||0===s.size?s.set(i,n):console.error(`Bootstrap doesn't 
allow more than one instance per element. Bound instance: 
${Array.from(s.keys())[0]}.`)},get:(e,i)=>t.has(e)&&t.get(e).g [...]
 //# sourceMappingURL=bootstrap.bundle.min.js.map
\ No newline at end of file
diff --git 
a/core/src/main/resources/org/apache/spark/ui/static/bootstrap.min.css 
b/core/src/main/resources/org/apache/spark/ui/static/bootstrap.min.css
index 83a71b1f5072..1d8bac41b3b5 100644
--- a/core/src/main/resources/org/apache/spark/ui/static/bootstrap.min.css
+++ b/core/src/main/resources/org/apache/spark/ui/static/bootstrap.min.css
@@ -1,7 +1,6 @@
-/*!
- * Bootstrap v4.6.2 (https://getbootstrap.com/)
- * Copyright 2011-2022 The Bootstrap Authors
- * Copyright 2011-2022 Twitter, Inc.
+@charset "UTF-8";/*!
+ * Bootstrap  v5.3.8 (https://getbootstrap.com/)
+ * Copyright 2011-2025 The Bootstrap Authors
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
- 
*/:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-s
 [...]
+ 
*/:root,[data-bs-theme=light]{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#d63384;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-black:#000;--bs-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-gray-100:#f8f9fa;--bs-gray-200:#e9ecef;--bs-gray-300:#dee2e6;--bs-gray-400:#ced4da;--bs-gray-500:#adb5bd;--bs-gray-600:#6c757d;--bs-gray-700:#495057;--bs-gray-800:#343a40;--bs-gray-900:#212529;--
 [...]
 /*# sourceMappingURL=bootstrap.min.css.map */
\ No newline at end of file
diff --git 
a/core/src/main/resources/org/apache/spark/ui/static/dataTables.bootstrap4.min.css
 
b/core/src/main/resources/org/apache/spark/ui/static/dataTables.bootstrap4.min.css
deleted file mode 100644
index d344f78a3974..000000000000
--- 
a/core/src/main/resources/org/apache/spark/ui/static/dataTables.bootstrap4.min.css
+++ /dev/null
@@ -1 +0,0 @@
-:root{--dt-row-selected: 2, 117, 216;--dt-row-selected-text: 255, 255, 
255;--dt-row-selected-link: 9, 10, 11;--dt-row-stripe: 0, 0, 0;--dt-row-hover: 
0, 0, 0;--dt-column-ordering: 0, 0, 0;--dt-html-background: 
white}:root.dark{--dt-html-background: rgb(33, 37, 41)}table.dataTable 
td.dt-control{text-align:center;cursor:pointer}table.dataTable 
td.dt-control:before{display:inline-block;color:rgba(0, 0, 0, 
0.5);content:"▶"}table.dataTable tr.dt-hasChild 
td.dt-control:before{content:"▼"}html. [...]
diff --git 
a/core/src/main/resources/org/apache/spark/ui/static/dataTables.bootstrap4.min.js
 
b/core/src/main/resources/org/apache/spark/ui/static/dataTables.bootstrap4.min.js
deleted file mode 100644
index c99016713ab1..000000000000
--- 
a/core/src/main/resources/org/apache/spark/ui/static/dataTables.bootstrap4.min.js
+++ /dev/null
@@ -1,4 +0,0 @@
-/*! DataTables Bootstrap 4 integration
- * ©2011-2017 SpryMedia Ltd - datatables.net/license
- */
-!function(t){var n,o;"function"==typeof 
define&&define.amd?define(["jquery","datatables.net"],function(e){return 
t(e,window,document)}):"object"==typeof 
exports?(n=require("jquery"),o=function(e,a){a.fn.dataTable||require("datatables.net")(e,a)},"undefined"==typeof
 window?module.exports=function(e,a){return 
e=e||window,a=a||n(e),o(e,a),t(a,0,e.document)}:(o(window,n),module.exports=t(n,window,window.document))):t(jQuery,window,document)}(function(x,e,n,o){"use
 strict";var r=x.fn.dataTabl [...]
\ No newline at end of file
diff --git 
a/core/src/main/resources/org/apache/spark/ui/static/dataTables.bootstrap5.min.css
 
b/core/src/main/resources/org/apache/spark/ui/static/dataTables.bootstrap5.min.css
new file mode 100644
index 000000000000..31ee56dacf37
--- /dev/null
+++ 
b/core/src/main/resources/org/apache/spark/ui/static/dataTables.bootstrap5.min.css
@@ -0,0 +1,5 @@
+:root{--dt-row-selected: 13, 110, 253;--dt-row-selected-text: 255, 255, 
255;--dt-row-selected-link: 9, 10, 11;--dt-row-stripe: 0, 0, 0;--dt-row-hover: 
0, 0, 0;--dt-column-ordering: 0, 0, 0;--dt-html-background: 
white}:root.dark{--dt-html-background: rgb(33, 37, 41)}table.dataTable 
td.dt-control{text-align:center;cursor:pointer}table.dataTable 
td.dt-control:before{display:inline-block;color:rgba(0, 0, 0, 
0.5);content:"▶"}table.dataTable tr.dt-hasChild 
td.dt-control:before{content:"▼"}html [...]
+ *
+ * ©2020 SpryMedia Ltd, all rights reserved.
+ * License: MIT datatables.net/license/mit
+ */table.dataTable{clear:both;margin-top:6px !important;margin-bottom:6px 
!important;max-width:none !important;border-collapse:separate 
!important;border-spacing:0}table.dataTable td,table.dataTable 
th{-webkit-box-sizing:content-box;box-sizing:content-box}table.dataTable 
td.dataTables_empty,table.dataTable 
th.dataTables_empty{text-align:center}table.dataTable.nowrap 
th,table.dataTable.nowrap 
td{white-space:nowrap}table.dataTable.table-striped>tbody>tr:nth-of-type(2n+1)>*{box-shadow:none}
 [...]
diff --git 
a/core/src/main/resources/org/apache/spark/ui/static/dataTables.bootstrap5.min.js
 
b/core/src/main/resources/org/apache/spark/ui/static/dataTables.bootstrap5.min.js
new file mode 100644
index 000000000000..d0b2d4b13f8e
--- /dev/null
+++ 
b/core/src/main/resources/org/apache/spark/ui/static/dataTables.bootstrap5.min.js
@@ -0,0 +1,4 @@
+/*! DataTables Bootstrap 5 integration
+ * 2020 SpryMedia Ltd - datatables.net/license
+ */
+!function(t){var n,r;"function"==typeof 
define&&define.amd?define(["jquery","datatables.net"],function(e){return 
t(e,window,document)}):"object"==typeof 
exports?(n=require("jquery"),r=function(e,a){a.fn.dataTable||require("datatables.net")(e,a)},"undefined"==typeof
 window?module.exports=function(e,a){return 
e=e||window,a=a||n(e),r(e,a),t(a,0,e.document)}:(r(window,n),module.exports=t(n,window,window.document))):t(jQuery,window,document)}(function(x,e,r,o){"use
 strict";var i=x.fn.dataTabl [...]
\ No newline at end of file
diff --git 
a/core/src/main/resources/org/apache/spark/ui/static/executorspage-template.html
 
b/core/src/main/resources/org/apache/spark/ui/static/executorspage-template.html
index d2229e2498bf..3dfcc0dd0416 100644
--- 
a/core/src/main/resources/org/apache/spark/ui/static/executorspage-template.html
+++ 
b/core/src/main/resources/org/apache/spark/ui/static/executorspage-template.html
@@ -24,38 +24,38 @@ limitations under the License.
           <tr>
         <th></th>
         <th>RDD Blocks</th>
-        <th><span data-toggle="tooltip" data-placement="top"
+        <th><span data-bs-toggle="tooltip" data-bs-placement="top"
                   title="Memory used / total available memory for storage of 
data like RDD partitions cached in memory.">Storage Memory</span>
         </th>
         <th>
-          <span data-toggle="tooltip" data-placement="top"
+          <span data-bs-toggle="tooltip" data-bs-placement="top"
                 title="Memory used / total available memory for on heap 
storage of data like RDD partitions cached in memory.">On Heap Storage 
Memory</span>
         </th>
         <th>
-          <span data-toggle="tooltip"
+          <span data-bs-toggle="tooltip"
                 title="Memory used / total available memory for off heap 
storage of data like RDD partitions cached in memory.">Off Heap Storage 
Memory</span>
         </th>
         <th>Disk Used</th>
         <th>Cores</th>
-        <th><span data-toggle="tooltip" data-placement="top" title="Number of 
tasks currently executing. Darker shading highlights executors with more active 
tasks.">Active Tasks</span></th>
-        <th><span data-toggle="tooltip" data-placement="top" title="Number of 
tasks that have failed on this executor. Darker shading highlights executors 
with a high proportion of failed tasks.">Failed Tasks</span></th>
+        <th><span data-bs-toggle="tooltip" data-bs-placement="top" 
title="Number of tasks currently executing. Darker shading highlights executors 
with more active tasks.">Active Tasks</span></th>
+        <th><span data-bs-toggle="tooltip" data-bs-placement="top" 
title="Number of tasks that have failed on this executor. Darker shading 
highlights executors with a high proportion of failed tasks.">Failed 
Tasks</span></th>
         <th>Complete Tasks</th>
         <th>Total Tasks</th>
-        <th><span data-toggle="tooltip" data-placement="top"
+        <th><span data-bs-toggle="tooltip" data-bs-placement="top"
                   title="Shaded red when garbage collection (GC) time is over 
10% of task time">
           Task Time (GC Time)</span></th>
-        <th><span data-toggle="tooltip" data-placement="top"
+        <th><span data-bs-toggle="tooltip" data-bs-placement="top"
                   title="Bytes and records read from Hadoop or from Spark 
storage.">Input</span></th>
-        <th><span data-toggle="tooltip" data-placement="top"
+        <th><span data-bs-toggle="tooltip" data-bs-placement="top"
                   title="Total shuffle bytes and records read (includes both 
data read locally and data read from remote executors).">
           Shuffle Read</span></th>
         <th>
-          <span data-toggle="tooltip" data-placement="top"
+          <span data-bs-toggle="tooltip" data-bs-placement="top"
                 title="Bytes and records written to disk in order to be read 
by a shuffle in a future stage.">
             Shuffle Write</span>
         </th>
         <th>
-          <span data-toggle="tooltip" data-placement="top"
+          <span data-bs-toggle="tooltip" data-bs-placement="top"
                 title="Number of executors excluded by the scheduler due to 
task failures.">
             Excluded</span>
         </th>
@@ -75,55 +75,55 @@ limitations under the License.
           <th>Status</th>
           <th>RDD Blocks</th>
           <th>
-            <span data-toggle="tooltip" data-placement="top"
+            <span data-bs-toggle="tooltip" data-bs-placement="top"
                   title="Memory used / total available memory for storage of 
data like RDD partitions cached in memory.">
               Storage Memory</span></th>
           <th>
-            <span data-toggle="tooltip" data-placement="top"
+            <span data-bs-toggle="tooltip" data-bs-placement="top"
                   title="Memory used / total available memory for on heap 
storage of data like RDD partitions cached in memory.">
               On Heap Storage Memory</span></th>
           <th>
-            <span data-toggle="tooltip" data-placement="top"
+            <span data-bs-toggle="tooltip" data-bs-placement="top"
                   title="Memory used / total available memory for off heap 
storage of data like RDD partitions cached in memory.">
               Off Heap Storage Memory</span></th>
           <th>
-            <span data-toggle="tooltip" data-placement="top"
+            <span data-bs-toggle="tooltip" data-bs-placement="top"
                   title="Peak onHeap / offHeap memory used by JVM.">
               Peak JVM Memory OnHeap / OffHeap</span></th>
           <th>
-            <span data-toggle="tooltip" data-placement="top"
+            <span data-bs-toggle="tooltip" data-bs-placement="top"
                   title="Peak onHeap / offHeap memory used for execution. This 
refers to memory used for computation in shuffles, joins, user data structures, 
etc. See the Memory Management Overview documentation for more details.">
               Peak Execution Memory OnHeap / OffHeap</span></th>
           <th>
-            <span data-toggle="tooltip" data-placement="top"
+            <span data-bs-toggle="tooltip" data-bs-placement="top"
             title="Peak storage onHeap / offHeap memory used for storage of 
data like RDD partitions cached in memory.">
               Peak Storage Memory OnHeap / OffHeap</span></th>
           <th>
-            <span data-toggle="tooltip" data-placement="top"
+            <span data-bs-toggle="tooltip" data-bs-placement="top"
                   title="Peak direct byte buffer / memory-mapped buffer pool 
memory used by JVM. This refers to BufferPoolMXBean with form 
'java.nio:type=BufferPool,name=direct' and 
'java.nio:type=BufferPool,name=mapped'.">
               Peak Pool Memory Direct / Mapped</span></th>
           <th>Disk Used</th>
           <th>Cores</th>
-          <th><span data-toggle="tooltip" data-placement="top" 
title="Resources currently used by each executor, such as GPU, FPGA, 
etc.">Resources</span></th>
+          <th><span data-bs-toggle="tooltip" data-bs-placement="top" 
title="Resources currently used by each executor, such as GPU, FPGA, 
etc.">Resources</span></th>
           <th>Resource Profile Id</th>
-          <th><span data-toggle="tooltip" data-placement="top" title="Number 
of tasks currently executing. Darker shading highlights executors with more 
active tasks.">Active Tasks</span></th>
-          <th><span data-toggle="tooltip" data-placement="top" title="Number 
of tasks that have failed on this executor. Darker shading highlights executors 
with a high proportion of failed tasks.">Failed Tasks</span></th>
+          <th><span data-bs-toggle="tooltip" data-bs-placement="top" 
title="Number of tasks currently executing. Darker shading highlights executors 
with more active tasks.">Active Tasks</span></th>
+          <th><span data-bs-toggle="tooltip" data-bs-placement="top" 
title="Number of tasks that have failed on this executor. Darker shading 
highlights executors with a high proportion of failed tasks.">Failed 
Tasks</span></th>
           <th>Complete Tasks</th>
           <th>Total Tasks</th>
           <th>
-            <span data-toggle="tooltip" data-placement="top"
+            <span data-bs-toggle="tooltip" data-bs-placement="top"
                   title="Shaded red when garbage collection (GC) time is over 
10% of task time">
               Task Time (GC Time)
             </span>
           </th>
-          <th><span data-toggle="tooltip" data-placement="top"
+          <th><span data-bs-toggle="tooltip" data-bs-placement="top"
                     title="Bytes and records read from Hadoop or from Spark 
storage.">Input</span></th>
           <th>
-            <span data-toggle="tooltip" data-placement="top"
+            <span data-bs-toggle="tooltip" data-bs-placement="top"
                   title="Total shuffle bytes and records read (includes both 
data read locally and data read from remote executors).">
               Shuffle Read</span></th>
           <th>
-            <span data-toggle="tooltip" data-placement="top"
+            <span data-bs-toggle="tooltip" data-bs-placement="top"
                   title="Bytes and records written to disk in order to be read 
by a shuffle in a future stage.">
               Shuffle Write</span></th>
           <th>Logs</th>
diff --git 
a/core/src/main/resources/org/apache/spark/ui/static/executorspage.js 
b/core/src/main/resources/org/apache/spark/ui/static/executorspage.js
index 1b02fc0493e7..12f3d0a5f6a4 100644
--- a/core/src/main/resources/org/apache/spark/ui/static/executorspage.js
+++ b/core/src/main/resources/org/apache/spark/ui/static/executorspage.js
@@ -623,7 +623,7 @@ $(document).ready(function () {
         
execDataTable.column('executorLogsCol:name').visible(logsExist(response));
         
execDataTable.column('threadDumpCol:name').visible(getThreadDumpEnabled());
         
execDataTable.column('heapHistogramCol:name').visible(getHeapHistogramEnabled());
-        $('#active-executors [data-toggle="tooltip"]').tooltip();
+        $('#active-executors [data-bs-toggle="tooltip"]').each(function() { 
new bootstrap.Tooltip(this); });
     
         // This section should be visible once API gives the response.
         $('.active-process-container').hide();
@@ -751,7 +751,7 @@ $(document).ready(function () {
         };
 
         sumDataTable = $(sumSelector).DataTable(sumConf);
-        $('#execSummary [data-toggle="tooltip"]').tooltip();
+        $('#execSummary [data-bs-toggle="tooltip"]').each(function() { new 
bootstrap.Tooltip(this); });
   
         $("#showAdditionalMetrics").append(
           "<div><a id='additionalMetrics' class='collapse-table'>" +
diff --git 
a/core/src/main/resources/org/apache/spark/ui/static/historypage-template.html 
b/core/src/main/resources/org/apache/spark/ui/static/historypage-template.html
index 5427125cb3b5..a780459fee1f 100644
--- 
a/core/src/main/resources/org/apache/spark/ui/static/historypage-template.html
+++ 
b/core/src/main/resources/org/apache/spark/ui/static/historypage-template.html
@@ -20,56 +20,56 @@
   <thead>
     <tr>
       <th>
-        <span data-toggle="tooltip" data-placement="top" title="Spark version 
of this application.">
+        <span data-bs-toggle="tooltip" data-bs-placement="top" title="Spark 
version of this application.">
           Version
         </span>
       </th>
       <th>
-        <span data-toggle="tooltip" data-placement="top" title="ID of this 
application.">
+        <span data-bs-toggle="tooltip" data-bs-placement="top" title="ID of 
this application.">
           App ID
         </span>
       </th>
       <th>
-        <span data-toggle="tooltip" data-placement="top" title="Name of this 
application.">
+        <span data-bs-toggle="tooltip" data-bs-placement="top" title="Name of 
this application.">
           App Name
         </span>
       </th>
       {{#hasMultipleAttempts}}
       <th>
-        <span data-toggle="tooltip" data-placement="top" title="The attempt ID 
of this application since one application might be launched several times">
+        <span data-bs-toggle="tooltip" data-bs-placement="top" title="The 
attempt ID of this application since one application might be launched several 
times">
           Attempt ID
         </span>
       </th>
       {{/hasMultipleAttempts}}
       <th>
-        <span data-toggle="tooltip" data-placement="top" title="Started time 
of this application.">
+        <span data-bs-toggle="tooltip" data-bs-placement="top" title="Started 
time of this application.">
           Started
         </span>
       </th>
       {{#showCompletedColumns}}
       <th>
-        <span data-toggle="tooltip" data-placement="top" title="The completed 
time of this application.">
+        <span data-bs-toggle="tooltip" data-bs-placement="top" title="The 
completed time of this application.">
           Completed
         </span>
       </th>
       <th>
-        <span data-toggle="tooltip" data-placement="top" title="The duration 
time of this application.">
+        <span data-bs-toggle="tooltip" data-bs-placement="top" title="The 
duration time of this application.">
           Duration
         </span>
       </th>
       {{/showCompletedColumns}}
       <th>
-        <span data-toggle="tooltip" data-placement="top" title="The Spark user 
of this application">
+        <span data-bs-toggle="tooltip" data-bs-placement="top" title="The 
Spark user of this application">
           Spark User
         </span>
       </th>
       <th>
-        <span data-toggle="tooltip" data-placement="top" title="The timestamp 
of the last updating on this application">
+        <span data-bs-toggle="tooltip" data-bs-placement="top" title="The 
timestamp of the last updating on this application">
           Last Updated
         </span>
       </th>
       <th>
-        <span data-toggle="tooltip" data-placement="top" title="Download the 
event log for this application">
+        <span data-bs-toggle="tooltip" data-bs-placement="top" title="Download 
the event log for this application">
           Event Log
         </span>
       </th>
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 853dfa708ef4..c5f3a0bf5d3e 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
@@ -265,7 +265,7 @@ $(document).ready(function() {
       historySummary.append(apps);
       apps.DataTable(conf);
       sibling.after(historySummary);
-      $('#history-summary [data-toggle="tooltip"]').tooltip();
+      $('#history-summary [data-bs-toggle="tooltip"]').each(function() { new 
bootstrap.Tooltip(this); });
     });
   });
 });
diff --git 
a/core/src/main/resources/org/apache/spark/ui/static/initialize-tooltips.js 
b/core/src/main/resources/org/apache/spark/ui/static/initialize-tooltips.js
index b273a19783f8..6533787415e0 100644
--- a/core/src/main/resources/org/apache/spark/ui/static/initialize-tooltips.js
+++ b/core/src/main/resources/org/apache/spark/ui/static/initialize-tooltips.js
@@ -15,9 +15,9 @@
  * limitations under the License.
  */
 
-/* global $ */
-
-$(document).ready(function(){
-  $("[data-toggle=tooltip]").tooltip({container: 'body'});
+document.addEventListener("DOMContentLoaded", function() {
+  document.querySelectorAll("[data-bs-toggle=tooltip]").forEach(function(el) {
+    new bootstrap.Tooltip(el, {container: 'body'});
+  });
 });
 
diff --git 
a/core/src/main/resources/org/apache/spark/ui/static/spark-dag-viz.js 
b/core/src/main/resources/org/apache/spark/ui/static/spark-dag-viz.js
index fa30004bb5b7..5393597b7e64 100644
--- a/core/src/main/resources/org/apache/spark/ui/static/spark-dag-viz.js
+++ b/core/src/main/resources/org/apache/spark/ui/static/spark-dag-viz.js
@@ -562,7 +562,7 @@ function addTooltipsForRDDs(svgContainer, g) {
   g.nodes().filter((v) => !g.node(v).isCluster).forEach((v) => {
     const node = g.node(v);
     d3.select("#" + node.id).each(function () {
-      $(this).tooltip({
+      new bootstrap.Tooltip(this, {
         title: node.label, trigger: "hover focus", container: "body", 
placement: "top", html: true
       })
     });
diff --git a/core/src/main/resources/org/apache/spark/ui/static/stagepage.js 
b/core/src/main/resources/org/apache/spark/ui/static/stagepage.js
index 55305dee3899..ba573c0535f3 100644
--- a/core/src/main/resources/org/apache/spark/ui/static/stagepage.js
+++ b/core/src/main/resources/org/apache/spark/ui/static/stagepage.js
@@ -356,36 +356,36 @@ $(document).ready(function () {
     "<div id='executor_direct_mapped_pool_memory' 
class='executor-jvm-metrics-checkbox-div'><input type='checkbox' 
class='toggle-vis' id='executor-box-18' data-column='18' 
data-metrics-type='executor'> Peak Pool Memory Direct / Mapped</div>" +
     "</div>");
 
-  $('#scheduler_delay').attr("data-toggle", "tooltip")
-    .attr("data-placement", "top")
+  $('#scheduler_delay').attr("data-bs-toggle", "tooltip")
+    .attr("data-bs-placement", "top")
     .attr("title", "Scheduler delay includes time to ship the task from the 
scheduler to the executor, and time to send " +
       "the task result from the executor to the scheduler. If scheduler delay 
is large, consider decreasing the size of tasks or decreasing the size of task 
results.");
-  $('#task_deserialization_time').attr("data-toggle", "tooltip")
-    .attr("data-placement", "top")
+  $('#task_deserialization_time').attr("data-bs-toggle", "tooltip")
+    .attr("data-bs-placement", "top")
     .attr("title", "Time spent deserializing the task closure on the executor, 
including the time to read the broadcasted task.");
-  $('#shuffle_read_fetch_wait_time').attr("data-toggle", "tooltip")
-    .attr("data-placement", "top")
+  $('#shuffle_read_fetch_wait_time').attr("data-bs-toggle", "tooltip")
+    .attr("data-bs-placement", "top")
     .attr("title", "Time that the task spent blocked waiting for shuffle data 
to be read from remote machines.");
-  $('#shuffle_remote_reads').attr("data-toggle", "tooltip")
-    .attr("data-placement", "top")
+  $('#shuffle_remote_reads').attr("data-bs-toggle", "tooltip")
+    .attr("data-bs-placement", "top")
     .attr("title", "Total shuffle bytes read from remote executors. This is a 
subset of the shuffle read bytes; the remaining shuffle data is read locally. 
");
-  $('#shuffle_write_time').attr("data-toggle", "tooltip")
-    .attr("data-placement", "top")
+  $('#shuffle_write_time').attr("data-bs-toggle", "tooltip")
+    .attr("data-bs-placement", "top")
     .attr("title", "Time that the task spent writing shuffle data.");
-  $('#result_serialization_time').attr("data-toggle", "tooltip")
-    .attr("data-placement", "top")
+  $('#result_serialization_time').attr("data-bs-toggle", "tooltip")
+    .attr("data-bs-placement", "top")
     .attr("title", "Time spent serializing the task result on the executor 
before sending it back to the driver.");
-  $('#getting_result_time').attr("data-toggle", "tooltip")
-    .attr("data-placement", "top")
+  $('#getting_result_time').attr("data-bs-toggle", "tooltip")
+    .attr("data-bs-placement", "top")
     .attr("title", "Time that the driver spends fetching task results from 
workers. If this is large, consider decreasing the amount of data returned from 
each task.");
-  $('#peak_execution_memory').attr("data-toggle", "tooltip")
-    .attr("data-placement", "top")
+  $('#peak_execution_memory').attr("data-bs-toggle", "tooltip")
+    .attr("data-bs-placement", "top")
     .attr("title", "Execution memory refers to the memory used by internal 
data structures created during " +
       "shuffles, aggregations and joins when Tungsten is enabled. The value of 
this accumulator " +
       "should be approximately the sum of the peak sizes across all such data 
structures created " +
       "in this task. For SQL jobs, this only tracks all unsafe operators, 
broadcast joins, and " +
       "external sort.");
-  $('[data-toggle="tooltip"]').tooltip();
+  document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(function(el) 
{ new bootstrap.Tooltip(el); });
   var tasksSummary = $("#parent-container");
   getStandAloneAppId(function (appId) {
     // rendering the UI page
@@ -622,35 +622,35 @@ $(document).ready(function () {
             };
             executorSummaryTableSelector =
               $("#summary-executor-table").DataTable(executorSummaryConf);
-            $('#parent-container [data-toggle="tooltip"]').tooltip();
+            $('#parent-container [data-bs-toggle="tooltip"]').each(function() 
{ new bootstrap.Tooltip(this); });
   
             
executorSummaryTableSelector.column(9).visible(dataToShow.showInputData);
             if (dataToShow.showInputData) {
-              $('#executor-summary-input').attr("data-toggle", "tooltip")
-                .attr("data-placement", "top")
+              $('#executor-summary-input').attr("data-bs-toggle", "tooltip")
+                .attr("data-bs-placement", "top")
                 .attr("title", "Bytes and records read from Hadoop or from 
Spark storage.");
-              $('#executor-summary-input').tooltip(true);
+              new 
bootstrap.Tooltip(document.getElementById('executor-summary-input'));
             }
             
executorSummaryTableSelector.column(10).visible(dataToShow.showOutputData);
             if (dataToShow.showOutputData) {
-              $('#executor-summary-output').attr("data-toggle", "tooltip")
-                .attr("data-placement", "top")
+              $('#executor-summary-output').attr("data-bs-toggle", "tooltip")
+                .attr("data-bs-placement", "top")
                 .attr("title", "Bytes and records written to Hadoop.");
-              $('#executor-summary-output').tooltip(true);
+              new 
bootstrap.Tooltip(document.getElementById('executor-summary-output'));
             }
             
executorSummaryTableSelector.column(11).visible(dataToShow.showShuffleReadData);
             if (dataToShow.showShuffleReadData) {
-              $('#executor-summary-shuffle-read').attr("data-toggle", 
"tooltip")
-                .attr("data-placement", "top")
+              $('#executor-summary-shuffle-read').attr("data-bs-toggle", 
"tooltip")
+                .attr("data-bs-placement", "top")
                 .attr("title", "Total shuffle bytes and records read (includes 
both data read locally and data read from remote executors).");
-              $('#executor-summary-shuffle-read').tooltip(true);
+              new 
bootstrap.Tooltip(document.getElementById('executor-summary-shuffle-read'));
             }
             
executorSummaryTableSelector.column(12).visible(dataToShow.showShuffleWriteData);
             if (dataToShow.showShuffleWriteData) {
-              $('#executor-summary-shuffle-write').attr("data-toggle", 
"tooltip")
-                .attr("data-placement", "top")
+              $('#executor-summary-shuffle-write').attr("data-bs-toggle", 
"tooltip")
+                .attr("data-bs-placement", "top")
                 .attr("title", "Bytes and records written to disk in order to 
be read by a shuffle in a future stage.");
-              $('#executor-summary-shuffle-write').tooltip(true);
+              new 
bootstrap.Tooltip(document.getElementById('executor-summary-shuffle-write'));
             }
             
executorSummaryTableSelector.column(13).visible(dataToShow.showBytesSpilledData);
             
executorSummaryTableSelector.column(14).visible(dataToShow.showBytesSpilledData);
diff --git 
a/core/src/main/resources/org/apache/spark/ui/static/stagespage-template.html 
b/core/src/main/resources/org/apache/spark/ui/static/stagespage-template.html
index 86ec73e91a76..ab911ea77988 100644
--- 
a/core/src/main/resources/org/apache/spark/ui/static/stagespage-template.html
+++ 
b/core/src/main/resources/org/apache/spark/ui/static/stagespage-template.html
@@ -64,7 +64,7 @@ limitations under the License.
                 <th>Killed Tasks</th>
                 <th>Succeeded Tasks</th>
                 <th>
-          <span data-toggle="tooltip" data-placement="top"
+          <span data-bs-toggle="tooltip" data-bs-placement="top"
                 title="Shows if this executor has been excluded by the 
scheduler due to task failures.">
             Excluded</span>
                 </th>
diff --git 
a/core/src/main/resources/org/apache/spark/ui/static/streaming-page.js 
b/core/src/main/resources/org/apache/spark/ui/static/streaming-page.js
index 73941e618c89..1342f70577cc 100644
--- a/core/src/main/resources/org/apache/spark/ui/static/streaming-page.js
+++ b/core/src/main/resources/org/apache/spark/ui/static/streaming-page.js
@@ -44,15 +44,18 @@ var onClickTimeline = function() {};
 // Show a tooltip "text" for "node"
 function showBootstrapTooltip(d3Selection, text) {
   d3Selection.each(function() {
-    $(this).tooltip({title: text, trigger: "manual", container: "body"});
-    $(this).tooltip("show");
+    var tt = bootstrap.Tooltip.getInstance(this);
+    if (tt) tt.dispose();
+    tt = new bootstrap.Tooltip(this, {title: text, trigger: "manual", 
container: "body"});
+    tt.show();
   });
 }
 
 // Hide the tooltip for "node"
 function hideBootstrapTooltip(d3Selection) {
   d3Selection.each(function() {
-    $(this).tooltip("dispose");
+    var tt = bootstrap.Tooltip.getInstance(this);
+    if (tt) tt.dispose();
   });
 }
 
diff --git 
a/core/src/main/resources/org/apache/spark/ui/static/timeline-view.js 
b/core/src/main/resources/org/apache/spark/ui/static/timeline-view.js
index 62a1034ff69a..2e368fcbd596 100644
--- a/core/src/main/resources/org/apache/spark/ui/static/timeline-view.js
+++ b/core/src/main/resources/org/apache/spark/ui/static/timeline-view.js
@@ -61,8 +61,8 @@ function drawApplicationTimeline(groupArray, eventObjArray, 
startTime, offset) {
     xss: {
       disabled: false,
       filterOptions: {
-        whiteList: { svg: ['width', 'height', 'class'], div: ['class', 
'style', 'data-toggle', 'data-placement',
-          'data-html', 'data-container', 'data-title', 'data-original-title', 
'title'],
+        whiteList: { svg: ['width', 'height', 'class'], div: ['class', 
'style', 'data-bs-toggle', 'data-bs-placement',
+          'data-bs-html', 'data-bs-container', 'data-title', 
'data-original-title', 'title'],
         text: ['x', 'y'], rect: ['x', 'y', 'class', 'width', 'height', 'rx', 
'ry'],},
       },
     }
@@ -93,11 +93,13 @@ function drawApplicationTimeline(groupArray, eventObjArray, 
startTime, offset) {
       $(this).hover(
         function() {
           
$(getSelectorForJobEntry(getIdForJobEntry(this))).addClass("corresponding-item-hover");
-          
$($(this).find("div.application-timeline-content")[0]).tooltip("show");
+          var el = $($(this).find("div.application-timeline-content")[0])[0];
+          var tt = bootstrap.Tooltip.getInstance(el); if (tt) tt.show();
         },
         function() {
           
$(getSelectorForJobEntry(getIdForJobEntry(this))).removeClass("corresponding-item-hover");
-          
$($(this).find("div.application-timeline-content")[0]).tooltip("hide");
+          var el = $($(this).find("div.application-timeline-content")[0])[0];
+          var tt = bootstrap.Tooltip.getInstance(el); if (tt) tt.hide();
         }
       );
     });
@@ -154,8 +156,8 @@ function drawJobTimeline(groupArray, eventObjArray, 
startTime, offset) {
     xss: {
       disabled: false,
       filterOptions: {
-        whiteList: { svg: ['width', 'height', 'class'], div: ['class', 
'style', 'data-toggle', 'data-placement',
-          'data-html', 'data-container', 'data-title', 'data-original-title', 
'title'],
+        whiteList: { svg: ['width', 'height', 'class'], div: ['class', 
'style', 'data-bs-toggle', 'data-bs-placement',
+          'data-bs-html', 'data-bs-container', 'data-title', 
'data-original-title', 'title'],
         text: ['x', 'y'], rect: ['x', 'y', 'class', 'width', 'height', 'rx', 
'ry'],},
       },
     }
@@ -189,12 +191,16 @@ function drawJobTimeline(groupArray, eventObjArray, 
startTime, offset) {
         function() {
           $(getSelectorForStageEntry(getStageIdAndAttemptForStageEntry(this)))
             .addClass("corresponding-item-hover");
-          $($(this).find("div.job-timeline-content")[0]).tooltip("show");
+          $($(this).find("div.job-timeline-content")[0]).each(function() {
+            var tt = bootstrap.Tooltip.getInstance(this); if (tt) tt.show();
+          });
         },
         function() {
           $(getSelectorForStageEntry(getStageIdAndAttemptForStageEntry(this)))
             .removeClass("corresponding-item-hover");
-          $($(this).find("div.job-timeline-content")[0]).tooltip("hide");
+          $($(this).find("div.job-timeline-content")[0]).each(function() {
+            var tt = bootstrap.Tooltip.getInstance(this); if (tt) tt.hide();
+          });
         }
       );
     });
@@ -253,8 +259,8 @@ function drawTaskAssignmentTimeline(groupArray, 
eventObjArray, minLaunchTime, ma
     xss: {
       disabled: false,
       filterOptions: {
-        whiteList: { svg: ['width', 'height', 'class'], div: ['class', 
'style', 'data-toggle', 'data-placement',
-          'data-html', 'data-container', 'data-title', 'data-original-title', 
'title'],
+        whiteList: { svg: ['width', 'height', 'class'], div: ['class', 
'style', 'data-bs-toggle', 'data-bs-placement',
+          'data-bs-html', 'data-bs-container', 'data-title', 
'data-original-title', 'title'],
         text: ['x', 'y'], rect: ['x', 'y', 'class', 'width', 'height', 'rx', 
'ry'],},
       },
     }
@@ -276,7 +282,7 @@ function drawTaskAssignmentTimeline(groupArray, 
eventObjArray, minLaunchTime, ma
   }, ".task-assignment-timeline-content");
   taskTimeline.on("rangechange", function(prop) {
     if (currentDisplayedTooltip !== null) {
-      $(currentDisplayedTooltip).tooltip("hide");
+      var tt = bootstrap.Tooltip.getInstance(currentDisplayedTooltip); if (tt) 
tt.hide();
     }
   });
 
@@ -314,10 +320,12 @@ function setupExecutorEventAction() {
   $(".vis-item.vis-box.executor").each(function () {
     $(this).hover(
       function() {
-        $($(this).find(".executor-event-content")[0]).tooltip("show");
+        var el = $($(this).find(".executor-event-content")[0])[0];
+        var tt = bootstrap.Tooltip.getInstance(el); if (tt) tt.show();
       },
       function() {
-        $($(this).find(".executor-event-content")[0]).tooltip("hide");
+        var el = $($(this).find(".executor-event-content")[0])[0];
+        var tt = bootstrap.Tooltip.getInstance(el); if (tt) tt.hide();
       }
     );
   });
diff --git 
a/core/src/main/scala/org/apache/spark/deploy/master/ui/ApplicationPage.scala 
b/core/src/main/scala/org/apache/spark/deploy/master/ui/ApplicationPage.scala
index 5483d30de70d..864b27577c1e 100644
--- 
a/core/src/main/scala/org/apache/spark/deploy/master/ui/ApplicationPage.scala
+++ 
b/core/src/main/scala/org/apache/spark/deploy/master/ui/ApplicationPage.scala
@@ -72,8 +72,8 @@ private[ui] class ApplicationPage(parent: MasterWebUI) 
extends WebUIPage("app")
             }
             </li>
             <li>
-              <span data-toggle="tooltip" 
title={ToolTips.APPLICATION_EXECUTOR_LIMIT}
-                    data-placement="top">
+              <span data-bs-toggle="tooltip" 
title={ToolTips.APPLICATION_EXECUTOR_LIMIT}
+                    data-bs-placement="top">
                 <strong>Executor Limit: </strong>
                 {
                   if (app.getExecutorLimit == Int.MaxValue) "Unlimited" else 
app.getExecutorLimit
diff --git a/core/src/main/scala/org/apache/spark/ui/PagedTable.scala 
b/core/src/main/scala/org/apache/spark/ui/PagedTable.scala
index a7c74e74d284..930964182d43 100644
--- a/core/src/main/scala/org/apache/spark/ui/PagedTable.scala
+++ b/core/src/main/scala/org/apache/spark/ui/PagedTable.scala
@@ -134,7 +134,7 @@ private[spark] trait PagedTable[T] {
         val PageData(totalPages, _) = _dataSource.pageData(1)
         <div>
           {pageNavigation(1, _dataSource.pageSize, totalPages)}
-          <div class="alert alert-error">
+          <div class="alert alert-danger">
             <p>Error while rendering table:</p>
             <pre>
               {Utils.exceptionString(e)}
@@ -218,35 +218,10 @@ private[spark] trait PagedTable[T] {
       }
     }
 
-    <div>
-      <div>
-        <form id={s"form-$navigationId-page"}
-              method="get"
-              action={Unparsed(goButtonFormPath)}
-              class="form-inline float-right justify-content-end"
-              style="margin-bottom: 0px;">
-          {hiddenFormFields}
-          <label>{totalPages} Pages. Jump to</label>
-          <input type="text"
-                 name={pageNumberFormField}
-                 id={s"form-$navigationId-page-no"}
-                 value={page.toString}
-                 class="col-1 form-control" />
-
-          <label>. Show </label>
-          <input type="text"
-                 id={s"form-$navigationId-page-size"}
-                 name={pageSizeFormField}
-                 value={pageSize.toString}
-                 class="col-1 form-control" />
-          <label>items in a page.</label>
-
-          <button type="submit" class="btn btn-spark">Go</button>
-        </form>
-      </div>
-      <div>
-        <span style="float: left; padding-top: 4px; padding-right: 4px;">Page: 
</span>
-        <ul class="pagination">
+    <div class="d-flex justify-content-between align-items-center">
+      <div class="d-flex align-items-center">
+        <span style="padding-right: 4px;">Page: </span>
+        <ul class="pagination" style="margin-bottom: 0;">
           {if (currentGroup > firstGroup) {
           <li class="page-item">
             <a href={Unparsed(pageLink(startPage - groupSize))} 
class="page-link"
@@ -286,6 +261,33 @@ private[spark] trait PagedTable[T] {
         }}
         </ul>
       </div>
+      <div>
+        <form id={s"form-$navigationId-page"}
+              method="get"
+              action={Unparsed(goButtonFormPath)}
+              class="d-flex align-items-center gap-1"
+              style="margin-bottom: 0px;">
+          {hiddenFormFields}
+          <label style="white-space: nowrap;">{totalPages} Pages. Jump 
to</label>
+          <input type="text"
+                 name={pageNumberFormField}
+                 id={s"form-$navigationId-page-no"}
+                 value={page.toString}
+                 class="form-control form-control-sm"
+                 style="width: 60px;" />
+
+          <label style="white-space: nowrap;">. Show </label>
+          <input type="text"
+                 id={s"form-$navigationId-page-size"}
+                 name={pageSizeFormField}
+                 value={pageSize.toString}
+                 class="form-control form-control-sm"
+                 style="width: 60px;" />
+          <label style="white-space: nowrap;">items in a page.</label>
+
+          <button type="submit" class="btn btn-spark btn-sm">Go</button>
+        </form>
+      </div>
     </div>
   }
 
@@ -362,7 +364,7 @@ private[spark] trait PagedTable[T] {
 
           <th>
             <a href={headerLink}>
-              <span data-toggle="tooltip" data-placement="top" 
title={tooltip.getOrElse("")}>
+              <span data-bs-toggle="tooltip" data-bs-placement="top" 
title={tooltip.getOrElse("")}>
                 {header}&nbsp;{Unparsed(arrow)}
               </span>
             </a>
@@ -377,14 +379,15 @@ private[spark] trait PagedTable[T] {
 
             <th>
               <a href={headerLink}>
-                <span data-toggle="tooltip" data-placement="top" 
title={tooltip.getOrElse("")}>
+                <span data-bs-toggle="tooltip"
+                  data-bs-placement="top" title={tooltip.getOrElse("")}>
                   {header}
                 </span>
               </a>
             </th>
           } else {
             <th>
-              <span data-toggle="tooltip" data-placement="top" 
title={tooltip.getOrElse("")}>
+              <span data-bs-toggle="tooltip" data-bs-placement="top" 
title={tooltip.getOrElse("")}>
                 {header}
               </span>
             </th>
diff --git a/core/src/main/scala/org/apache/spark/ui/UIUtils.scala 
b/core/src/main/scala/org/apache/spark/ui/UIUtils.scala
index e84adbe710cb..6d00996d9e73 100644
--- a/core/src/main/scala/org/apache/spark/ui/UIUtils.scala
+++ b/core/src/main/scala/org/apache/spark/ui/UIUtils.scala
@@ -246,7 +246,7 @@ private[spark] object UIUtils extends Logging {
 
   def dataTablesHeaderNodes(request: HttpServletRequest): Seq[Node] = {
     <link rel="stylesheet"
-          href={prependBaseUri(request, 
"/static/dataTables.bootstrap4.min.css")}
+          href={prependBaseUri(request, 
"/static/dataTables.bootstrap5.min.css")}
           type="text/css"/>
     <link rel="stylesheet"
           href={prependBaseUri(request, "/static/jquery.dataTables.min.css")}
@@ -256,7 +256,7 @@ private[spark] object UIUtils extends Logging {
     <script src={prependBaseUri(request, 
"/static/jquery.dataTables.min.js")}></script>
     <script src={prependBaseUri(request, 
"/static/jquery.cookies.2.2.0.min.js")}></script>
     <script src={prependBaseUri(request, 
"/static/jquery.blockUI.min.js")}></script>
-    <script src={prependBaseUri(request, 
"/static/dataTables.bootstrap4.min.js")}></script>
+    <script src={prependBaseUri(request, 
"/static/dataTables.bootstrap5.min.js")}></script>
     <script src={prependBaseUri(request, 
"/static/jquery.mustache.js")}></script>
   }
 
@@ -300,13 +300,13 @@ private[spark] object UIUtils extends Logging {
               </a>
             </div>
           </div>
-          <button class="navbar-toggler" type="button" data-toggle="collapse"
-                  data-target="#navbarCollapse" aria-controls="navbarCollapse"
+          <button class="navbar-toggler" type="button" 
data-bs-toggle="collapse"
+                  data-bs-target="#navbarCollapse" 
aria-controls="navbarCollapse"
                   aria-expanded="false" aria-label="Toggle navigation">
             <span class="navbar-toggler-icon"></span>
           </button>
           <div class="collapse navbar-collapse" id="navbarCollapse">
-            <ul class="navbar-nav mr-auto">{header}</ul>
+            <ul class="navbar-nav me-auto">{header}</ul>
             <span class="navbar-text navbar-right d-none d-md-block">
               <strong title={appName} 
class="text-nowrap">{shortAppName}</strong>
               <span class="text-nowrap">application UI</span>
@@ -429,7 +429,7 @@ private[spark] object UIUtils extends Logging {
         getTooltip(x._2) match {
           case Some(tooltip) =>
             <th width={colWidthAttr} class={getClass(x._2)}>
-              <span data-toggle="tooltip" title={tooltip}>
+              <span data-bs-toggle="tooltip" title={tooltip}>
                 {getHeaderContent(x._1)}
               </span>
             </th>
@@ -509,8 +509,8 @@ private[spark] object UIUtils extends Logging {
       <span id={if (forJob) "job-dag-viz" else "stage-dag-viz"}
             class="expand-dag-viz" data-forjob={forJob.toString}>
         <span class="expand-dag-viz-arrow arrow-closed"></span>
-        <a data-toggle="tooltip" title={if (forJob) ToolTips.JOB_DAG else 
ToolTips.STAGE_DAG}
-           data-placement="top">
+        <a data-bs-toggle="tooltip" title={if (forJob) ToolTips.JOB_DAG else 
ToolTips.STAGE_DAG}
+           data-bs-placement="top">
           DAG Visualization
         </a>
       </span>
@@ -544,7 +544,7 @@ private[spark] object UIUtils extends Logging {
 
   def tooltip(text: String, position: String): Seq[Node] = {
     <sup>
-      (<a data-toggle="tooltip" data-placement={position} title={text}>?</a>)
+      (<a data-bs-toggle="tooltip" data-bs-placement={position} 
title={text}>?</a>)
     </sup>
   }
 
diff --git 
a/core/src/main/scala/org/apache/spark/ui/exec/ExecutorThreadDumpPage.scala 
b/core/src/main/scala/org/apache/spark/ui/exec/ExecutorThreadDumpPage.scala
index 000a88c0ac53..f1486539591e 100644
--- a/core/src/main/scala/org/apache/spark/ui/exec/ExecutorThreadDumpPage.scala
+++ b/core/src/main/scala/org/apache/spark/ui/exec/ExecutorThreadDumpPage.scala
@@ -94,11 +94,11 @@ private[ui] class ExecutorThreadDumpPage(
             <a class="expandbutton" 
data-action="expandAllThreadStackTrace">Expand All</a>
             <a class="expandbutton d-none" 
data-action="collapseAllThreadStackTrace">Collapse All</a>
             <a class="downloadbutton" href={"data:text/plain;charset=utf-8," + 
threadDump.map(_.toString).mkString} download={"threaddump_" + executorId + 
".txt"}>Download</a>
-            <div class="form-inline">
-              <div class="bs-example" data-example-id="simple-form-inline">
-                <div class="form-group">
+            <div class="d-flex">
+              <div class="bs-example" data-example-id="simple-d-flex">
+                <div class="mb-3">
                   <div class="input-group">
-                    <label class="mr-2" for="search">Search:</label>
+                    <label class="me-2" for="search">Search:</label>
                     <input type="text" class="form-control" id="search" 
data-search-input="true"></input>
                   </div>
                 </div>
@@ -113,7 +113,7 @@ private[ui] class ExecutorThreadDumpPage(
             <th data-action="collapseAllThreadStackTrace" 
data-toggle-button="false">Thread Name</th>
             <th data-action="collapseAllThreadStackTrace" 
data-toggle-button="false">Thread State</th>
             <th data-action="collapseAllThreadStackTrace" 
data-toggle-button="false">
-              <span data-toggle="tooltip" data-placement="top"
+              <span data-bs-toggle="tooltip" data-bs-placement="top"
                     title="Objects whose lock the thread currently holds">
                 Thread Locks
               </span>
diff --git a/core/src/main/scala/org/apache/spark/ui/jobs/AllJobsPage.scala 
b/core/src/main/scala/org/apache/spark/ui/jobs/AllJobsPage.scala
index a1a9fff53f64..ed9c1cbe17ce 100644
--- a/core/src/main/scala/org/apache/spark/ui/jobs/AllJobsPage.scala
+++ b/core/src/main/scala/org/apache/spark/ui/jobs/AllJobsPage.scala
@@ -105,7 +105,7 @@ private[ui] class AllJobsPage(parent: JobsTab, store: 
AppStatusStore) extends We
            |  'start': new Date(${submissionTime}),
            |  'end': new Date(${completionTime}),
            |  'content': '<div class="application-timeline-content"' +
-           |     'data-html="true" data-placement="top" data-toggle="tooltip"' 
+
+           |     'data-bs-html="true" data-bs-placement="top" 
data-bs-toggle="tooltip"' +
            |     'data-title="${jsEscapedDescForTooltip} (Job ${jobId})<br>' +
            |     'Status: ${status}<br>' +
            |     'Submitted: ${UIUtils.formatDate(new Date(submissionTime))}' +
@@ -136,10 +136,10 @@ private[ui] class AllJobsPage(parent: JobsTab, store: 
AppStatusStore) extends We
            |  'group': 'executors',
            |  'start': new Date(${e.addTime.getTime()}),
            |  'content': '<div class="executor-event-content"' +
-           |    'data-toggle="tooltip" data-placement="top"' +
+           |    'data-bs-toggle="tooltip" data-bs-placement="top"' +
            |    'data-title="Executor ${e.id}<br>' +
            |    'Added at ${UIUtils.formatDate(e.addTime)}"' +
-           |    'data-html="true">Executor ${e.id} added</div>'
+           |    'data-bs-html="true">Executor ${e.id} added</div>'
            |}
          """.stripMargin
       events += addedEvent
@@ -152,7 +152,7 @@ private[ui] class AllJobsPage(parent: JobsTab, store: 
AppStatusStore) extends We
              |  'group': 'executors',
              |  'start': new Date(${removeTime.getTime()}),
              |  'content': '<div class="executor-event-content"' +
-             |    'data-toggle="tooltip" data-placement="top"' +
+             |    'data-bs-toggle="tooltip" data-bs-placement="top"' +
              |    'data-title="Executor ${e.id}<br>' +
              |    'Removed at ${UIUtils.formatDate(removeTime)}' +
              |    '${
@@ -161,7 +161,7 @@ private[ui] class AllJobsPage(parent: JobsTab, store: 
AppStatusStore) extends We
                           reason.replace("\n", " "))}"""
                       }.getOrElse("")
                    }"' +
-             |    'data-html="true">Executor ${e.id} removed</div>'
+             |    'data-bs-html="true">Executor ${e.id} removed</div>'
              |}
            """.stripMargin
         events += removedEvent
@@ -199,7 +199,7 @@ private[ui] class AllJobsPage(parent: JobsTab, store: 
AppStatusStore) extends We
 
     <span class="expand-application-timeline">
       <span class="expand-application-timeline-arrow arrow-closed"></span>
-      <a data-toggle="tooltip" title={ToolTips.JOB_TIMELINE} 
data-placement="top">
+      <a data-bs-toggle="tooltip" title={ToolTips.JOB_TIMELINE} 
data-bs-placement="top">
         Event Timeline
       </a>
     </span> ++
@@ -266,7 +266,7 @@ private[ui] class AllJobsPage(parent: JobsTab, store: 
AppStatusStore) extends We
       ).table(jobPage)
     } catch {
       case e @ (_ : IllegalArgumentException | _ : IndexOutOfBoundsException) 
=>
-        <div class="alert alert-error">
+        <div class="alert alert-danger">
           <p>Error while rendering job table:</p>
           <pre>
             {Utils.exceptionString(e)}
diff --git a/core/src/main/scala/org/apache/spark/ui/jobs/JobPage.scala 
b/core/src/main/scala/org/apache/spark/ui/jobs/JobPage.scala
index 2f5e3a8e098b..8820a7b1661e 100644
--- a/core/src/main/scala/org/apache/spark/ui/jobs/JobPage.scala
+++ b/core/src/main/scala/org/apache/spark/ui/jobs/JobPage.scala
@@ -86,8 +86,8 @@ private[ui] class JobPage(parent: JobsTab, store: 
AppStatusStore) extends WebUIP
          |  'group': 'stages',
          |  'start': new Date(${submissionTime}),
          |  'end': new Date(${completionTime}),
-         |  'content': '<div class="job-timeline-content" 
data-toggle="tooltip"' +
-         |   'data-placement="top" data-html="true"' +
+         |  'content': '<div class="job-timeline-content" 
data-bs-toggle="tooltip"' +
+         |   'data-bs-placement="top" data-bs-html="true"' +
          |   'data-title="${jsEscapedNameForTooltip} (Stage 
${stageId}.${attemptId})<br>' +
          |   'Status: ${status.toUpperCase(Locale.ROOT)}<br>' +
          |   'Submitted: ${UIUtils.formatDate(submissionTime)}' +
@@ -116,10 +116,10 @@ private[ui] class JobPage(parent: JobsTab, store: 
AppStatusStore) extends WebUIP
            |  'group': 'executors',
            |  'start': new Date(${e.addTime.getTime()}),
            |  'content': '<div class="executor-event-content"' +
-           |    'data-toggle="tooltip" data-placement="top"' +
+           |    'data-bs-toggle="tooltip" data-bs-placement="top"' +
            |    'data-title="Executor ${e.id}<br>' +
            |    'Added at ${UIUtils.formatDate(e.addTime)}"' +
-           |    'data-html="true">Executor ${e.id} added</div>'
+           |    'data-bs-html="true">Executor ${e.id} added</div>'
            |}
          """.stripMargin
       events += addedEvent
@@ -132,7 +132,7 @@ private[ui] class JobPage(parent: JobsTab, store: 
AppStatusStore) extends WebUIP
              |  'group': 'executors',
              |  'start': new Date(${removeTime.getTime()}),
              |  'content': '<div class="executor-event-content"' +
-             |    'data-toggle="tooltip" data-placement="top"' +
+             |    'data-bs-toggle="tooltip" data-bs-placement="top"' +
              |    'data-title="Executor ${e.id}<br>' +
              |    'Removed at ${UIUtils.formatDate(removeTime)}' +
              |    '${
@@ -141,7 +141,7 @@ private[ui] class JobPage(parent: JobsTab, store: 
AppStatusStore) extends WebUIP
                           reason.replace("\n", " "))}"""
                       }.getOrElse("")
                    }"' +
-             |    'data-html="true">Executor ${e.id} removed</div>'
+             |    'data-bs-html="true">Executor ${e.id} removed</div>'
              |}
            """.stripMargin
           events += removedEvent
@@ -179,7 +179,7 @@ private[ui] class JobPage(parent: JobsTab, store: 
AppStatusStore) extends WebUIP
 
     <span class="expand-job-timeline">
       <span class="expand-job-timeline-arrow arrow-closed"></span>
-      <a data-toggle="tooltip" title={ToolTips.STAGE_TIMELINE} 
data-placement="top">
+      <a data-bs-toggle="tooltip" title={ToolTips.STAGE_TIMELINE} 
data-bs-placement="top">
         Event Timeline
       </a>
     </span> ++
diff --git a/core/src/main/scala/org/apache/spark/ui/jobs/PoolTable.scala 
b/core/src/main/scala/org/apache/spark/ui/jobs/PoolTable.scala
index a6b2a029f71e..cb4ed7190ad7 100644
--- a/core/src/main/scala/org/apache/spark/ui/jobs/PoolTable.scala
+++ b/core/src/main/scala/org/apache/spark/ui/jobs/PoolTable.scala
@@ -37,11 +37,12 @@ private[ui] class PoolTable(pools: Map[Schedulable, 
PoolData], parent: StagesTab
         <tr>
           <th>Pool Name</th>
           <th>
-            <span data-toggle="tooltip" data-placement="top" title="Pool's 
minimum share of CPU
+            <span data-bs-toggle="tooltip" data-bs-placement="top"
+              title="Pool's minimum share of CPU
              cores">Minimum Share</span>
           </th>
           <th>
-            <span data-toggle="tooltip" data-placement="top" title="Pool's 
share of cluster
+            <span data-bs-toggle="tooltip" data-bs-placement="top" 
title="Pool's share of cluster
              resources relative to others">Pool Weight</span>
           </th>
           <th>Active Stages</th>
diff --git a/core/src/main/scala/org/apache/spark/ui/jobs/StagePage.scala 
b/core/src/main/scala/org/apache/spark/ui/jobs/StagePage.scala
index 9d246a414714..935eb8bb52cc 100644
--- a/core/src/main/scala/org/apache/spark/ui/jobs/StagePage.scala
+++ b/core/src/main/scala/org/apache/spark/ui/jobs/StagePage.scala
@@ -361,8 +361,8 @@ private[ui] class StagePage(parent: StagesTab, store: 
AppStatusStore) extends We
                |'className': 'task task-assignment-timeline-object',
                |'group': '$executorId',
                |'content': '<div class="task-assignment-timeline-content"
-                 |data-toggle="tooltip" data-placement="top"
-                 |data-html="true" data-container="body"
+                 |data-bs-toggle="tooltip" data-bs-placement="top"
+                 |data-bs-html="true" data-bs-container="body"
                  |data-title="${"Task " + index + " (attempt " + attempt + 
")"}<br>
                  |Status: ${taskInfo.status}<br>
                  |Launch Time: ${UIUtils.formatDate(new Date(launchTime))}
@@ -422,7 +422,7 @@ private[ui] class StagePage(parent: StagesTab, store: 
AppStatusStore) extends We
           <form id={"form-event-timeline-page"}
                 method="get"
                 action=""
-                class="form-inline float-right justify-content-end"
+                class="d-flex float-end justify-content-end align-items-center 
gap-1"
                 style="margin-bottom: 0px;">
             <label>Tasks: {totalTasks}. {totalPages} Pages. Jump to</label>
             <input type="hidden" name="id" value={stageId.toString} />
@@ -431,14 +431,14 @@ private[ui] class StagePage(parent: StagesTab, store: 
AppStatusStore) extends We
                    name="task.eventTimelinePageNumber"
                    id={"form-event-timeline-page-no"}
                    value={page.toString}
-                   class="col-1 form-control" />
+                   class="form-control form-control-sm" style="width: 60px;" />
 
             <label>. Show </label>
             <input type="text"
                    id={"form-event-timeline-page-size"}
                    name="task.eventTimelinePageSize"
                    value={pageSize.toString}
-                   class="col-1 form-control" />
+                   class="form-control form-control-sm" style="width: 60px;" />
             <label>items in a page.</label>
 
             <button type="submit" class="btn btn-spark">Go</button>
diff --git a/core/src/main/scala/org/apache/spark/ui/jobs/StageTable.scala 
b/core/src/main/scala/org/apache/spark/ui/jobs/StageTable.scala
index e3064ed9a0cb..d7bbb1481774 100644
--- a/core/src/main/scala/org/apache/spark/ui/jobs/StageTable.scala
+++ b/core/src/main/scala/org/apache/spark/ui/jobs/StageTable.scala
@@ -62,7 +62,7 @@ private[ui] class StageTableBase(
     ).table(stagePage)
   } catch {
     case e @ (_ : IllegalArgumentException | _ : IndexOutOfBoundsException) =>
-      <div class="alert alert-error">
+      <div class="alert alert-danger">
         <p>Error while rendering stage table:</p>
         <pre>
           {Utils.exceptionString(e)}
diff --git 
a/core/src/main/scala/org/apache/spark/ui/jobs/TaskThreadDumpPage.scala 
b/core/src/main/scala/org/apache/spark/ui/jobs/TaskThreadDumpPage.scala
index 5fe542d4fa21..ac595b810d62 100644
--- a/core/src/main/scala/org/apache/spark/ui/jobs/TaskThreadDumpPage.scala
+++ b/core/src/main/scala/org/apache/spark/ui/jobs/TaskThreadDumpPage.scala
@@ -78,7 +78,7 @@ private[spark] class TaskThreadDumpPage(
               <th>Thread Name</th>
               <th>Thread State</th>
               <th>
-                <span data-toggle="tooltip" data-placement="top"
+                <span data-bs-toggle="tooltip" data-bs-placement="top"
                       title="Objects whose lock the thread currently holds">
                   Thread Locks
                 </span>
diff --git a/core/src/main/scala/org/apache/spark/ui/storage/RDDPage.scala 
b/core/src/main/scala/org/apache/spark/ui/storage/RDDPage.scala
index ff11816835ec..4eb59bf855fe 100644
--- a/core/src/main/scala/org/apache/spark/ui/storage/RDDPage.scala
+++ b/core/src/main/scala/org/apache/spark/ui/storage/RDDPage.scala
@@ -61,7 +61,7 @@ private[ui] class RDDPage(parent: SparkUITab, store: 
AppStatusStore) extends Web
       _blockTable.table(blockPage)
     } catch {
       case e @ (_ : IllegalArgumentException | _ : IndexOutOfBoundsException) 
=>
-        <div class="alert alert-error">{e.getMessage}</div>
+        <div class="alert alert-danger">{e.getMessage}</div>
     }
 
     val jsForScrollingDownToBlockTable =
diff --git a/core/src/test/scala/org/apache/spark/ui/UIUtilsSuite.scala 
b/core/src/test/scala/org/apache/spark/ui/UIUtilsSuite.scala
index ec05eda8c128..c0753a2af8be 100644
--- a/core/src/test/scala/org/apache/spark/ui/UIUtilsSuite.scala
+++ b/core/src/test/scala/org/apache/spark/ui/UIUtilsSuite.scala
@@ -158,7 +158,7 @@ class UIUtilsSuite extends SparkFunSuite {
         <thead>
           <th width="" class="">{header(0)}</th>
           <th width="" class="">
-              <span data-toggle="tooltip" title="tooltip">
+              <span data-bs-toggle="tooltip" title="tooltip">
                 {header(1)}
               </span>
           </th>
diff --git 
a/core/src/test/scala/org/apache/spark/ui/storage/StoragePageSuite.scala 
b/core/src/test/scala/org/apache/spark/ui/storage/StoragePageSuite.scala
index 7f8cba0c3918..ada799c863ee 100644
--- a/core/src/test/scala/org/apache/spark/ui/storage/StoragePageSuite.scala
+++ b/core/src/test/scala/org/apache/spark/ui/storage/StoragePageSuite.scala
@@ -81,7 +81,7 @@ class StoragePageSuite extends SparkFunSuite {
         storagePage.tooltips(x._2) match {
           case Some(tooltip) =>
             <th width={""} class={""}>
-              <span data-toggle="tooltip" title={tooltip}>
+              <span data-bs-toggle="tooltip" title={tooltip}>
                 {Text(x._1)}
               </span>
             </th>
diff --git a/dev/.rat-excludes b/dev/.rat-excludes
index 725287810000..5867bae4bea1 100644
--- a/dev/.rat-excludes
+++ b/dev/.rat-excludes
@@ -32,8 +32,8 @@ graphlib-dot.min.js
 sorttable.js
 vis-timeline-graph2d.min.js
 vis-timeline-graph2d.min.css
-dataTables.bootstrap4.min.css
-dataTables.bootstrap4.min.js
+dataTables.bootstrap5.min.css
+dataTables.bootstrap5.min.js
 dataTables.rowsGroup.js
 jquery.blockUI.min.js
 jquery.cookies.2.2.0.min.js
diff --git a/dev/eslint.js b/dev/eslint.js
index abb06526fe96..51df12a5f68f 100644
--- a/dev/eslint.js
+++ b/dev/eslint.js
@@ -21,6 +21,9 @@ module.exports = {
     "es6": true,
     "jest": true
   },
+  "globals": {
+    "bootstrap": "readonly"
+  },
   "extends": "eslint:recommended",
   "rules": {
     "indent": [
diff --git a/docs/_layouts/global.html b/docs/_layouts/global.html
index 6938b118a21c..ef71211e6c8d 100755
--- a/docs/_layouts/global.html
+++ b/docs/_layouts/global.html
@@ -59,8 +59,8 @@
             <div class="navbar-brand"><a href="{{ rel_path_to_root 
}}index.html">
                 <img src="https://spark.apache.org/images/spark-logo-rev.svg"; 
width="141" height="72"/></a><span 
class="version">{{site.SPARK_VERSION_SHORT}}</span>
             </div>
-            <button class="navbar-toggler" type="button" data-toggle="collapse"
-                    data-target="#navbarCollapse" 
aria-controls="navbarCollapse"
+            <button class="navbar-toggler" type="button" 
data-bs-toggle="collapse"
+                    data-bs-target="#navbarCollapse" 
aria-controls="navbarCollapse"
                     aria-expanded="false" aria-label="Toggle navigation">
                 <span class="navbar-toggler-icon"></span>
             </button>
@@ -69,7 +69,7 @@
                     <li class="nav-item"><a href="{{ rel_path_to_root 
}}index.html" class="nav-link">Overview</a></li>
 
                     <li class="nav-item dropdown">
-                        <a href="#" class="nav-link dropdown-toggle" 
id="navbarQuickStart" role="button" data-toggle="dropdown" aria-haspopup="true" 
aria-expanded="false">Programming Guides</a>
+                        <a href="#" class="nav-link dropdown-toggle" 
id="navbarQuickStart" role="button" data-bs-toggle="dropdown" 
aria-haspopup="true" aria-expanded="false">Programming Guides</a>
                         <div class="dropdown-menu" 
aria-labelledby="navbarQuickStart">
                             <a class="dropdown-item" href="{{ rel_path_to_root 
}}quick-start.html">Quick Start</a>
                             <a class="dropdown-item" href="{{ rel_path_to_root 
}}rdd-programming-guide.html">RDDs, Accumulators, Broadcasts Vars</a>
@@ -85,7 +85,7 @@
                     </li>
 
                     <li class="nav-item dropdown">
-                        <a href="#" class="nav-link dropdown-toggle" 
id="navbarAPIDocs" role="button" data-toggle="dropdown" aria-haspopup="true" 
aria-expanded="false">API Docs</a>
+                        <a href="#" class="nav-link dropdown-toggle" 
id="navbarAPIDocs" role="button" data-bs-toggle="dropdown" aria-haspopup="true" 
aria-expanded="false">API Docs</a>
                         <div class="dropdown-menu" 
aria-labelledby="navbarAPIDocs">
                             <a class="dropdown-item" href="{{ rel_path_to_root 
}}api/python/index.html">Python</a>
                             <a class="dropdown-item" href="{{ rel_path_to_root 
}}api/scala/org/apache/spark/index.html">Scala</a>
@@ -96,7 +96,7 @@
                     </li>
 
                     <li class="nav-item dropdown">
-                        <a href="#" class="nav-link dropdown-toggle" 
id="navbarDeploying" role="button" data-toggle="dropdown" aria-haspopup="true" 
aria-expanded="false">Deploying</a>
+                        <a href="#" class="nav-link dropdown-toggle" 
id="navbarDeploying" role="button" data-bs-toggle="dropdown" 
aria-haspopup="true" aria-expanded="false">Deploying</a>
                         <div class="dropdown-menu" 
aria-labelledby="navbarDeploying">
                             <a class="dropdown-item" href="{{ rel_path_to_root 
}}cluster-overview.html">Overview</a>
                             <a class="dropdown-item" href="{{ rel_path_to_root 
}}submitting-applications.html">Submitting Applications</a>
@@ -108,7 +108,7 @@
                     </li>
 
                     <li class="nav-item dropdown">
-                        <a href="#" class="nav-link dropdown-toggle" 
id="navbarMore" role="button" data-toggle="dropdown" aria-haspopup="true" 
aria-expanded="false">More</a>
+                        <a href="#" class="nav-link dropdown-toggle" 
id="navbarMore" role="button" data-bs-toggle="dropdown" aria-haspopup="true" 
aria-expanded="false">More</a>
                         <div class="dropdown-menu" 
aria-labelledby="navbarMore">
                             <a class="dropdown-item" href="{{ rel_path_to_root 
}}configuration.html">Configuration</a>
                             <a class="dropdown-item" href="{{ rel_path_to_root 
}}monitoring.html">Monitoring</a>
diff --git 
a/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/ui/SparkConnectServerPage.scala
 
b/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/ui/SparkConnectServerPage.scala
index 9e9243fe9f72..d374a70a02b8 100644
--- 
a/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/ui/SparkConnectServerPage.scala
+++ 
b/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/ui/SparkConnectServerPage.scala
@@ -93,7 +93,7 @@ private[ui] class SparkConnectServerPage(parent: 
SparkConnectServerTab)
             showSessionLink = true).table(sqlTablePage))
       } catch {
         case e @ (_: IllegalArgumentException | _: IndexOutOfBoundsException) 
=>
-          Some(<div class="alert alert-error">
+          Some(<div class="alert alert-danger">
             <p>Error while rendering job table:</p>
             <pre>
               {Utils.exceptionString(e)}
@@ -139,7 +139,7 @@ private[ui] class SparkConnectServerPage(parent: 
SparkConnectServerTab)
             sessionTableTag).table(sessionTablePage))
       } catch {
         case e @ (_: IllegalArgumentException | _: IndexOutOfBoundsException) 
=>
-          Some(<div class="alert alert-error">
+          Some(<div class="alert alert-danger">
             <p>Error while rendering job table:</p>
             <pre>
               {Utils.exceptionString(e)}
diff --git 
a/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/ui/SparkConnectServerSessionPage.scala
 
b/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/ui/SparkConnectServerSessionPage.scala
index ac360c8b3219..f6a1cf18721e 100644
--- 
a/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/ui/SparkConnectServerSessionPage.scala
+++ 
b/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/ui/SparkConnectServerSessionPage.scala
@@ -103,7 +103,7 @@ private[ui] class SparkConnectServerSessionPage(parent: 
SparkConnectServerTab)
             showSessionLink = false).table(sqlTablePage))
       } catch {
         case e @ (_: IllegalArgumentException | _: IndexOutOfBoundsException) 
=>
-          Some(<div class="alert alert-error">
+          Some(<div class="alert alert-danger">
             <p>Error while rendering job table:</p>
             <pre>
               {Utils.exceptionString(e)}
diff --git 
a/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/ui/SparkConnectServerPageSuite.scala
 
b/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/ui/SparkConnectServerPageSuite.scala
index 7ae7a68be5f3..3fc00f609779 100644
--- 
a/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/ui/SparkConnectServerPageSuite.scala
+++ 
b/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/ui/SparkConnectServerPageSuite.scala
@@ -97,7 +97,7 @@ class SparkConnectServerPageSuite
     assert(html.contains("dummy query"))
 
     // Pagination support
-    assert(html.contains("<label>1 pages. jump to</label>"))
+    assert(html.contains("<label style=\"white-space: nowrap;\">1 pages. jump 
to</label>"))
 
     // Hiding table support
     assert(
@@ -124,7 +124,7 @@ class SparkConnectServerPageSuite
     assert(html.contains("jobtag"))
 
     // Pagination support
-    assert(html.contains("<label>1 pages. jump to</label>"))
+    assert(html.contains("<label style=\"white-space: nowrap;\">1 pages. jump 
to</label>"))
 
     // Hiding table support
     assert(
diff --git 
a/sql/core/src/main/scala/org/apache/spark/sql/execution/ui/AllExecutionsPage.scala
 
b/sql/core/src/main/scala/org/apache/spark/sql/execution/ui/AllExecutionsPage.scala
index 8d0dc154906a..552158ae08ec 100644
--- 
a/sql/core/src/main/scala/org/apache/spark/sql/execution/ui/AllExecutionsPage.scala
+++ 
b/sql/core/src/main/scala/org/apache/spark/sql/execution/ui/AllExecutionsPage.scala
@@ -221,7 +221,7 @@ private[ui] class AllExecutionsPage(parent: SQLTab) extends 
WebUIPage("") with L
         executionIdToSubExecutions).table(executionPage)
     } catch {
       case e@(_: IllegalArgumentException | _: IndexOutOfBoundsException) =>
-        <div class="alert alert-error">
+        <div class="alert alert-danger">
           <p>Error while rendering execution table:</p>
           <pre>
             {Utils.exceptionString(e)}
diff --git 
a/sql/core/src/main/scala/org/apache/spark/sql/streaming/ui/StreamingQueryPage.scala
 
b/sql/core/src/main/scala/org/apache/spark/sql/streaming/ui/StreamingQueryPage.scala
index d7f13153078e..d60af8fb181d 100644
--- 
a/sql/core/src/main/scala/org/apache/spark/sql/streaming/ui/StreamingQueryPage.scala
+++ 
b/sql/core/src/main/scala/org/apache/spark/sql/streaming/ui/StreamingQueryPage.scala
@@ -102,7 +102,7 @@ private[ui] class StreamingQueryPage(parent: 
StreamingQueryTab)
       ).table(page)
     } catch {
       case e@(_: IllegalArgumentException | _: IndexOutOfBoundsException) =>
-        <div class="alert alert-error">
+        <div class="alert alert-danger">
           <p>Error while rendering execution table:</p>
           <pre>
             {Utils.exceptionString(e)}
diff --git 
a/sql/hive-thriftserver/src/main/scala/org/apache/spark/sql/hive/thriftserver/ui/ThriftServerPage.scala
 
b/sql/hive-thriftserver/src/main/scala/org/apache/spark/sql/hive/thriftserver/ui/ThriftServerPage.scala
index 0f431959f9c4..16ad10ac3e3a 100644
--- 
a/sql/hive-thriftserver/src/main/scala/org/apache/spark/sql/hive/thriftserver/ui/ThriftServerPage.scala
+++ 
b/sql/hive-thriftserver/src/main/scala/org/apache/spark/sql/hive/thriftserver/ui/ThriftServerPage.scala
@@ -88,7 +88,7 @@ private[ui] class ThriftServerPage(parent: ThriftServerTab) 
extends WebUIPage(""
           sqlTableTag).table(sqlTablePage))
       } catch {
         case e@(_: IllegalArgumentException | _: IndexOutOfBoundsException) =>
-          Some(<div class="alert alert-error">
+          Some(<div class="alert alert-danger">
             <p>Error while rendering job table:</p>
             <pre>
               {Utils.exceptionString(e)}
@@ -134,7 +134,7 @@ private[ui] class ThriftServerPage(parent: ThriftServerTab) 
extends WebUIPage(""
         ).table(sessionTablePage))
       } catch {
         case e@(_: IllegalArgumentException | _: IndexOutOfBoundsException) =>
-          Some(<div class="alert alert-error">
+          Some(<div class="alert alert-danger">
             <p>Error while rendering job table:</p>
             <pre>
               {Utils.exceptionString(e)}
diff --git 
a/sql/hive-thriftserver/src/main/scala/org/apache/spark/sql/hive/thriftserver/ui/ThriftServerSessionPage.scala
 
b/sql/hive-thriftserver/src/main/scala/org/apache/spark/sql/hive/thriftserver/ui/ThriftServerSessionPage.scala
index f0b7c59f22b4..140161ff25fd 100644
--- 
a/sql/hive-thriftserver/src/main/scala/org/apache/spark/sql/hive/thriftserver/ui/ThriftServerSessionPage.scala
+++ 
b/sql/hive-thriftserver/src/main/scala/org/apache/spark/sql/hive/thriftserver/ui/ThriftServerSessionPage.scala
@@ -90,7 +90,7 @@ private[ui] class ThriftServerSessionPage(parent: 
ThriftServerTab)
         ).table(sqlTablePage))
       } catch {
         case e@(_: IllegalArgumentException | _: IndexOutOfBoundsException) =>
-          Some(<div class="alert alert-error">
+          Some(<div class="alert alert-danger">
             <p>Error while rendering job table:</p>
             <pre>
               {Utils.exceptionString(e)}
diff --git 
a/sql/hive-thriftserver/src/test/scala/org/apache/spark/sql/hive/thriftserver/ui/ThriftServerPageSuite.scala
 
b/sql/hive-thriftserver/src/test/scala/org/apache/spark/sql/hive/thriftserver/ui/ThriftServerPageSuite.scala
index 34dadd628148..ae169491edf8 100644
--- 
a/sql/hive-thriftserver/src/test/scala/org/apache/spark/sql/hive/thriftserver/ui/ThriftServerPageSuite.scala
+++ 
b/sql/hive-thriftserver/src/test/scala/org/apache/spark/sql/hive/thriftserver/ui/ThriftServerPageSuite.scala
@@ -98,7 +98,7 @@ class ThriftServerPageSuite extends SparkFunSuite with 
BeforeAndAfter {
     assert(html.contains("dummy plan"))
 
     // Pagination support
-    assert(html.contains("<label>1 pages. jump to</label>"))
+    assert(html.contains("<label style=\"white-space: nowrap;\">1 pages. jump 
to</label>"))
 
     // Hiding table support
     assert(html.contains("class=\"collapse-aggregated-sessionstat" +
@@ -124,7 +124,7 @@ class ThriftServerPageSuite extends SparkFunSuite with 
BeforeAndAfter {
     assert(html.contains("groupid"))
 
     // Pagination support
-    assert(html.contains("<label>1 pages. jump to</label>"))
+    assert(html.contains("<label style=\"white-space: nowrap;\">1 pages. jump 
to</label>"))
 
     // Hiding table support
     assert(html.contains("collapse-aggregated-sqlsessionstat collapse-table\"" 
+
diff --git 
a/streaming/src/main/scala/org/apache/spark/streaming/ui/StreamingPage.scala 
b/streaming/src/main/scala/org/apache/spark/streaming/ui/StreamingPage.scala
index 8dbe5df5af12..7a74c2135947 100644
--- a/streaming/src/main/scala/org/apache/spark/streaming/ui/StreamingPage.scala
+++ b/streaming/src/main/scala/org/apache/spark/streaming/ui/StreamingPage.scala
@@ -281,7 +281,7 @@ private[ui] class StreamingPage(parent: StreamingTab)
                 if (hasStream) {
                   <span class="expand-input-rate">
                     <span class="expand-input-rate-arrow arrow-closed"></span>
-                    <a data-toggle="tooltip" title="Show/hide details of each 
receiver" data-placement="top">
+                    <a data-bs-toggle="tooltip" title="Show/hide details of 
each receiver" data-bs-placement="top">
                       <strong>Input Rate</strong>
                     </a>
                   </span>
@@ -459,7 +459,7 @@ private[ui] class StreamingPage(parent: StreamingTab)
       ).table(streamingPage)
     } catch {
       case e @ (_: IllegalArgumentException | _: IndexOutOfBoundsException) =>
-        <div class="alert alert-error">
+        <div class="alert alert-danger">
           <p>Error while rendering streaming table:</p>
           <pre>
             {Utils.exceptionString(e)}


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

Reply via email to