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 eae012e75dbd [SPARK-55773][UI] Replace custom collapse/toggle system 
with Bootstrap 5 Collapse API
eae012e75dbd is described below

commit eae012e75dbd8edb23271ea1c5075eaf801aa447
Author: Kent Yao <[email protected]>
AuthorDate: Tue Mar 3 11:52:28 2026 +0800

    [SPARK-55773][UI] Replace custom collapse/toggle system with Bootstrap 5 
Collapse API
    
    ### What changes were proposed in this pull request?
    
    This PR replaces the custom JavaScript collapse/toggle system 
(`collapseTable`, `collapseTablePageLoad`, arrow-open/closed classes) with the 
native Bootstrap 5 Collapse API across the entire Spark Web UI.
    
    ### Key Changes
    
    **JavaScript (`webui.js`)**
    - Removed custom `collapseTable()` and `collapseTablePageLoad()` functions
    - Removed 45+ individual `collapseTablePageLoad()` registration calls and 
click handler
    - Added BS5 event-based localStorage persistence using `shown.bs.collapse` 
/ `hidden.bs.collapse` events
    - Added page-load restore handler that reads localStorage and collapses 
previously-collapsed sections
    
    **JavaScript (`table.js`)**
    - Removed `collapseTableAndButton()` function (was used for legacy 
collapse-with-button pattern)
    
    **Scala HTML generators (21 files)**
    - Converted all collapsible sections to use `data-bs-toggle="collapse"` + 
`data-bs-target="#id"` on trigger elements
    - Added `collapse show` classes on content elements (initially visible)
    - Added `aria-expanded="true"` for accessibility
    - Kept `data-collapse-name` for localStorage key compatibility
    
    ### Affected pages
    - Environment (7 sections: Runtime, Spark Props, Resource Profiles, Hadoop, 
System, Metrics, Classpath)
    - Jobs (event timeline, active/completed/failed tables)
    - Job detail (event timeline, stages tables)
    - Stages (pool table, active/pending/completed/failed tables)
    - Pool page (stages table)
    - Storage (RDD table)
    - Executor thread dump (summary, stack trace tables)
    - SQL executions (running/completed/failed tables)
    - SQL execution detail (physical plan)
    - Streaming (timelines, histograms, receivers)
    - Streaming Query page (active/completed tables)
    - ThriftServer pages (session/operation tables)
    - Spark Connect Server pages (session/operation tables)
    - Standalone Master page (workers, apps, drivers)
    - Standalone Worker page (executors, drivers)
    - Standalone Application page (executors)
    
    ### Why are the changes needed?
    
    Part of the Bootstrap 5 migration umbrella (SPARK-55760). The custom 
collapse system predates BS5 and duplicates functionality that BS5 provides 
natively with better accessibility support (`aria-expanded`, keyboard 
navigation) and simpler code.
    
    ### Does this PR introduce _any_ user-facing change?
    
    No functional change. Collapse/expand behavior and localStorage persistence 
work identically.
    
    ### How was this patch tested?
    
    - Existing unit tests pass (`EnvironmentPageSuite`, `StoragePageSuite`, 
`ThriftServerPageSuite`, `SparkConnectServerPageSuite`)
    - Manual testing of collapse behavior across all affected pages
    - Verified localStorage persistence (collapse → reload → stays collapsed)
    - Scalastyle checks pass
    
    ### Screenshots
    
    **Jobs page** (all sections expanded):
    <img 
src="https://raw.githubusercontent.com/yaooqinn/spark/SPARK-55786-screenshots/screenshots/SPARK-55773/jobs.png";
 width="800">
    
    **Jobs page** (sections collapsed):
    <img 
src="https://raw.githubusercontent.com/yaooqinn/spark/SPARK-55786-screenshots/screenshots/SPARK-55773/jobs_collapsed.png";
 width="800">
    
    **Stages page:**
    <img 
src="https://raw.githubusercontent.com/yaooqinn/spark/SPARK-55786-screenshots/screenshots/SPARK-55773/stages.png";
 width="800">
    
    **Environment page** (all sections expanded):
    <img 
src="https://raw.githubusercontent.com/yaooqinn/spark/SPARK-55786-screenshots/screenshots/SPARK-55773/environment.png";
 width="800">
    
    **Environment page** (first 3 sections collapsed):
    <img 
src="https://raw.githubusercontent.com/yaooqinn/spark/SPARK-55786-screenshots/screenshots/SPARK-55773/environment_collapsed.png";
 width="800">
    
    **Storage page:**
    <img 
src="https://raw.githubusercontent.com/yaooqinn/spark/SPARK-55786-screenshots/screenshots/SPARK-55773/storage.png";
 width="800">
    
    **SQL Executions page:**
    <img 
src="https://raw.githubusercontent.com/yaooqinn/spark/SPARK-55786-screenshots/screenshots/SPARK-55773/sql.png";
 width="800">
    
    **SQL Execution detail:**
    <img 
src="https://raw.githubusercontent.com/yaooqinn/spark/SPARK-55786-screenshots/screenshots/SPARK-55773/sql_detail.png";
 width="800">
    
    **Job detail:**
    <img 
src="https://raw.githubusercontent.com/yaooqinn/spark/SPARK-55786-screenshots/screenshots/SPARK-55773/job_detail.png";
 width="800">
    
    **Stage detail:**
    <img 
src="https://raw.githubusercontent.com/yaooqinn/spark/SPARK-55786-screenshots/screenshots/SPARK-55773/stage_detail.png";
 width="800">
    
    Closes #54574 from yaooqinn/SPARK-55773.
    
    Authored-by: Kent Yao <[email protected]>
    Signed-off-by: Kent Yao <[email protected]>
---
 .../resources/org/apache/spark/ui/static/table.js  |  15 +--
 .../resources/org/apache/spark/ui/static/webui.js  | 116 ++++++---------------
 .../spark/deploy/master/ui/ApplicationPage.scala   |  20 ++--
 .../spark/deploy/master/ui/EnvironmentPage.scala   |  63 ++++++-----
 .../apache/spark/deploy/master/ui/MasterPage.scala |  52 +++++----
 .../apache/spark/deploy/worker/ui/WorkerPage.scala |  40 ++++---
 .../org/apache/spark/ui/env/EnvironmentPage.scala  |  65 +++++++-----
 .../spark/ui/exec/ExecutorThreadDumpPage.scala     |  54 ++++++----
 .../org/apache/spark/ui/jobs/AllJobsPage.scala     |  27 ++---
 .../org/apache/spark/ui/jobs/AllStagesPage.scala   |  18 ++--
 .../scala/org/apache/spark/ui/jobs/JobPage.scala   |  45 ++++----
 .../scala/org/apache/spark/ui/jobs/PoolPage.scala  |   9 +-
 .../org/apache/spark/ui/storage/StoragePage.scala  |   9 +-
 .../sql/connect/ui/SparkConnectServerPage.scala    |  18 ++--
 .../connect/ui/SparkConnectServerSessionPage.scala |   9 +-
 .../connect/ui/SparkConnectServerPageSuite.scala   |   8 +-
 .../spark/sql/execution/ui/AllExecutionsPage.scala |  29 +++---
 .../spark/sql/execution/ui/ExecutionPage.scala     |  18 ++--
 .../sql/streaming/ui/StreamingQueryPage.scala      |  23 ++--
 .../hive/thriftserver/ui/ThriftServerPage.scala    |  18 ++--
 .../thriftserver/ui/ThriftServerSessionPage.scala  |   9 +-
 .../thriftserver/ui/ThriftServerPageSuite.scala    |   8 +-
 .../apache/spark/streaming/ui/StreamingPage.scala  |  34 +++---
 23 files changed, 363 insertions(+), 344 deletions(-)

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 1e99b13f7ccb..34155c817cee 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
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-/* global $, d3, collapseTable */
+/* global $ */
 /* eslint-disable no-unused-vars */
 /* Adds background colors to stripe table rows in the summary table (on the 
stage page). This is
  * necessary (instead of using css or the table striping provided by 
bootstrap) because the summary
@@ -105,19 +105,6 @@ function onSearchStringChange() {
 }
 /* eslint-enable no-unused-vars */
 
-/* eslint-disable no-unused-vars */
-function collapseTableAndButton(thisName, table) {
-  collapseTable(thisName, table);
-
-  const t = d3.select("." + table);
-  if (t.classed("collapsed")) {
-    d3.select("." + table + "-button").style("display", "none");
-  } else {
-    d3.select("." + table + "-button").style("display", "flex");
-  }
-}
-/* eslint-enable no-unused-vars */
-
 // Event delegation for thread dump page (CSP-compliant)
 $(function() {
   // toggleThreadStackTrace on row click
diff --git a/core/src/main/resources/org/apache/spark/ui/static/webui.js 
b/core/src/main/resources/org/apache/spark/ui/static/webui.js
index 6d20c16ffaf4..dc877d9be55e 100644
--- a/core/src/main/resources/org/apache/spark/ui/static/webui.js
+++ b/core/src/main/resources/org/apache/spark/ui/static/webui.js
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-/* global $, collapseTableAndButton, loadMore, loadNew, toggleDagViz, 
togglePlanViz, clickPhysicalPlanDetails */
+/* global $, loadMore, loadNew, toggleDagViz, togglePlanViz, 
clickPhysicalPlanDetails */
 /* eslint-disable no-unused-vars */
 var uiRoot = "";
 var appBasePath = "";
@@ -29,80 +29,37 @@ function setAppBasePath(path) {
 }
 /* eslint-enable no-unused-vars */
 
-function collapseTablePageLoad(name, table){
-  if (window.localStorage.getItem(name) == "true") {
-    // Set it to false so that the click function can revert it
-    window.localStorage.setItem(name, "false");
-    collapseTable(name, table);
-  }
-}
-
-function collapseTable(thisName, table){
-  var status = window.localStorage.getItem(thisName) == "true";
-  status = !status;
-
-  var thisClass = '.' + thisName;
-
-  // Expand the list of additional metrics.
-  var tableDiv = $(thisClass).parent().find('.' + table);
-  $(tableDiv).toggleClass('collapsed');
-
-  // Switch the class of the arrow from open to closed.
-  $(thisClass).find('.collapse-table-arrow').toggleClass('arrow-open');
-  $(thisClass).find('.collapse-table-arrow').toggleClass('arrow-closed');
-
-  window.localStorage.setItem(thisName, "" + status);
-}
-
-// Add a call to collapseTablePageLoad() on each collapsible table
-// to remember if it's collapsed on each page reload
+// Persist BS5 collapse state in localStorage
 $(function() {
-  collapseTablePageLoad('collapse-aggregated-metrics','aggregated-metrics');
-  
collapseTablePageLoad('collapse-aggregated-executors','aggregated-executors');
-  
collapseTablePageLoad('collapse-aggregated-removedExecutors','aggregated-removedExecutors');
-  collapseTablePageLoad('collapse-aggregated-workers','aggregated-workers');
-  
collapseTablePageLoad('collapse-aggregated-activeApps','aggregated-activeApps');
-  
collapseTablePageLoad('collapse-aggregated-activeDrivers','aggregated-activeDrivers');
-  
collapseTablePageLoad('collapse-aggregated-completedApps','aggregated-completedApps');
-  
collapseTablePageLoad('collapse-aggregated-completedDrivers','aggregated-completedDrivers');
-  
collapseTablePageLoad('collapse-aggregated-runningExecutors','aggregated-runningExecutors');
-  
collapseTablePageLoad('collapse-aggregated-runningDrivers','aggregated-runningDrivers');
-  
collapseTablePageLoad('collapse-aggregated-finishedExecutors','aggregated-finishedExecutors');
-  
collapseTablePageLoad('collapse-aggregated-finishedDrivers','aggregated-finishedDrivers');
-  
collapseTablePageLoad('collapse-aggregated-runtimeInformation','aggregated-runtimeInformation');
-  
collapseTablePageLoad('collapse-aggregated-sparkProperties','aggregated-sparkProperties');
-  
collapseTablePageLoad('collapse-aggregated-hadoopProperties','aggregated-hadoopProperties');
-  
collapseTablePageLoad('collapse-aggregated-systemProperties','aggregated-systemProperties');
-  
collapseTablePageLoad('collapse-aggregated-metricsProperties','aggregated-metricsProperties');
-  
collapseTablePageLoad('collapse-aggregated-classpathEntries','aggregated-classpathEntries');
-  
collapseTablePageLoad('collapse-aggregated-environmentVariables','aggregated-environmentVariables');
-  
collapseTablePageLoad('collapse-aggregated-activeJobs','aggregated-activeJobs');
-  
collapseTablePageLoad('collapse-aggregated-completedJobs','aggregated-completedJobs');
-  
collapseTablePageLoad('collapse-aggregated-failedJobs','aggregated-failedJobs');
-  
collapseTablePageLoad('collapse-aggregated-poolTable','aggregated-poolTable');
-  
collapseTablePageLoad('collapse-aggregated-allActiveStages','aggregated-allActiveStages');
-  
collapseTablePageLoad('collapse-aggregated-allPendingStages','aggregated-allPendingStages');
-  
collapseTablePageLoad('collapse-aggregated-allCompletedStages','aggregated-allCompletedStages');
-  
collapseTablePageLoad('collapse-aggregated-allSkippedStages','aggregated-allSkippedStages');
-  
collapseTablePageLoad('collapse-aggregated-allFailedStages','aggregated-allFailedStages');
-  
collapseTablePageLoad('collapse-aggregated-activeStages','aggregated-activeStages');
-  
collapseTablePageLoad('collapse-aggregated-pendingOrSkippedStages','aggregated-pendingOrSkippedStages');
-  
collapseTablePageLoad('collapse-aggregated-completedStages','aggregated-completedStages');
-  
collapseTablePageLoad('collapse-aggregated-failedStages','aggregated-failedStages');
-  
collapseTablePageLoad('collapse-aggregated-poolActiveStages','aggregated-poolActiveStages');
-  collapseTablePageLoad('collapse-aggregated-tasks','aggregated-tasks');
-  collapseTablePageLoad('collapse-aggregated-rdds','aggregated-rdds');
-  
collapseTablePageLoad('collapse-aggregated-waitingBatches','aggregated-waitingBatches');
-  
collapseTablePageLoad('collapse-aggregated-runningBatches','aggregated-runningBatches');
-  
collapseTablePageLoad('collapse-aggregated-completedBatches','aggregated-completedBatches');
-  
collapseTablePageLoad('collapse-aggregated-runningExecutions','aggregated-runningExecutions');
-  
collapseTablePageLoad('collapse-aggregated-completedExecutions','aggregated-completedExecutions');
-  
collapseTablePageLoad('collapse-aggregated-failedExecutions','aggregated-failedExecutions');
-  
collapseTablePageLoad('collapse-aggregated-sessionstat','aggregated-sessionstat');
-  collapseTablePageLoad('collapse-aggregated-sqlstat','aggregated-sqlstat');
-  
collapseTablePageLoad('collapse-aggregated-sqlsessionstat','aggregated-sqlsessionstat');
-  
collapseTablePageLoad('collapse-aggregated-activeQueries','aggregated-activeQueries');
-  
collapseTablePageLoad('collapse-aggregated-completedQueries','aggregated-completedQueries');
+  $(document).on("shown.bs.collapse hidden.bs.collapse", ".collapsible-table", 
function(e) {
+    var trigger = document.querySelector('[data-bs-target="#' + this.id + 
'"]');
+    if (trigger) {
+      var name = trigger.getAttribute("data-collapse-name");
+      if (name) {
+        var isShown = e.type === "shown";
+        window.localStorage.setItem(name, "" + !isShown);
+        $(trigger).find('.collapse-table-arrow')
+          .toggleClass('arrow-open', isShown)
+          .toggleClass('arrow-closed', !isShown);
+        trigger.setAttribute("aria-expanded", "" + isShown);
+      }
+    }
+  });
+
+  // Restore collapse state from localStorage on page load
+  $("[data-collapse-name]").each(function() {
+    var name = this.getAttribute("data-collapse-name");
+    var target = this.getAttribute("data-bs-target");
+    if (name && target && window.localStorage.getItem(name) === "true") {
+      var contentEl = document.querySelector(target);
+      if (contentEl) {
+        $(contentEl).removeClass("show");
+        $(this).find('.collapse-table-arrow')
+          .removeClass('arrow-open').addClass('arrow-closed');
+        this.setAttribute("aria-expanded", "false");
+      }
+    }
+  });
 });
 
 $(function() {
@@ -114,17 +71,6 @@ $(function() {
 
 // Event delegation for CSP-compliant inline event handler replacement.
 $(function() {
-  // collapseTable / collapseTableAndButton
-  $(document).on("click", "[data-collapse-name]", function() {
-    var name = $(this).data("collapse-name");
-    var table = $(this).data("collapse-table");
-    if ($(this).data("collapse-button")) {
-      collapseTableAndButton(name, table);
-    } else {
-      collapseTable(name, table);
-    }
-  });
-
   // toggle details (stage-details, stacktrace-details, expand-details)
   $(document).on("click", "[data-toggle-details]", function() {
     var selector = $(this).data("toggle-details");
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 864b27577c1e..886cff3d6b39 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
@@ -115,28 +115,32 @@ private[ui] class ApplicationPage(parent: MasterWebUI) 
extends WebUIPage("app")
 
       <div class="row"> <!-- Executors -->
         <div class="col-12">
-          <span class="collapse-aggregated-executors collapse-table"
-              data-collapse-name="collapse-aggregated-executors"
-              data-collapse-table="aggregated-executors">
+          <span class="collapse-table" data-bs-toggle="collapse"
+              data-bs-target="#aggregated-executors"
+              aria-expanded="true" aria-controls="aggregated-executors"
+              data-collapse-name="collapse-aggregated-executors">
             <h4>
               <span class="collapse-table-arrow arrow-open"></span>
               <a>Executor Summary ({allExecutors.length})</a>
             </h4>
           </span>
-          <div class="aggregated-executors collapsible-table">
+          <div class="collapsible-table collapse show" 
id="aggregated-executors">
             {executorsTable}
           </div>
           {
             if (removedExecutors.nonEmpty) {
-              <span class="collapse-aggregated-removedExecutors collapse-table"
-                  data-collapse-name="collapse-aggregated-removedExecutors"
-                  data-collapse-table="aggregated-removedExecutors">
+              <span class="collapse-table" data-bs-toggle="collapse"
+                  data-bs-target="#aggregated-removedExecutors"
+                  aria-expanded="true"
+                  aria-controls="aggregated-removedExecutors"
+                  data-collapse-name="collapse-aggregated-removedExecutors">
                 <h4>
                   <span class="collapse-table-arrow arrow-open"></span>
                   <a>Removed Executors ({removedExecutors.length})</a>
                 </h4>
               </span> ++
-              <div class="aggregated-removedExecutors collapsible-table">
+              <div class="collapsible-table collapse show"
+                  id="aggregated-removedExecutors">
                 {removedExecutorsTable}
               </div>
             }
diff --git 
a/core/src/main/scala/org/apache/spark/deploy/master/ui/EnvironmentPage.scala 
b/core/src/main/scala/org/apache/spark/deploy/master/ui/EnvironmentPage.scala
index 396e33e7a675..087453175257 100644
--- 
a/core/src/main/scala/org/apache/spark/deploy/master/ui/EnvironmentPage.scala
+++ 
b/core/src/main/scala/org/apache/spark/deploy/master/ui/EnvironmentPage.scala
@@ -65,81 +65,88 @@ private[ui] class EnvironmentPage(
         <p><a href="/">Back to Master</a></p>
       </div>
       <span>
-        <span class="collapse-aggregated-runtimeInformation collapse-table"
-            data-collapse-name="collapse-aggregated-runtimeInformation"
-            data-collapse-table="aggregated-runtimeInformation">
+        <span class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#aggregated-runtimeInformation"
+            aria-expanded="true" aria-controls="aggregated-runtimeInformation"
+            data-collapse-name="collapse-aggregated-runtimeInformation">
           <h4>
             <span class="collapse-table-arrow arrow-open"></span>
             <a>Runtime Information</a>
           </h4>
         </span>
-        <div class="aggregated-runtimeInformation collapsible-table">
+        <div class="collapsible-table collapse show" 
id="aggregated-runtimeInformation">
           {runtimeInformationTable}
         </div>
-        <span class="collapse-aggregated-sparkProperties collapse-table"
-            data-collapse-name="collapse-aggregated-sparkProperties"
-            data-collapse-table="aggregated-sparkProperties">
+        <span class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#aggregated-sparkProperties"
+            aria-expanded="true" aria-controls="aggregated-sparkProperties"
+            data-collapse-name="collapse-aggregated-sparkProperties">
           <h4>
             <span class="collapse-table-arrow arrow-open"></span>
             <a>Spark Properties</a>
           </h4>
         </span>
-        <div class="aggregated-sparkProperties collapsible-table">
+        <div class="collapsible-table collapse show" 
id="aggregated-sparkProperties">
           {sparkPropertiesTable}
         </div>
-        <span class="collapse-aggregated-hadoopProperties collapse-table"
-              data-collapse-name="collapse-aggregated-hadoopProperties"
-              data-collapse-table="aggregated-hadoopProperties">
+        <span class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#aggregated-hadoopProperties"
+            aria-expanded="false" aria-controls="aggregated-hadoopProperties"
+            data-collapse-name="collapse-aggregated-hadoopProperties">
           <h4>
             <span class="collapse-table-arrow arrow-closed"></span>
             <a>Hadoop Properties</a>
           </h4>
         </span>
-        <div class="aggregated-hadoopProperties collapsible-table collapsed">
+        <div class="collapsible-table collapse" 
id="aggregated-hadoopProperties">
           {hadoopPropertiesTable}
         </div>
-        <span class="collapse-aggregated-systemProperties collapse-table"
-            data-collapse-name="collapse-aggregated-systemProperties"
-            data-collapse-table="aggregated-systemProperties">
+        <span class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#aggregated-systemProperties"
+            aria-expanded="false" aria-controls="aggregated-systemProperties"
+            data-collapse-name="collapse-aggregated-systemProperties">
           <h4>
             <span class="collapse-table-arrow arrow-closed"></span>
             <a>System Properties</a>
           </h4>
         </span>
-        <div class="aggregated-systemProperties collapsible-table collapsed">
+        <div class="collapsible-table collapse" 
id="aggregated-systemProperties">
           {systemPropertiesTable}
         </div>
-        <span class="collapse-aggregated-metricsProperties collapse-table"
-              data-collapse-name="collapse-aggregated-metricsProperties"
-              data-collapse-table="aggregated-metricsProperties">
+        <span class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#aggregated-metricsProperties"
+            aria-expanded="false" aria-controls="aggregated-metricsProperties"
+            data-collapse-name="collapse-aggregated-metricsProperties">
           <h4>
             <span class="collapse-table-arrow arrow-closed"></span>
             <a>Metrics Properties</a>
           </h4>
         </span>
-        <div class="aggregated-metricsProperties collapsible-table collapsed">
+        <div class="collapsible-table collapse" 
id="aggregated-metricsProperties">
           {metricsPropertiesTable}
         </div>
-        <span class="collapse-aggregated-classpathEntries collapse-table"
-            data-collapse-name="collapse-aggregated-classpathEntries"
-            data-collapse-table="aggregated-classpathEntries">
+        <span class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#aggregated-classpathEntries"
+            aria-expanded="false" aria-controls="aggregated-classpathEntries"
+            data-collapse-name="collapse-aggregated-classpathEntries">
           <h4>
             <span class="collapse-table-arrow arrow-closed"></span>
             <a>Classpath Entries</a>
           </h4>
         </span>
-        <div class="aggregated-classpathEntries collapsible-table collapsed">
+        <div class="collapsible-table collapse" 
id="aggregated-classpathEntries">
           {classpathEntriesTable}
         </div>
-        <span class="collapse-aggregated-environmentVariables collapse-table"
-            data-collapse-name="collapse-aggregated-environmentVariables"
-            data-collapse-table="aggregated-environmentVariables">
+        <span class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#aggregated-environmentVariables"
+            aria-expanded="false" 
aria-controls="aggregated-environmentVariables"
+            data-collapse-name="collapse-aggregated-environmentVariables">
           <h4>
             <span class="collapse-table-arrow arrow-closed"></span>
             <a>Environment Variables</a>
           </h4>
         </span>
-        <div class="aggregated-environmentVariables collapsible-table 
collapsed">
+        <div class="collapsible-table collapse" 
id="aggregated-environmentVariables">
           {environmentVariablesTable}
         </div>
         <script src={UIUtils.prependBaseUri(request, 
"/static/environmentpage.js")}></script>
diff --git 
a/core/src/main/scala/org/apache/spark/deploy/master/ui/MasterPage.scala 
b/core/src/main/scala/org/apache/spark/deploy/master/ui/MasterPage.scala
index b33fdc4939ac..c1ac892fe891 100644
--- a/core/src/main/scala/org/apache/spark/deploy/master/ui/MasterPage.scala
+++ b/core/src/main/scala/org/apache/spark/deploy/master/ui/MasterPage.scala
@@ -181,15 +181,16 @@ private[ui] class MasterPage(parent: MasterWebUI) extends 
WebUIPage("") {
 
         <div class="row">
           <div class="col-12">
-            <span class="collapse-aggregated-workers collapse-table"
-                data-collapse-name="collapse-aggregated-workers"
-                data-collapse-table="aggregated-workers">
+            <span class="collapse-table" data-bs-toggle="collapse"
+                data-bs-target="#aggregated-workers"
+                aria-expanded="true" aria-controls="aggregated-workers"
+                data-collapse-name="collapse-aggregated-workers">
               <h4>
                 <span class="collapse-table-arrow arrow-open"></span>
                 <a>Workers ({workers.length})</a>
               </h4>
             </span>
-            <div class="aggregated-workers collapsible-table">
+            <div class="collapsible-table collapse show" 
id="aggregated-workers">
               {workerTable}
             </div>
           </div>
@@ -197,15 +198,17 @@ private[ui] class MasterPage(parent: MasterWebUI) extends 
WebUIPage("") {
 
         <div class="row">
           <div class="col-12">
-            <span id="running-app" class="collapse-aggregated-activeApps 
collapse-table"
-                data-collapse-name="collapse-aggregated-activeApps"
-                data-collapse-table="aggregated-activeApps">
+            <span id="running-app" class="collapse-table"
+                data-bs-toggle="collapse"
+                data-bs-target="#aggregated-activeApps"
+                aria-expanded="true" aria-controls="aggregated-activeApps"
+                data-collapse-name="collapse-aggregated-activeApps">
               <h4>
                 <span class="collapse-table-arrow arrow-open"></span>
                 <a>Running Applications ({activeApps.length})</a>
               </h4>
             </span>
-            <div class="aggregated-activeApps collapsible-table">
+            <div class="collapsible-table collapse show" 
id="aggregated-activeApps">
               {activeAppsTable}
             </div>
           </div>
@@ -215,15 +218,18 @@ private[ui] class MasterPage(parent: MasterWebUI) extends 
WebUIPage("") {
           {if (hasDrivers) {
              <div class="row">
                <div class="col-12">
-                 <span class="collapse-aggregated-activeDrivers collapse-table"
-                     data-collapse-name="collapse-aggregated-activeDrivers"
-                     data-collapse-table="aggregated-activeDrivers">
+                 <span class="collapse-table" data-bs-toggle="collapse"
+                     data-bs-target="#aggregated-activeDrivers"
+                     aria-expanded="true"
+                     aria-controls="aggregated-activeDrivers"
+                     data-collapse-name="collapse-aggregated-activeDrivers">
                    <h4>
                      <span class="collapse-table-arrow arrow-open"></span>
                      <a>Running Drivers ({activeDrivers.length})</a>
                    </h4>
                  </span>
-                 <div class="aggregated-activeDrivers collapsible-table">
+                 <div class="collapsible-table collapse show"
+                     id="aggregated-activeDrivers">
                    {activeDriversTable}
                  </div>
                </div>
@@ -234,15 +240,18 @@ private[ui] class MasterPage(parent: MasterWebUI) extends 
WebUIPage("") {
 
         <div class="row">
           <div class="col-12">
-            <span id="completed-app" class="collapse-aggregated-completedApps 
collapse-table"
-                data-collapse-name="collapse-aggregated-completedApps"
-                data-collapse-table="aggregated-completedApps">
+            <span id="completed-app" class="collapse-table"
+                data-bs-toggle="collapse"
+                data-bs-target="#aggregated-completedApps"
+                aria-expanded="true" aria-controls="aggregated-completedApps"
+                data-collapse-name="collapse-aggregated-completedApps">
               <h4>
                 <span class="collapse-table-arrow arrow-open"></span>
                 <a>Completed Applications ({completedApps.length})</a>
               </h4>
             </span>
-            <div class="aggregated-completedApps collapsible-table">
+            <div class="collapsible-table collapse show"
+                id="aggregated-completedApps">
               {completedAppsTable}
             </div>
           </div>
@@ -253,15 +262,18 @@ private[ui] class MasterPage(parent: MasterWebUI) extends 
WebUIPage("") {
             if (hasDrivers) {
               <div class="row">
                 <div class="col-12">
-                  <span class="collapse-aggregated-completedDrivers 
collapse-table"
-                      data-collapse-name="collapse-aggregated-completedDrivers"
-                      data-collapse-table="aggregated-completedDrivers">
+                  <span class="collapse-table" data-bs-toggle="collapse"
+                      data-bs-target="#aggregated-completedDrivers"
+                      aria-expanded="true"
+                      aria-controls="aggregated-completedDrivers"
+                      
data-collapse-name="collapse-aggregated-completedDrivers">
                     <h4>
                       <span class="collapse-table-arrow arrow-open"></span>
                       <a>Completed Drivers ({completedDrivers.length})</a>
                     </h4>
                   </span>
-                  <div class="aggregated-completedDrivers collapsible-table">
+                  <div class="collapsible-table collapse show"
+                      id="aggregated-completedDrivers">
                     {completedDriversTable}
                   </div>
                 </div>
diff --git 
a/core/src/main/scala/org/apache/spark/deploy/worker/ui/WorkerPage.scala 
b/core/src/main/scala/org/apache/spark/deploy/worker/ui/WorkerPage.scala
index bf55a588d548..2512f4eda9f6 100644
--- a/core/src/main/scala/org/apache/spark/deploy/worker/ui/WorkerPage.scala
+++ b/core/src/main/scala/org/apache/spark/deploy/worker/ui/WorkerPage.scala
@@ -100,58 +100,66 @@ private[ui] class WorkerPage(parent: WorkerWebUI) extends 
WebUIPage("") {
       </div>
       <div class="row"> <!-- Executors and Drivers -->
         <div class="col-12">
-          <span class="collapse-aggregated-runningExecutors collapse-table"
-              data-collapse-name="collapse-aggregated-runningExecutors"
-              data-collapse-table="aggregated-runningExecutors">
+          <span class="collapse-table" data-bs-toggle="collapse"
+              data-bs-target="#aggregated-runningExecutors"
+              aria-expanded="true" aria-controls="aggregated-runningExecutors"
+              data-collapse-name="collapse-aggregated-runningExecutors">
             <h4>
               <span class="collapse-table-arrow arrow-open"></span>
               <a>Running Executors ({runningExecutors.size})</a>
             </h4>
           </span>
-          <div class="aggregated-runningExecutors collapsible-table">
+          <div class="collapsible-table collapse show" 
id="aggregated-runningExecutors">
             {runningExecutorTable}
           </div>
           {
             if (runningDrivers.nonEmpty) {
-              <span class="collapse-aggregated-runningDrivers collapse-table"
-                  data-collapse-name="collapse-aggregated-runningDrivers"
-                  data-collapse-table="aggregated-runningDrivers">
+              <span class="collapse-table" data-bs-toggle="collapse"
+                  data-bs-target="#aggregated-runningDrivers"
+                  aria-expanded="true" 
aria-controls="aggregated-runningDrivers"
+                  data-collapse-name="collapse-aggregated-runningDrivers">
                 <h4>
                   <span class="collapse-table-arrow arrow-open"></span>
                   <a>Running Drivers ({runningDrivers.size})</a>
                 </h4>
               </span> ++
-              <div class="aggregated-runningDrivers collapsible-table">
+              <div class="collapsible-table collapse show"
+                  id="aggregated-runningDrivers">
                 {runningDriverTable}
               </div>
             }
           }
           {
             if (finishedExecutors.nonEmpty) {
-              <span class="collapse-aggregated-finishedExecutors 
collapse-table"
-                  data-collapse-name="collapse-aggregated-finishedExecutors"
-                  data-collapse-table="aggregated-finishedExecutors">
+              <span class="collapse-table" data-bs-toggle="collapse"
+                  data-bs-target="#aggregated-finishedExecutors"
+                  aria-expanded="true"
+                  aria-controls="aggregated-finishedExecutors"
+                  data-collapse-name="collapse-aggregated-finishedExecutors">
                 <h4>
                   <span class="collapse-table-arrow arrow-open"></span>
                   <a>Finished Executors ({finishedExecutors.size})</a>
                 </h4>
               </span> ++
-              <div class="aggregated-finishedExecutors collapsible-table">
+              <div class="collapsible-table collapse show"
+                  id="aggregated-finishedExecutors">
                 {finishedExecutorTable}
               </div>
             }
           }
           {
             if (finishedDrivers.nonEmpty) {
-              <span class="collapse-aggregated-finishedDrivers collapse-table"
-                  data-collapse-name="collapse-aggregated-finishedDrivers"
-                  data-collapse-table="aggregated-finishedDrivers">
+              <span class="collapse-table" data-bs-toggle="collapse"
+                  data-bs-target="#aggregated-finishedDrivers"
+                  aria-expanded="true" 
aria-controls="aggregated-finishedDrivers"
+                  data-collapse-name="collapse-aggregated-finishedDrivers">
                 <h4>
                   <span class="collapse-table-arrow arrow-open"></span>
                   <a>Finished Drivers ({finishedDrivers.size})</a>
                 </h4>
               </span> ++
-              <div class="aggregated-finishedDrivers collapsible-table">
+              <div class="collapsible-table collapse show"
+                  id="aggregated-finishedDrivers">
                 {finishedDriverTable}
               </div>
             }
diff --git a/core/src/main/scala/org/apache/spark/ui/env/EnvironmentPage.scala 
b/core/src/main/scala/org/apache/spark/ui/env/EnvironmentPage.scala
index 7994f6983ba6..56ac8618204d 100644
--- a/core/src/main/scala/org/apache/spark/ui/env/EnvironmentPage.scala
+++ b/core/src/main/scala/org/apache/spark/ui/env/EnvironmentPage.scala
@@ -92,81 +92,90 @@ private[ui] class EnvironmentPage(
       headerClasses = headerClasses)
     val content =
       <span>
-        <span class="collapse-aggregated-runtimeInformation collapse-table"
-            data-collapse-name="collapse-aggregated-runtimeInformation"
-            data-collapse-table="aggregated-runtimeInformation">
+        <span class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#aggregated-runtimeInformation"
+            aria-expanded="true" aria-controls="aggregated-runtimeInformation"
+            data-collapse-name="collapse-aggregated-runtimeInformation">
           <h4>
             <span class="collapse-table-arrow arrow-open"></span>
             <a>Runtime Information</a>
           </h4>
         </span>
-        <div class="aggregated-runtimeInformation collapsible-table">
+        <div class="collapsible-table collapse show" 
id="aggregated-runtimeInformation">
           {runtimeInformationTable}
         </div>
-        <span class="collapse-aggregated-sparkProperties collapse-table"
-            data-collapse-name="collapse-aggregated-sparkProperties"
-            data-collapse-table="aggregated-sparkProperties">
+        <span class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#aggregated-sparkProperties"
+            aria-expanded="true" aria-controls="aggregated-sparkProperties"
+            data-collapse-name="collapse-aggregated-sparkProperties">
           <h4>
             <span class="collapse-table-arrow arrow-open"></span>
             <a>Spark Properties</a>
           </h4>
         </span>
-        <div class="aggregated-sparkProperties collapsible-table">
+        <div class="collapsible-table collapse show" 
id="aggregated-sparkProperties">
           {sparkPropertiesTable}
         </div>
-        <span class="collapse-aggregated-execResourceProfileInformation 
collapse-table"
-              
data-collapse-name="collapse-aggregated-execResourceProfileInformation"
-              data-collapse-table="aggregated-execResourceProfileInformation">
+        <span class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#aggregated-execResourceProfileInformation"
+            aria-expanded="true"
+            aria-controls="aggregated-execResourceProfileInformation"
+            
data-collapse-name="collapse-aggregated-execResourceProfileInformation">
           <h4>
             <span class="collapse-table-arrow arrow-open"></span>
             <a>Resource Profiles</a>
           </h4>
         </span>
-        <div class="aggregated-execResourceProfileInformation 
collapsible-table">
+        <div class="collapsible-table collapse show"
+            id="aggregated-execResourceProfileInformation">
           {resourceProfileInformationTable}
         </div>
-        <span class="collapse-aggregated-hadoopProperties collapse-table"
-              data-collapse-name="collapse-aggregated-hadoopProperties"
-              data-collapse-table="aggregated-hadoopProperties">
+        <span class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#aggregated-hadoopProperties"
+            aria-expanded="false" aria-controls="aggregated-hadoopProperties"
+            data-collapse-name="collapse-aggregated-hadoopProperties">
           <h4>
             <span class="collapse-table-arrow arrow-closed"></span>
             <a>Hadoop Properties</a>
           </h4>
         </span>
-        <div class="aggregated-hadoopProperties collapsible-table collapsed">
+        <div class="collapsible-table collapse" 
id="aggregated-hadoopProperties">
           {hadoopPropertiesTable}
         </div>
-        <span class="collapse-aggregated-systemProperties collapse-table"
-            data-collapse-name="collapse-aggregated-systemProperties"
-            data-collapse-table="aggregated-systemProperties">
+        <span class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#aggregated-systemProperties"
+            aria-expanded="false" aria-controls="aggregated-systemProperties"
+            data-collapse-name="collapse-aggregated-systemProperties">
           <h4>
             <span class="collapse-table-arrow arrow-closed"></span>
             <a>System Properties</a>
           </h4>
         </span>
-        <div class="aggregated-systemProperties collapsible-table collapsed">
+        <div class="collapsible-table collapse" 
id="aggregated-systemProperties">
           {systemPropertiesTable}
         </div>
-        <span class="collapse-aggregated-metricsProperties collapse-table"
-              data-collapse-name="collapse-aggregated-metricsProperties"
-              data-collapse-table="aggregated-metricsProperties">
+        <span class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#aggregated-metricsProperties"
+            aria-expanded="false" aria-controls="aggregated-metricsProperties"
+            data-collapse-name="collapse-aggregated-metricsProperties">
           <h4>
             <span class="collapse-table-arrow arrow-closed"></span>
             <a>Metrics Properties</a>
           </h4>
         </span>
-        <div class="aggregated-metricsProperties collapsible-table collapsed">
+        <div class="collapsible-table collapse" 
id="aggregated-metricsProperties">
           {metricsPropertiesTable}
         </div>
-        <span class="collapse-aggregated-classpathEntries collapse-table"
-            data-collapse-name="collapse-aggregated-classpathEntries"
-            data-collapse-table="aggregated-classpathEntries">
+        <span class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#aggregated-classpathEntries"
+            aria-expanded="false" aria-controls="aggregated-classpathEntries"
+            data-collapse-name="collapse-aggregated-classpathEntries">
           <h4>
             <span class="collapse-table-arrow arrow-closed"></span>
             <a>Classpath Entries</a>
           </h4>
         </span>
-        <div class="aggregated-classpathEntries collapsible-table collapsed">
+        <div class="collapsible-table collapse" 
id="aggregated-classpathEntries">
           {classpathEntriesTable}
         </div>
         <script src={UIUtils.prependBaseUri(request, 
"/static/environmentpage.js")}></script>
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 f1486539591e..b4a205e09fb8 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
@@ -81,15 +81,19 @@ private[ui] class ExecutorThreadDumpPage(
         {
           // scalastyle:off
           <p></p>
-          <span class="collapse-thead-stack-trace-table collapse-table"
-                data-collapse-name="collapse-thead-stack-trace-table"
-                data-collapse-table="thead-stack-trace-table"
-                data-collapse-button="true">
+          <span class="collapse-table" data-bs-toggle="collapse"
+                data-bs-target="#thead-stack-trace-table"
+                aria-expanded="true" aria-controls="thead-stack-trace-table"
+                data-collapse-name="collapse-thead-stack-trace-table">
             <h4>
               <span class="collapse-table-arrow arrow-open"></span>
               <a>Thread Stack Trace</a>
             </h4>
           </span>
+        }
+        <div class="collapsible-table collapse show" 
id="thead-stack-trace-table">
+          {
+          // scalastyle:off
           <div class="thead-stack-trace-table-button" style="display: flex; 
align-items: center;">
             <a class="expandbutton" 
data-action="expandAllThreadStackTrace">Expand All</a>
             <a class="expandbutton d-none" 
data-action="collapseAllThreadStackTrace">Collapse All</a>
@@ -106,21 +110,22 @@ private[ui] class ExecutorThreadDumpPage(
             </div>
           </div>
           <p></p>
-        }
-        <table class={UIUtils.TABLE_CLASS_STRIPED + " accordion-group" + " 
sortable" + " thead-stack-trace-table collapsible-table"}>
-          <thead>
-            <th data-action="collapseAllThreadStackTrace" 
data-toggle-button="false">Thread ID</th>
-            <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-bs-toggle="tooltip" data-bs-placement="top"
-                    title="Objects whose lock the thread currently holds">
-                Thread Locks
-              </span>
-            </th>
-          </thead>
-          <tbody>{dumpRows}</tbody>
-        </table>
+          }
+          <table class={UIUtils.TABLE_CLASS_STRIPED + " accordion-group" + " 
sortable"}>
+            <thead>
+              <th data-action="collapseAllThreadStackTrace" 
data-toggle-button="false">Thread ID</th>
+              <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-bs-toggle="tooltip" data-bs-placement="top"
+                      title="Objects whose lock the thread currently holds">
+                  Thread Locks
+                </span>
+              </th>
+            </thead>
+            <tbody>{dumpRows}</tbody>
+          </table>
+        </div>
       </div>
     </div>
     }.getOrElse(Text("Error fetching thread dump"))
@@ -159,15 +164,17 @@ private[ui] class ExecutorThreadDumpPage(
   private def threadDumpSummary(threadDump: Array[ThreadStackTrace]): 
Seq[Node] = {
     val totalCount = threadDump.length
     <div>
-      <span class="thead-dump-summary collapse-table"
-            data-collapse-name="thead-dump-summary"
-            data-collapse-table="thread-dump-summary-table">
+      <span class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#thread-dump-summary-table"
+            aria-expanded="true" aria-controls="thread-dump-summary-table"
+            data-collapse-name="thead-dump-summary">
         <h4>
           <span class="collapse-table-arrow arrow-open"></span>
           <a>Thread Dump Summary: { totalCount }</a>
         </h4>
       </span>
-      <table class={UIUtils.TABLE_CLASS_STRIPED + " accordion-group" + " 
sortable" + " thread-dump-summary-table collapsible-table"}>
+      <div class="collapsible-table collapse show" 
id="thread-dump-summary-table">
+      <table class={UIUtils.TABLE_CLASS_STRIPED + " accordion-group" + " 
sortable"}>
         <thead><th>Thread State</th><th>Count</th><th>Percentage</th></thead>
         <tbody>
           {
@@ -181,6 +188,7 @@ private[ui] class ExecutorThreadDumpPage(
           }
         </tbody>
       </table>
+      </div>
     </div>
   }
   // scalastyle:on
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 c395c7cca4e3..a270d4b71ac3 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
@@ -379,43 +379,46 @@ private[ui] class AllJobsPage(parent: JobsTab, store: 
AppStatusStore) extends We
 
     if (shouldShowActiveJobs) {
       content ++=
-        <span id="active" class="collapse-aggregated-activeJobs collapse-table"
-            data-collapse-name="collapse-aggregated-activeJobs"
-            data-collapse-table="aggregated-activeJobs">
+        <span id="active" class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#aggregated-activeJobs"
+            aria-expanded="true" aria-controls="aggregated-activeJobs"
+            data-collapse-name="collapse-aggregated-activeJobs">
           <h4>
             <span class="collapse-table-arrow arrow-open"></span>
             <a>Active Jobs ({activeJobs.size})</a>
           </h4>
         </span> ++
-        <div class="aggregated-activeJobs collapsible-table">
+        <div class="collapsible-table collapse show" 
id="aggregated-activeJobs">
           {activeJobsTable}
         </div>
     }
     if (shouldShowCompletedJobs) {
       content ++=
-        <span id="completed" class="collapse-aggregated-completedJobs 
collapse-table"
-            data-collapse-name="collapse-aggregated-completedJobs"
-            data-collapse-table="aggregated-completedJobs">
+        <span id="completed" class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#aggregated-completedJobs"
+            aria-expanded="true" aria-controls="aggregated-completedJobs"
+            data-collapse-name="collapse-aggregated-completedJobs">
           <h4>
             <span class="collapse-table-arrow arrow-open"></span>
             <a>Completed Jobs ({completedJobNumStr})</a>
           </h4>
         </span> ++
-        <div class="aggregated-completedJobs collapsible-table">
+        <div class="collapsible-table collapse show" 
id="aggregated-completedJobs">
           {completedJobsTable}
         </div>
     }
     if (shouldShowFailedJobs) {
       content ++=
-        <span id ="failed" class="collapse-aggregated-failedJobs 
collapse-table"
-            data-collapse-name="collapse-aggregated-failedJobs"
-            data-collapse-table="aggregated-failedJobs">
+        <span id ="failed" class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#aggregated-failedJobs"
+            aria-expanded="true" aria-controls="aggregated-failedJobs"
+            data-collapse-name="collapse-aggregated-failedJobs">
           <h4>
             <span class="collapse-table-arrow arrow-open"></span>
             <a>Failed Jobs ({failedJobs.size})</a>
           </h4>
         </span> ++
-      <div class="aggregated-failedJobs collapsible-table">
+      <div class="collapsible-table collapse show" id="aggregated-failedJobs">
         {failedJobsTable}
       </div>
     }
diff --git a/core/src/main/scala/org/apache/spark/ui/jobs/AllStagesPage.scala 
b/core/src/main/scala/org/apache/spark/ui/jobs/AllStagesPage.scala
index 165358fd9864..6895db261330 100644
--- a/core/src/main/scala/org/apache/spark/ui/jobs/AllStagesPage.scala
+++ b/core/src/main/scala/org/apache/spark/ui/jobs/AllStagesPage.scala
@@ -57,15 +57,16 @@ private[ui] class AllStagesPage(parent: StagesTab) extends 
WebUIPage("") {
       </div>
 
     val poolsDescription = if (parent.isFairScheduler) {
-        <span class="collapse-aggregated-poolTable collapse-table"
-            data-collapse-name="collapse-aggregated-poolTable"
-            data-collapse-table="aggregated-poolTable">
+        <span class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#aggregated-poolTable"
+            aria-expanded="true" aria-controls="aggregated-poolTable"
+            data-collapse-name="collapse-aggregated-poolTable">
           <h4>
             <span class="collapse-table-arrow arrow-open"></span>
             <a>Fair Scheduler Pools ({pools.size})</a>
           </h4>
         </span> ++
-        <div class="aggregated-poolTable collapsible-table">
+        <div class="collapsible-table collapse show" id="aggregated-poolTable">
           {poolTable.toNodeSeq(request)}
         </div>
       } else {
@@ -146,15 +147,16 @@ private[ui] class AllStagesPage(parent: StagesTab) 
extends WebUIPage("") {
       size: Int): NodeSeq = {
     val classSuffix = s"${statusName(status).capitalize}Stages"
     <span id={statusName(status)}
-          class={s"collapse-aggregated-all$classSuffix collapse-table"}
-          data-collapse-name={s"collapse-aggregated-all$classSuffix"}
-          data-collapse-table={s"aggregated-all$classSuffix"}>
+          class="collapse-table" data-bs-toggle="collapse"
+          data-bs-target={s"#aggregated-all$classSuffix"}
+          aria-expanded="true" aria-controls={s"aggregated-all$classSuffix"}
+          data-collapse-name={s"collapse-aggregated-all$classSuffix"}>
       <h4>
         <span class="collapse-table-arrow arrow-open"></span>
         <a>{headerDescription(status)} Stages ({summaryContent(appSummary, 
status, size)})</a>
       </h4>
     </span> ++
-      <div class={s"aggregated-all$classSuffix collapsible-table"}>
+      <div class="collapsible-table collapse show" 
id={s"aggregated-all$classSuffix"}>
         {stagesTable.toNodeSeq}
       </div>
   }
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 a235d5ea30d9..ef9ce225d08a 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
@@ -458,71 +458,76 @@ private[ui] class JobPage(parent: JobsTab, store: 
AppStatusStore) extends WebUIP
 
     if (shouldShowActiveStages) {
       content ++=
-        <span id="active" class="collapse-aggregated-activeStages 
collapse-table"
-            data-collapse-name="collapse-aggregated-activeStages"
-            data-collapse-table="aggregated-activeStages">
+        <span id="active" class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#aggregated-activeStages"
+            aria-expanded="true" aria-controls="aggregated-activeStages"
+            data-collapse-name="collapse-aggregated-activeStages">
           <h4>
             <span class="collapse-table-arrow arrow-open"></span>
             <a>Active Stages ({activeStages.size})</a>
           </h4>
         </span> ++
-        <div class="aggregated-activeStages collapsible-table">
+        <div class="collapsible-table collapse show" 
id="aggregated-activeStages">
           {activeStagesTable.toNodeSeq}
         </div>
     }
     if (shouldShowPendingStages) {
       content ++=
-        <span id="pending" class="collapse-aggregated-pendingOrSkippedStages 
collapse-table"
-            data-collapse-name="collapse-aggregated-pendingOrSkippedStages"
-            data-collapse-table="aggregated-pendingOrSkippedStages">
+        <span id="pending" class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#aggregated-pendingStages"
+            aria-expanded="true" aria-controls="aggregated-pendingStages"
+            data-collapse-name="collapse-aggregated-pendingOrSkippedStages">
           <h4>
             <span class="collapse-table-arrow arrow-open"></span>
             <a>Pending Stages ({pendingOrSkippedStages.size})</a>
           </h4>
         </span> ++
-        <div class="aggregated-pendingOrSkippedStages collapsible-table">
+        <div class="collapsible-table collapse show" 
id="aggregated-pendingStages">
           {pendingOrSkippedStagesTable.toNodeSeq}
         </div>
     }
     if (shouldShowCompletedStages) {
       content ++=
-        <span id="completed" class="collapse-aggregated-completedStages 
collapse-table"
-            data-collapse-name="collapse-aggregated-completedStages"
-            data-collapse-table="aggregated-completedStages">
+        <span id="completed" class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#aggregated-completedStages"
+            aria-expanded="true" aria-controls="aggregated-completedStages"
+            data-collapse-name="collapse-aggregated-completedStages">
           <h4>
             <span class="collapse-table-arrow arrow-open"></span>
             <a>Completed Stages ({completedStages.size})</a>
           </h4>
         </span> ++
-        <div class="aggregated-completedStages collapsible-table">
+        <div class="collapsible-table collapse show" 
id="aggregated-completedStages">
           {completedStagesTable.toNodeSeq}
         </div>
     }
     if (shouldShowSkippedStages) {
       content ++=
-        <span id="skipped" class="collapse-aggregated-pendingOrSkippedStages 
collapse-table"
-            data-collapse-name="collapse-aggregated-pendingOrSkippedStages"
-            data-collapse-table="aggregated-pendingOrSkippedStages">
+        <span id="skipped" class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#aggregated-skippedStages"
+            aria-expanded="true" aria-controls="aggregated-skippedStages"
+            data-collapse-name="collapse-aggregated-pendingOrSkippedStages">
           <h4>
             <span class="collapse-table-arrow arrow-open"></span>
             <a>Skipped Stages ({pendingOrSkippedStages.size})</a>
           </h4>
         </span> ++
-        <div class="aggregated-pendingOrSkippedStages collapsible-table">
+        <div class="collapsible-table collapse show" 
id="aggregated-skippedStages">
           {pendingOrSkippedStagesTable.toNodeSeq}
         </div>
     }
     if (shouldShowFailedStages) {
       content ++=
-        <span id ="failed" class="collapse-aggregated-failedStages 
collapse-table"
-            data-collapse-name="collapse-aggregated-failedStages"
-            data-collapse-table="aggregated-failedStages">
+        <span id ="failed" class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#aggregated-failedStages"
+            aria-expanded="true" aria-controls="aggregated-failedStages"
+            data-collapse-name="collapse-aggregated-failedStages">
           <h4>
             <span class="collapse-table-arrow arrow-open"></span>
             <a>Failed Stages ({failedStages.size})</a>
           </h4>
         </span> ++
-        <div class="aggregated-failedStages collapsible-table">
+        <div class="collapsible-table collapse show" 
id="aggregated-failedStages">
           {failedStagesTable.toNodeSeq}
         </div>
     }
diff --git a/core/src/main/scala/org/apache/spark/ui/jobs/PoolPage.scala 
b/core/src/main/scala/org/apache/spark/ui/jobs/PoolPage.scala
index 85dbed0aa41a..f5c4a2bf21e4 100644
--- a/core/src/main/scala/org/apache/spark/ui/jobs/PoolPage.scala
+++ b/core/src/main/scala/org/apache/spark/ui/jobs/PoolPage.scala
@@ -50,15 +50,16 @@ private[ui] class PoolPage(parent: StagesTab) extends 
WebUIPage("pool") {
     var content = <h4>Summary </h4> ++ poolTable.toNodeSeq(request)
     if (activeStages.nonEmpty) {
       content ++=
-        <span class="collapse-aggregated-poolActiveStages collapse-table"
-            data-collapse-name="collapse-aggregated-poolActiveStages"
-            data-collapse-table="aggregated-poolActiveStages">
+        <span class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#aggregated-poolActiveStages"
+            aria-expanded="true" aria-controls="aggregated-poolActiveStages"
+            data-collapse-name="collapse-aggregated-poolActiveStages">
           <h4>
             <span class="collapse-table-arrow arrow-open"></span>
             <a>Active Stages ({activeStages.size})</a>
           </h4>
         </span> ++
-        <div class="aggregated-poolActiveStages collapsible-table">
+        <div class="collapsible-table collapse show" 
id="aggregated-poolActiveStages">
           {activeStagesTable.toNodeSeq}
         </div>
     }
diff --git a/core/src/main/scala/org/apache/spark/ui/storage/StoragePage.scala 
b/core/src/main/scala/org/apache/spark/ui/storage/StoragePage.scala
index 40d3a3693616..fac358e8fd04 100644
--- a/core/src/main/scala/org/apache/spark/ui/storage/StoragePage.scala
+++ b/core/src/main/scala/org/apache/spark/ui/storage/StoragePage.scala
@@ -45,15 +45,16 @@ private[ui] class StoragePage(parent: SparkUITab, store: 
AppStatusStore) extends
       Nil
     } else {
       <div>
-        <span class="collapse-aggregated-rdds collapse-table"
-            data-collapse-name="collapse-aggregated-rdds"
-            data-collapse-table="aggregated-rdds">
+        <span class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#aggregated-rdds"
+            aria-expanded="true" aria-controls="aggregated-rdds"
+            data-collapse-name="collapse-aggregated-rdds">
           <h4>
             <span class="collapse-table-arrow arrow-open"></span>
             <a>RDDs ({rdds.length})</a>
           </h4>
         </span>
-        <div class="aggregated-rdds collapsible-table">
+        <div class="collapsible-table collapse show" id="aggregated-rdds">
           {UIUtils.listingTable(
             rddHeader,
             rddRow(request, _: v1.RDDStorageInfo),
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 d374a70a02b8..b34cf8d5cfa7 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
@@ -104,15 +104,16 @@ private[ui] class SparkConnectServerPage(parent: 
SparkConnectServerTab)
       None
     }
     val content =
-      <span id="sqlstat" class="collapse-aggregated-sqlstat collapse-table"
-            data-collapse-name="collapse-aggregated-sqlstat"
-            data-collapse-table="aggregated-sqlstat">
+      <span id="sqlstat" class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#aggregated-sqlstat"
+            aria-expanded="true" aria-controls="aggregated-sqlstat"
+            data-collapse-name="collapse-aggregated-sqlstat">
         <h4>
           <span class="collapse-table-arrow arrow-open"></span>
           <a>Request Statistics ({numStatement})</a>
         </h4>
       </span> ++
-        <div class="aggregated-sqlstat collapsible-table">
+        <div class="collapsible-table collapse show" id="aggregated-sqlstat">
           {table.getOrElse("No statistics have been generated yet.")}
         </div>
     content
@@ -151,15 +152,16 @@ private[ui] class SparkConnectServerPage(parent: 
SparkConnectServerTab)
     }
 
     val content =
-      <span id="sessionstat" class="collapse-aggregated-sessionstat 
collapse-table"
-            data-collapse-name="collapse-aggregated-sessionstat"
-            data-collapse-table="aggregated-sessionstat">
+      <span id="sessionstat" class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#aggregated-sessionstat"
+            aria-expanded="true" aria-controls="aggregated-sessionstat"
+            data-collapse-name="collapse-aggregated-sessionstat">
         <h4>
           <span class="collapse-table-arrow arrow-open"></span>
           <a>Session Statistics ({numSessions})</a>
         </h4>
       </span> ++
-        <div class="aggregated-sessionstat collapsible-table">
+        <div class="collapsible-table collapse show" 
id="aggregated-sessionstat">
           {table.getOrElse("No statistics have been generated yet.")}
         </div>
 
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 f6a1cf18721e..391fc6c09fd1 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
@@ -114,15 +114,16 @@ private[ui] class SparkConnectServerSessionPage(parent: 
SparkConnectServerTab)
       None
     }
     val content =
-      <span id="sqlsessionstat" class="collapse-aggregated-sqlsessionstat 
collapse-table"
-            data-collapse-name="collapse-aggregated-sqlsessionstat"
-            data-collapse-table="aggregated-sqlsessionstat">
+      <span id="sqlsessionstat" class="collapse-table" 
data-bs-toggle="collapse"
+            data-bs-target="#aggregated-sqlsessionstat"
+            aria-expanded="true" aria-controls="aggregated-sqlsessionstat"
+            data-collapse-name="collapse-aggregated-sqlsessionstat">
         <h4>
           <span class="collapse-table-arrow arrow-open"></span>
           <a>Request Statistics</a>
         </h4>
       </span> ++
-        <div class="aggregated-sqlsessionstat collapsible-table">
+        <div class="collapsible-table collapse show" 
id="aggregated-sqlsessionstat">
           {table.getOrElse("No statistics have been generated yet.")}
         </div>
 
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 3fc00f609779..3c8786a42cd4 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
@@ -101,8 +101,8 @@ class SparkConnectServerPageSuite
 
     // Hiding table support
     assert(
-      html.contains("class=\"collapse-aggregated-sessionstat" +
-        " collapse-table\" 
data-collapse-name=\"collapse-aggregated-sessionstat\""))
+      html.contains("class=\"collapse-table\" data-bs-toggle=\"collapse\"" +
+        " data-bs-target=\"#aggregated-sessionstat\""))
   }
 
   test("Spark Connect Server session page should load successfully") {
@@ -128,7 +128,7 @@ class SparkConnectServerPageSuite
 
     // Hiding table support
     assert(
-      html.contains("collapse-aggregated-sqlsessionstat collapse-table\"" +
-        " data-collapse-name=\"collapse-aggregated-sqlsessionstat\""))
+      html.contains("collapse-table\" data-bs-toggle=\"collapse\"" +
+        " data-bs-target=\"#aggregated-sqlsessionstat\""))
   }
 }
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 552158ae08ec..1875220cbf9e 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
@@ -88,15 +88,16 @@ private[ui] class AllExecutionsPage(parent: SQLTab) extends 
WebUIPage("") with L
             showFailedJobs = true)
 
         _content ++=
-          <span id="running" class="collapse-aggregated-runningExecutions 
collapse-table"
-                data-collapse-name="collapse-aggregated-runningExecutions"
-                data-collapse-table="aggregated-runningExecutions">
+          <span id="running" class="collapse-table" data-bs-toggle="collapse"
+                data-bs-target="#aggregated-runningExecutions"
+                aria-expanded="true" 
aria-controls="aggregated-runningExecutions"
+                data-collapse-name="collapse-aggregated-runningExecutions">
             <h4>
               <span class="collapse-table-arrow arrow-open"></span>
               <a>Running Queries ({running.size})</a>
             </h4>
           </span> ++
-            <div class="aggregated-runningExecutions collapsible-table">
+            <div class="collapsible-table collapse show" 
id="aggregated-runningExecutions">
               {runningPageTable}
             </div>
       }
@@ -114,15 +115,17 @@ private[ui] class AllExecutionsPage(parent: SQLTab) 
extends WebUIPage("") with L
           showFailedJobs = false)
 
         _content ++=
-          <span id="completed" class="collapse-aggregated-completedExecutions 
collapse-table"
-                data-collapse-name="collapse-aggregated-completedExecutions"
-                data-collapse-table="aggregated-completedExecutions">
+          <span id="completed" class="collapse-table" data-bs-toggle="collapse"
+                data-bs-target="#aggregated-completedExecutions"
+                aria-expanded="true" 
aria-controls="aggregated-completedExecutions"
+                data-collapse-name="collapse-aggregated-completedExecutions">
             <h4>
               <span class="collapse-table-arrow arrow-open"></span>
               <a>Completed Queries ({completed.size})</a>
             </h4>
           </span> ++
-            <div class="aggregated-completedExecutions collapsible-table">
+            <div class="collapsible-table collapse show"
+                id="aggregated-completedExecutions">
               {completedPageTable}
             </div>
       }
@@ -141,15 +144,17 @@ private[ui] class AllExecutionsPage(parent: SQLTab) 
extends WebUIPage("") with L
             showFailedJobs = true)
 
         _content ++=
-          <span id="failed" class="collapse-aggregated-failedExecutions 
collapse-table"
-                data-collapse-name="collapse-aggregated-failedExecutions"
-                data-collapse-table="aggregated-failedExecutions">
+          <span id="failed" class="collapse-table" data-bs-toggle="collapse"
+                data-bs-target="#aggregated-failedExecutions"
+                aria-expanded="true" 
aria-controls="aggregated-failedExecutions"
+                data-collapse-name="collapse-aggregated-failedExecutions">
             <h4>
               <span class="collapse-table-arrow arrow-open"></span>
               <a>Failed Queries ({failed.size})</a>
             </h4>
           </span> ++
-            <div class="aggregated-failedExecutions collapsible-table">
+            <div class="collapsible-table collapse show"
+                id="aggregated-failedExecutions">
               {failedPageTable}
             </div>
       }
diff --git 
a/sql/core/src/main/scala/org/apache/spark/sql/execution/ui/ExecutionPage.scala 
b/sql/core/src/main/scala/org/apache/spark/sql/execution/ui/ExecutionPage.scala
index 0d31eb9e88e8..4860620d19d2 100644
--- 
a/sql/core/src/main/scala/org/apache/spark/sql/execution/ui/ExecutionPage.scala
+++ 
b/sql/core/src/main/scala/org/apache/spark/sql/execution/ui/ExecutionPage.scala
@@ -211,15 +211,16 @@ class ExecutionPage(parent: SQLTab) extends 
WebUIPage("execution") with Logging
     )
 
     <div>
-      <span class="collapse-sql-properties collapse-table"
-            data-collapse-name="collapse-sql-properties"
-            data-collapse-table="sql-properties">
+      <span class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#sql-properties"
+            aria-expanded="false" aria-controls="sql-properties"
+            data-collapse-name="collapse-sql-properties">
         <h4>
           <span class="collapse-table-arrow arrow-closed"></span>
           <a>SQL / DataFrame Properties</a>
         </h4>
       </span>
-      <div class="sql-properties collapsible-table collapsed">
+      <div class="collapsible-table collapse" id="sql-properties">
         {configs}
       </div>
     </div>
@@ -251,15 +252,16 @@ class ExecutionPage(parent: SQLTab) extends 
WebUIPage("execution") with Logging
     )
 
     <div>
-      <span class="collapse-pandas-on-spark-properties collapse-table"
-            data-collapse-name="collapse-pandas-on-spark-properties"
-            data-collapse-table="pandas-on-spark-properties">
+      <span class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#pandas-on-spark-properties"
+            aria-expanded="false" aria-controls="pandas-on-spark-properties"
+            data-collapse-name="collapse-pandas-on-spark-properties">
         <h4>
           <span class="collapse-table-arrow arrow-closed"></span>
           <a>Pandas API Properties</a>
         </h4>
       </span>
-      <div class="pandas-on-spark-properties collapsible-table collapsed">
+      <div class="collapsible-table collapse" id="pandas-on-spark-properties">
         {configs}
       </div>
     </div>
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 d60af8fb181d..87573f42b7f5 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
@@ -47,16 +47,17 @@ private[ui] class StreamingQueryPage(parent: 
StreamingQueryTab)
     if (activeQueries.nonEmpty) {
       // scalastyle:off
       content ++=
-        <span id="active" class="collapse-aggregated-activeQueries 
collapse-table"
-            data-collapse-name="collapse-aggregated-activeQueries"
-            data-collapse-table="aggregated-activeQueries">
+        <span id="active" class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#aggregated-activeQueries"
+            aria-expanded="true" aria-controls="aggregated-activeQueries"
+            data-collapse-name="collapse-aggregated-activeQueries">
           <h5 id="activequeries">
             <span class="collapse-table-arrow arrow-open"></span>
             <a>Active Streaming Queries ({activeQueries.length})</a>
           </h5>
         </span> ++
-          <div>
-            <ul class="aggregated-activeQueries collapsible-table">
+          <div class="collapsible-table collapse show" 
id="aggregated-activeQueries">
+            <ul>
               {queryTable(activeQueries, request, "active")}
             </ul>
           </div>
@@ -66,16 +67,18 @@ private[ui] class StreamingQueryPage(parent: 
StreamingQueryTab)
     if (inactiveQueries.nonEmpty) {
       // scalastyle:off
       content ++=
-        <span id="completed" class="collapse-aggregated-completedQueries 
collapse-table"
-            data-collapse-name="collapse-aggregated-completedQueries"
-            data-collapse-table="aggregated-completedQueries">
+        <span id="completed" class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#aggregated-completedQueries"
+            aria-expanded="true" aria-controls="aggregated-completedQueries"
+            data-collapse-name="collapse-aggregated-completedQueries">
           <h5 id="completedqueries">
             <span class="collapse-table-arrow arrow-open"></span>
             <a>Completed Streaming Queries ({inactiveQueries.length})</a>
           </h5>
         </span> ++
-          <div>
-            <ul class="aggregated-completedQueries collapsible-table">
+          <div class="collapsible-table collapse show"
+              id="aggregated-completedQueries">
+            <ul>
               {queryTable(inactiveQueries, request, "completed")}
             </ul>
           </div>
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 16ad10ac3e3a..2b43e2286e48 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
@@ -99,15 +99,16 @@ private[ui] class ThriftServerPage(parent: ThriftServerTab) 
extends WebUIPage(""
       None
     }
     val content =
-      <span id="sqlstat" class="collapse-aggregated-sqlstat collapse-table"
-            data-collapse-name="collapse-aggregated-sqlstat"
-            data-collapse-table="aggregated-sqlstat">
+      <span id="sqlstat" class="collapse-table" data-bs-toggle="collapse"
+            data-bs-target="#aggregated-sqlstat"
+            aria-expanded="true" aria-controls="aggregated-sqlstat"
+            data-collapse-name="collapse-aggregated-sqlstat">
         <h4>
           <span class="collapse-table-arrow arrow-open"></span>
           <a>SQL Statistics ({numStatement})</a>
         </h4>
       </span> ++
-        <div class="aggregated-sqlstat collapsible-table">
+        <div class="collapsible-table collapse show" id="aggregated-sqlstat">
           {table.getOrElse("No statistics have been generated yet.")}
         </div>
     content
@@ -146,15 +147,16 @@ private[ui] class ThriftServerPage(parent: 
ThriftServerTab) extends WebUIPage(""
     }
 
     val content =
-    <span id="sessionstat" class="collapse-aggregated-sessionstat 
collapse-table"
-          data-collapse-name="collapse-aggregated-sessionstat"
-          data-collapse-table="aggregated-sessionstat">
+    <span id="sessionstat" class="collapse-table" data-bs-toggle="collapse"
+          data-bs-target="#aggregated-sessionstat"
+          aria-expanded="true" aria-controls="aggregated-sessionstat"
+          data-collapse-name="collapse-aggregated-sessionstat">
       <h4>
         <span class="collapse-table-arrow arrow-open"></span>
         <a>Session Statistics ({numSessions})</a>
       </h4>
     </span> ++
-      <div class="aggregated-sessionstat collapsible-table">
+      <div class="collapsible-table collapse show" id="aggregated-sessionstat">
         {table.getOrElse("No statistics have been generated yet.")}
       </div>
 
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 140161ff25fd..b14a170a5164 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
@@ -101,15 +101,16 @@ private[ui] class ThriftServerSessionPage(parent: 
ThriftServerTab)
       None
     }
     val content =
-      <span id="sqlsessionstat" class="collapse-aggregated-sqlsessionstat 
collapse-table"
-            data-collapse-name="collapse-aggregated-sqlsessionstat"
-            data-collapse-table="aggregated-sqlsessionstat">
+      <span id="sqlsessionstat" class="collapse-table" 
data-bs-toggle="collapse"
+            data-bs-target="#aggregated-sqlsessionstat"
+            aria-expanded="true" aria-controls="aggregated-sqlsessionstat"
+            data-collapse-name="collapse-aggregated-sqlsessionstat">
         <h4>
           <span class="collapse-table-arrow arrow-open"></span>
           <a>SQL Statistics</a>
         </h4>
       </span> ++
-        <div class="aggregated-sqlsessionstat collapsible-table">
+        <div class="collapsible-table collapse show" 
id="aggregated-sqlsessionstat">
           {table.getOrElse("No statistics have been generated yet.")}
         </div>
 
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 ae169491edf8..580cac17b68c 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
@@ -101,8 +101,8 @@ class ThriftServerPageSuite extends SparkFunSuite with 
BeforeAndAfter {
     assert(html.contains("<label style=\"white-space: nowrap;\">1 pages. jump 
to</label>"))
 
     // Hiding table support
-    assert(html.contains("class=\"collapse-aggregated-sessionstat" +
-       " collapse-table\" 
data-collapse-name=\"collapse-aggregated-sessionstat\""))
+    assert(html.contains("class=\"collapse-table\" 
data-bs-toggle=\"collapse\"" +
+       " data-bs-target=\"#aggregated-sessionstat\""))
   }
 
   test("thriftserver session page should load successfully") {
@@ -127,8 +127,8 @@ class ThriftServerPageSuite extends SparkFunSuite with 
BeforeAndAfter {
     assert(html.contains("<label style=\"white-space: nowrap;\">1 pages. jump 
to</label>"))
 
     // Hiding table support
-    assert(html.contains("collapse-aggregated-sqlsessionstat collapse-table\"" 
+
-          " data-collapse-name=\"collapse-aggregated-sqlsessionstat\""))
+    assert(html.contains("collapse-table\" data-bs-toggle=\"collapse\"" +
+          " data-bs-target=\"#aggregated-sqlsessionstat\""))
   }
 }
 
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 7a74c2135947..e2caf5256226 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
@@ -480,15 +480,18 @@ private[ui] class StreamingPage(parent: StreamingTab)
       content ++=
         <div class="row">
           <div class="col-12">
-            <span id="runningBatches" 
class="collapse-aggregated-runningBatches collapse-table"
-                  data-collapse-name="collapse-aggregated-runningBatches"
-                  data-collapse-table="aggregated-runningBatches">
+            <span id="runningBatches" class="collapse-table"
+                  data-bs-toggle="collapse"
+                  data-bs-target="#aggregated-runningBatches"
+                  aria-expanded="true" 
aria-controls="aggregated-runningBatches"
+                  data-collapse-name="collapse-aggregated-runningBatches">
               <h4>
                 <span class="collapse-table-arrow arrow-open"></span>
                 <a>Running Batches ({runningBatches.size})</a>
               </h4>
             </span>
-            <div class="aggregated-runningBatches collapsible-table">
+            <div class="collapsible-table collapse show"
+                id="aggregated-runningBatches">
               { streamingTable(request, runningBatches, "runningBatches") }
             </div>
           </div>
@@ -499,15 +502,18 @@ private[ui] class StreamingPage(parent: StreamingTab)
       content ++=
         <div class="row">
           <div class="col-12">
-            <span id="waitingBatches" 
class="collapse-aggregated-waitingBatches collapse-table"
-                  data-collapse-name="collapse-aggregated-waitingBatches"
-                  data-collapse-table="aggregated-waitingBatches">
+            <span id="waitingBatches" class="collapse-table"
+                  data-bs-toggle="collapse"
+                  data-bs-target="#aggregated-waitingBatches"
+                  aria-expanded="true" 
aria-controls="aggregated-waitingBatches"
+                  data-collapse-name="collapse-aggregated-waitingBatches">
               <h4>
                 <span class="collapse-table-arrow arrow-open"></span>
                 <a>Waiting Batches ({waitingBatches.size})</a>
               </h4>
             </span>
-            <div class="aggregated-waitingBatches collapsible-table">
+            <div class="collapsible-table collapse show"
+                id="aggregated-waitingBatches">
               { streamingTable(request, waitingBatches, "waitingBatches") }
             </div>
           </div>
@@ -518,16 +524,20 @@ private[ui] class StreamingPage(parent: StreamingTab)
       content ++=
         <div class="row">
           <div class="col-12">
-            <span id="completedBatches" 
class="collapse-aggregated-completedBatches collapse-table"
-                  data-collapse-name="collapse-aggregated-completedBatches"
-                  data-collapse-table="aggregated-completedBatches">
+            <span id="completedBatches" class="collapse-table"
+                  data-bs-toggle="collapse"
+                  data-bs-target="#aggregated-completedBatches"
+                  aria-expanded="true"
+                  aria-controls="aggregated-completedBatches"
+                  data-collapse-name="collapse-aggregated-completedBatches">
               <h4>
                 <span class="collapse-table-arrow arrow-open"></span>
                 <a>Completed Batches (last {completedBatches.size}
                   out of {listener.numTotalCompletedBatches})</a>
               </h4>
             </span>
-            <div class="aggregated-completedBatches collapsible-table">
+            <div class="collapsible-table collapse show"
+                id="aggregated-completedBatches">
               { streamingTable(request, completedBatches, "completedBatches") }
             </div>
           </div>


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

Reply via email to