From 5ff14aff0abc3904b397bef29e619d9035958e10 Mon Sep 17 00:00:00 2001 From: wgoldm03 Date: Mon, 13 Apr 2026 15:12:18 -0400 Subject: [PATCH 1/4] Move final code for collapsible sidebar into final branch --- .../stylesheets/batch_connect/sessions.scss | 32 ++++++++++++++ apps/dashboard/app/javascript/application.js | 1 + .../batch_connect/sidebar_collapsible.js | 43 +++++++++++++++++++ .../batch_connect/shared/_app_list.html.erb | 18 ++++++-- 4 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 apps/dashboard/app/javascript/batch_connect/sidebar_collapsible.js diff --git a/apps/dashboard/app/assets/stylesheets/batch_connect/sessions.scss b/apps/dashboard/app/assets/stylesheets/batch_connect/sessions.scss index 922448f7ce..dd5e99a9ab 100644 --- a/apps/dashboard/app/assets/stylesheets/batch_connect/sessions.scss +++ b/apps/dashboard/app/assets/stylesheets/batch_connect/sessions.scss @@ -31,6 +31,38 @@ background-color: #f5f5f5; } +.collapsible-app-card { + .collapsible-app-card-toggle { + width: 100%; + text-align: left; + border: 0; + cursor: pointer; + display: flex; + align-items: center; + justify-content: space-between; + } + + .collapsible-app-card-toggle::after { + content: "▸"; + margin-left: 0.5rem; + transition: transform 0.2s ease; + } + + .list-group { + display: none; + } + + &.is-open { + .collapsible-app-card-toggle::after { + transform: rotate(90deg); + } + + .list-group { + display: block; + } + } +} + .custom-range { height: 4px; box-shadow: inset 0 1px 10px gray; diff --git a/apps/dashboard/app/javascript/application.js b/apps/dashboard/app/javascript/application.js index fc663208f8..d9ec7224a4 100644 --- a/apps/dashboard/app/javascript/application.js +++ b/apps/dashboard/app/javascript/application.js @@ -37,6 +37,7 @@ import { createPopper } from '@popperjs/core'; import 'bootstrap/dist/js/bootstrap'; import initPopovers from './popovers' +import './batch_connect/sidebar_collapsible'; // lot's of inline scripts and stuff rely on jquery just being available window.jQuery = jQuery; diff --git a/apps/dashboard/app/javascript/batch_connect/sidebar_collapsible.js b/apps/dashboard/app/javascript/batch_connect/sidebar_collapsible.js new file mode 100644 index 0000000000..9eba9e13a5 --- /dev/null +++ b/apps/dashboard/app/javascript/batch_connect/sidebar_collapsible.js @@ -0,0 +1,43 @@ +'use strict'; + +const CARD_SELECTOR = '[data-collapsible-sidebar-card]'; +const TOGGLE_SELECTOR = '.collapsible-app-card-toggle'; + +function setCardState(card, isOpen) { + const toggle = card.querySelector(TOGGLE_SELECTOR); + if (!toggle) return; + + toggle.setAttribute('aria-expanded', isOpen ? 'true' : 'false'); + card.classList.toggle('is-open', isOpen); +} + +function initializeCard(card) { + setCardState(card, false); +} + +function toggleCardFromButton(button) { + const card = button.closest(CARD_SELECTOR); + if (!card) return; + + const isOpen = button.getAttribute('aria-expanded') === 'true'; + const nextOpen = !isOpen; + + setCardState(card, nextOpen); +} + +function setupCollapsibleSidebar() { + const cards = document.querySelectorAll(CARD_SELECTOR); + if (!cards.length) return; + + cards.forEach(initializeCard); +} + +document.addEventListener('click', function(event) { + const button = event.target.closest(TOGGLE_SELECTOR); + if (!button) return; + + toggleCardFromButton(button); +}); + +document.addEventListener('DOMContentLoaded', setupCollapsibleSidebar); +document.addEventListener('turbo:load', setupCollapsibleSidebar); diff --git a/apps/dashboard/app/views/batch_connect/shared/_app_list.html.erb b/apps/dashboard/app/views/batch_connect/shared/_app_list.html.erb index fb3c5273ac..d946c51c88 100644 --- a/apps/dashboard/app/views/batch_connect/shared/_app_list.html.erb +++ b/apps/dashboard/app/views/batch_connect/shared/_app_list.html.erb @@ -1,6 +1,18 @@ -
"> -
<%= title %>
-
+<% + safe_title = title.to_s.parameterize.presence || "group" + card_dom_id = "bc-app-list-#{safe_title}" + list_dom_id = "bc-app-list-#{safe_title}-items" +%> +
" data-collapsible-sidebar-card data-card-id="<%= card_dom_id %>"> + +
<%- OodAppGroup.groups_for( apps: apps, From 3e807ce44b93405f9cba15dcbad4ec1f520f5a4f Mon Sep 17 00:00:00 2001 From: wgoldm03 Date: Mon, 13 Apr 2026 15:22:00 -0400 Subject: [PATCH 2/4] Contributing compliance and testing --- .../batch_connect/sidebar_collapsible.js | 24 ++++++++++++++++++- .../batch_connect/shared/_app_list.html.erb | 9 +++---- .../system/batch_connect_sessions_test.rb | 22 +++++++++++++++++ 3 files changed, 50 insertions(+), 5 deletions(-) diff --git a/apps/dashboard/app/javascript/batch_connect/sidebar_collapsible.js b/apps/dashboard/app/javascript/batch_connect/sidebar_collapsible.js index 9eba9e13a5..d282f566f4 100644 --- a/apps/dashboard/app/javascript/batch_connect/sidebar_collapsible.js +++ b/apps/dashboard/app/javascript/batch_connect/sidebar_collapsible.js @@ -1,8 +1,19 @@ 'use strict'; +/** + * Collapsible Batch Connect sidebar: + * Cards start collapsed and clicking the header toggles the visibility of the + * app list + */ + const CARD_SELECTOR = '[data-collapsible-sidebar-card]'; const TOGGLE_SELECTOR = '.collapsible-app-card-toggle'; +/** + * Updates a card's open/closed state for assistive tech + * @param {HTMLElement} card - The root element + * @param {boolean} isOpen - Whether the card's app list should be visible + */ function setCardState(card, isOpen) { const toggle = card.querySelector(TOGGLE_SELECTOR); if (!toggle) return; @@ -11,10 +22,18 @@ function setCardState(card, isOpen) { card.classList.toggle('is-open', isOpen); } +/** + * Resets a card to the default collapsed state + * @param {HTMLElement} card - The root element + */ function initializeCard(card) { setCardState(card, false); } +/** + * Toggles open/closed state + * @param {HTMLButtonElement} button - The card header toggle control + */ function toggleCardFromButton(button) { const card = button.closest(CARD_SELECTOR); if (!card) return; @@ -25,6 +44,9 @@ function toggleCardFromButton(button) { setCardState(card, nextOpen); } +/** + * Finds all sidebar cards on the current page and initializes them collapsed. + */ function setupCollapsibleSidebar() { const cards = document.querySelectorAll(CARD_SELECTOR); if (!cards.length) return; @@ -32,7 +54,7 @@ function setupCollapsibleSidebar() { cards.forEach(initializeCard); } -document.addEventListener('click', function(event) { +document.addEventListener('click', function onCollapsibleSidebarClick(event) { const button = event.target.closest(TOGGLE_SELECTOR); if (!button) return; diff --git a/apps/dashboard/app/views/batch_connect/shared/_app_list.html.erb b/apps/dashboard/app/views/batch_connect/shared/_app_list.html.erb index d946c51c88..e6665fdfe2 100644 --- a/apps/dashboard/app/views/batch_connect/shared/_app_list.html.erb +++ b/apps/dashboard/app/views/batch_connect/shared/_app_list.html.erb @@ -1,9 +1,10 @@ <% - safe_title = title.to_s.parameterize.presence || "group" - card_dom_id = "bc-app-list-#{safe_title}" - list_dom_id = "bc-app-list-#{safe_title}-items" + # HTML ids use underscores per project convention (see CONTRIBUTING.md). + # Parameterize the card title so ids stay valid and pair with aria-controls. + slug = title.to_s.parameterize(separator: "_").presence || "group" + list_dom_id = "bc_app_list_#{slug}_items" %> -
" data-collapsible-sidebar-card data-card-id="<%= card_dom_id %>"> +
" data-collapsible-sidebar-card> -
+
<%- OodAppGroup.groups_for( apps: apps, diff --git a/apps/dashboard/test/system/batch_connect_sessions_test.rb b/apps/dashboard/test/system/batch_connect_sessions_test.rb index 38b33aea8e..70cd9f2ce9 100644 --- a/apps/dashboard/test/system/batch_connect_sessions_test.rb +++ b/apps/dashboard/test/system/batch_connect_sessions_test.rb @@ -57,19 +57,21 @@ def stub_scheduler(state, cores: 1, nodes: 1) within('nav[aria-label="Interactive Apps Menu"]') do card = find('.collapsible-app-card', match: :first) button = card.find('button.collapsible-app-card-toggle') + target_id = button['aria-controls'] + list_group = card.find("##{target_id}", visible: :all) assert_equal('false', button['aria-expanded']) - assert_not_includes(card[:class], 'is-open') + assert_not_includes(list_group[:class], 'show') button.click + assert_selector("##{target_id}.show") assert_equal('true', button['aria-expanded']) - assert_includes(card[:class], 'is-open') button.click + assert_no_selector("##{target_id}.show") assert_equal('false', button['aria-expanded']) - assert_not_includes(card[:class], 'is-open') end end From 2608c7950c83ff8f3d7dfa6ae3abf38cc503e501 Mon Sep 17 00:00:00 2001 From: wgoldm03 Date: Thu, 16 Apr 2026 09:47:58 -0400 Subject: [PATCH 4/4] Start expanded, simplify css --- .../stylesheets/batch_connect/sessions.scss | 28 ++++++++----------- .../batch_connect/shared/_app_list.html.erb | 4 +-- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/apps/dashboard/app/assets/stylesheets/batch_connect/sessions.scss b/apps/dashboard/app/assets/stylesheets/batch_connect/sessions.scss index 0b3f1175e6..a4dd5ffb2b 100644 --- a/apps/dashboard/app/assets/stylesheets/batch_connect/sessions.scss +++ b/apps/dashboard/app/assets/stylesheets/batch_connect/sessions.scss @@ -33,29 +33,23 @@ .collapsible-app-card { .collapsible-app-card-toggle { - width: 100%; - text-align: left; - border: 0; cursor: pointer; display: flex; align-items: center; justify-content: space-between; - } - .collapsible-app-card-toggle::after { - content: ""; - width: 0; - height: 0; - border-style: solid; - border-width: 0.3rem 0 0.3rem 0.45rem; - border-color: transparent transparent transparent currentColor; - margin-left: 0.5rem; - flex-shrink: 0; - transition: transform 0.2s ease; - } + &::after { + content: ""; + width: 0; + height: 0; + border-style: solid; + border-width: 0.3rem 0 0.3rem 0.45rem; + border-color: transparent transparent transparent currentColor; + } - .collapsible-app-card-toggle[aria-expanded="true"]::after { - transform: rotate(90deg); + &[aria-expanded="true"]::after { + transform: rotate(90deg); + } } } diff --git a/apps/dashboard/app/views/batch_connect/shared/_app_list.html.erb b/apps/dashboard/app/views/batch_connect/shared/_app_list.html.erb index 64b3ae1b0f..d978e757ff 100644 --- a/apps/dashboard/app/views/batch_connect/shared/_app_list.html.erb +++ b/apps/dashboard/app/views/batch_connect/shared/_app_list.html.erb @@ -10,12 +10,12 @@ type="button" data-bs-toggle="collapse" data-bs-target="#<%= list_dom_id %>" - aria-expanded="false" + aria-expanded="true" aria-controls="<%= list_dom_id %>" > <%= title %> -
+
<%- OodAppGroup.groups_for( apps: apps,