diff --git a/modules/localgov_subsites_paragraphs/css/localgov-accordion.css b/modules/localgov_subsites_paragraphs/css/localgov-accordion.css index b56b0b6..f2e5f56 100644 --- a/modules/localgov_subsites_paragraphs/css/localgov-accordion.css +++ b/modules/localgov_subsites_paragraphs/css/localgov-accordion.css @@ -3,29 +3,17 @@ * Basic styling for Accordion paragraph. */ -.accordion-pane__title button { - width: 100%; - text-align: left; -} - -.accordion-pane__title button[hidden] { - display: none; -} - -.accordion--initialised .accordion-pane__content { - display: none; -} - -.accordion--initialised .accordion-pane__content--open { - display: block; -} - -/* initial hide of icon within the button, retain pointer events setting if used */ -.accordion-icon { - display: none; - pointer-events: none; -} - .accordion-toggle-all { margin-bottom: var(--vertical-rhythm-spacing); } + +/* Styling tweaks for layout builder only */ +.js-lpb-component .accordion-pane__title h2, +.js-lpb-component .accordion-pane__title h3, +.js-lpb-component .accordion-pane__title h4, +.js-lpb-component .accordion-pane__title h5, +.js-lpb-component .accordion-pane__title h6 { + display: inline; + margin-block-end: 0; + font-size: 1rem; +} diff --git a/modules/localgov_subsites_paragraphs/js/localgov-accordion.js b/modules/localgov_subsites_paragraphs/js/localgov-accordion.js index 9021a2c..6011208 100644 --- a/modules/localgov_subsites_paragraphs/js/localgov-accordion.js +++ b/modules/localgov_subsites_paragraphs/js/localgov-accordion.js @@ -3,7 +3,7 @@ * Localgov Accordion behaviour. */ -(Drupal => { +((Drupal) => { Drupal.behaviors.localgovAccordion = { /** * Attach accordion behaviour. @@ -27,32 +27,14 @@ * @param {number} index * Accordion element index. */ - init: function init(accordion, index) { - /** - * Expands one accordion pane, setting aria-expanded on button. - * - * @param {HTMLElement} button - * The button associated with the pane to expand. - * @param {HTMLElement} pane - * The pane to expand. - */ - function expandPane(button, pane) { - button.setAttribute('aria-expanded', 'true'); - pane.classList.add(openClass); - } - - /** - * Collapses one accordion pane, setting aria-expanded on button. - * - * @param {HTMLElement} button - * The button associated with the pane to collapse. - * @param {HTMLElement} pane - * The pane to collapse. - */ - function collapsePane(button, pane) { - button.setAttribute('aria-expanded', 'false'); - pane.classList.remove(openClass); - } + init: function init(accordion) { + const accordionPanes = accordion.querySelectorAll('.accordion-pane'); + const numberOfPanes = accordionPanes.length; + const displayShowHide = accordion.hasAttribute( + 'data-accordion-display-show-hide', + ); + let showHideButton; + let showHideButtonLabel; /** * Toggles all accordion panes open or closed. @@ -60,197 +42,30 @@ * Used both as an event listener callback, and called directly. */ function toggleAll() { - const labelEl = showHideButton.querySelector('.accordion-text'); - const nextState = showHideButton.getAttribute('aria-expanded') !== 'true'; + const nextState = + showHideButton.getAttribute('aria-expanded') !== 'true'; - showHideButtonLabel.textContent = showHideButton.dataset[nextState ? 'hideAll' : 'showAll']; + showHideButtonLabel.textContent = + showHideButton.dataset[nextState ? 'hideAll' : 'showAll']; showHideButton.setAttribute('aria-expanded', nextState); - for (let i = 0; i < numberOfPanes; i++) { - const currentButton = accordionPanes[i].querySelector('[aria-controls]'); - const currentPane = accordionPanes[i].querySelector('.accordion-pane__content'); + const tabopen = nextState + ? 'details:not([open]) summary' + : 'details[open] summary'; - if (nextState) { - expandPane(currentButton, currentPane); - - } else { - collapsePane(currentButton, currentPane); - } - } - } - - /** - * Gets the state of the accordion: all expanded, all collapsed, or mixed. - * - * @return {number} - * Returns a numeric value according to state: - * - * - all expanded: 1 - * - all collapsed: 0 - * - mixed: -1 - */ - function getAccordionState() { - const expandedPanes = accordion.querySelectorAll(`.${openClass}`).length; - return expandedPanes - ? (expandedPanes === numberOfPanes ? 1 : -1) - : 0; - } - - const accordionPanes = accordion.querySelectorAll('.accordion-pane'); - const numberOfPanes = accordionPanes.length; - const initClass = 'accordion--initialised'; - const openClass = 'accordion-pane__content--open'; - const breakpoint = accordion.dataset.accordionTabsSwitch || null; - const mq = window.matchMedia(`(max-width: '${breakpoint}')`); - const displayShowHide = accordion.hasAttribute('data-accordion-display-show-hide'); - const allowMultiple = displayShowHide || accordion.hasAttribute('data-accordion-allow-multiple'); - let showHideButton; - let showHideButtonLabel; - - const create = function create() { - // Only initialise accordion if it hasn't already been done. - if (accordion.classList.contains(initClass)) { - return; - } - - for (let i = 0; i < numberOfPanes; i++) { - const pane = accordionPanes[i]; - const content = pane.querySelectorAll('.accordion-pane__content'); - const title = pane.querySelectorAll('.accordion-pane__title'); - const button = title[0].querySelector('button'); - const heading = title[0].querySelector('.accordion-pane__heading'); - const id = `accordion-content-${index}-${i}`; - - // Add id attribute to all pane content elements. - content[0].setAttribute('id', id); - - // Hide default Heading text - if (heading) { - heading.hidden = true; - }; - - if (button) { - // Add aria-controls id to button and un-hide - button.setAttribute('aria-controls', id); - button.hidden = false; - - // Add click event listener to the show/hide button. - button.addEventListener('click', e => { - const targetPaneId = e.target.getAttribute('aria-controls'); - const targetPane = accordion.querySelectorAll(`#${targetPaneId}`); - const openPane = accordion.querySelectorAll(`.${openClass}`); - - // Check the current state of the button and the content it controls. - if (e.target.getAttribute('aria-expanded') === 'false') { - // Close currently open pane. - if (openPane.length && !allowMultiple) { - const openPaneId = openPane[0].getAttribute('id'); - const openPaneButton = accordion.querySelectorAll( - `[aria-controls="${openPaneId}"]`, - ); - - collapsePane(openPaneButton[0], openPane[0]); - } - - // Show new pane. - expandPane(e.target, targetPane[0]); - } else { - // If target pane is currently open, close it. - collapsePane(e.target, targetPane[0]); - } - - if (showHideButton) { - const accordionState = getAccordionState(); - const toggleState = showHideButton.getAttribute('aria-expanded') === 'true'; - - if ( - (accordionState === 1 && !toggleState) || - (!accordionState && toggleState) - ) { - toggleAll(); - } - } - }); - }; - - if (button) { - if (displayShowHide) { - showHideButton = accordion.querySelector('.accordion-toggle-all'); - showHideButton.hidden = false; - showHideButton.addEventListener('click', toggleAll); - showHideButtonLabel = showHideButton.querySelector('.accordion-text'); - } - - // Add init class. - accordion.classList.add(initClass); - }; - - } - }; - - const destroy = () => { for (let i = 0; i < numberOfPanes; i++) { - // Remove id attributes from buttons in accordion pane titles. - const button = accordion - .querySelectorAll('.accordion-pane__title')[i] - .querySelector('button') - .removeAttribute('id'); - - // Hide buttons in accordion pane titles. - if (button) { - button.hidden = true; - } - - // Un-hide default heading text - const heading = accordion - .querySelectorAll('.accordion-pane__title')[i] - .querySelector('.accordion-pane__heading'); - - if (heading) { - heading.hidden = false; - } - - // Remove id attributes from pane content elements. - accordionPanes[i] - .querySelectorAll('.accordion-pane__content')[0] - .removeAttribute('id'); - - // Remove open class from accordion pane's content elements. - if ( - accordionPanes[i] - .querySelectorAll('.accordion-pane__content')[0] - .classList.contains(openClass) - ) { - accordionPanes[i] - .querySelectorAll('.accordion-pane__content')[0] - .classList.remove(openClass); - } + const accordionSummary = accordionPanes[i].querySelector(tabopen); + accordionSummary?.click(); } + } + for (let i = 0; i < numberOfPanes; i++) { if (displayShowHide) { - showHideButton.hidden = true; - showHideButton.removeEventListener('click', toggleAll); - } - - // Remove accordion init class. - accordion.classList.remove(initClass); - }; - - const breakpointCheck = function breakpointCheck() { - if (mq.matches || breakpoint === null) { - create(); - } else { - destroy(); + showHideButton = accordion.querySelector('.accordion-toggle-all'); + showHideButton.hidden = false; + showHideButton.addEventListener('click', toggleAll); + showHideButtonLabel = showHideButton.querySelector('.accordion-text'); } - }; - - // Trigger create/destroy functions at different screen widths - // based on the value of data-accordion-tabs-switch attribute. - if (window.matchMedia) { - mq.addEventListener("change", () => { - breakpointCheck(); - }); - breakpointCheck(); } }, }; diff --git a/modules/localgov_subsites_paragraphs/templates/paragraph--localgov-accordion-pane.html.twig b/modules/localgov_subsites_paragraphs/templates/paragraph--localgov-accordion-pane.html.twig index d0a622b..3d6e75f 100644 --- a/modules/localgov_subsites_paragraphs/templates/paragraph--localgov-accordion-pane.html.twig +++ b/modules/localgov_subsites_paragraphs/templates/paragraph--localgov-accordion-pane.html.twig @@ -48,21 +48,23 @@ 'accordion-pane' ] %} + +{% set accordion = paragraph.getParentEntity() %} +{% set group_accordion = accordion.localgov_allow_multiple_open.value == 1 and accordion.localgov_display_show_hide_all.value != 1 %} + {% block paragraph %}