diff --git a/CHANGELOG.MD b/CHANGELOG.MD index ef681b33..a5e6b346 100644 --- a/CHANGELOG.MD +++ b/CHANGELOG.MD @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +- TMS-1044: Accordion-block changes + - Add open all & close all -buttons & js functionalities + - Add open / close text next to accordion toggler icon + ## [1.8.13] - 2024-05-20 - TMS-1028: Add social media link-list block, component & footer section diff --git a/assets/scripts/accordion.js b/assets/scripts/accordion.js index 8c8a78e4..ff585569 100644 --- a/assets/scripts/accordion.js +++ b/assets/scripts/accordion.js @@ -19,6 +19,8 @@ export default class Accordion { if ( this.mainContainer ) { + this.openAllButton = document.querySelectorAll( '.accordion__open-all' ); + this.closeAllButton = document.querySelectorAll( '.accordion__close-all' ); this.dropdownTogglers = document.querySelectorAll( '.accordion__title-button' ); this.dropdowns = document.querySelectorAll( '.accordion__content' ); @@ -46,6 +48,154 @@ export default class Accordion { ); } } + + if ( this.mainContainer ) { + for ( let i = 0; i < this.mainContainer.length; i++ ) { + this.openAllButton[ i ].addEventListener( + 'click', + () => this.openAllDropdowns( + this.mainContainer[ i ], + this.openAllButton[ i ], + this.closeAllButton[ i ] + ) + ); + + this.closeAllButton[ i ].addEventListener( + 'click', + () => this.closeAllDropdowns( + this.mainContainer[ i ], + this.closeAllButton[ i ], + this.openAllButton[ i ] + ) + ); + + if ( this.dropdownTogglers ) { + const togglers = this.mainContainer[ i ].getElementsByClassName( 'accordion__title-button' ); + + for ( let x = 0; x < togglers.length; x++ ) { + togglers[ x ].addEventListener( + 'click', + () => this.updateButtonStates( + this.mainContainer[ i ], + this.openAllButton[ i ], + this.closeAllButton[ i ] + ) + ); + } + } + } + } + } + + /** + * Opens all dropdowns. + * + * @param {HTMLDivElement} mainContainer Main container for accordion dropdowns. + * @param {HTMLButtonElement} openAllButton The open all -button that was clicked. + * @param {HTMLButtonElement} closeAllButton The close all -button to be shown. + * + * @return {void} + */ + openAllDropdowns( mainContainer, openAllButton, closeAllButton ) { + const dropdowns = mainContainer.getElementsByClassName( 'accordion__title-button' ); + + for ( let i = 0; i < dropdowns.length; i++ ) { + const containerId = dropdowns[ i ].getAttribute( 'aria-controls' ); + const dropDownContent = document.querySelector( `#${ containerId }` ); + const textOpen = dropdowns[ i ].querySelector( '.icon-text--open' ); + const textClose = dropdowns[ i ].querySelector( '.icon-text--close' ); + + textOpen.setAttribute( 'aria-hidden', 'true' ); + textClose.setAttribute( 'aria-hidden', 'false' ); + dropdowns[ i ].setAttribute( 'aria-expanded', 'true' ); + if ( ! dropdowns[ i ].classList.contains( 'active-accordion' ) ) { + dropdowns[ i ].classList.add( 'active-accordion' ); + } + + dropDownContent.classList.remove( 'is-hidden' ); + + if ( ! dropdowns[ i ].classList.contains( 'is-hidden' ) + && ! dropdowns[ i ].classList.contains( 'accordion--table-initialized' ) ) { + + const accordionTables = dropDownContent.getElementsByTagName( 'table' ); + + if ( accordionTables.length > 0 ) { + new Indicate( accordionTables, { arrows: true } ); + + dropdowns[ i ].classList.add( 'accordion--table-initialized' ); + } + } + } + + closeAllButton.classList.remove( 'is-hidden' ); + openAllButton.classList.add( 'is-hidden' ); + } + + /** + * Closes all dropdowns. + * + * @param {HTMLDivElement} mainContainer Main container for accordion dropdowns. + * @param {HTMLButtonElement} closeAllButton The close all -button that was clicked. + * @param {HTMLButtonElement} openAllButton The open all -button to be shown. + * + * @return {void} + */ + closeAllDropdowns( mainContainer, closeAllButton, openAllButton ) { + const dropdowns = mainContainer.getElementsByClassName( 'accordion__title-button' ); + + for ( let i = 0; i < dropdowns.length; i++ ) { + const containerId = dropdowns[ i ].getAttribute( 'aria-controls' ); + const dropDownContent = document.querySelector( `#${ containerId }` ); + const textOpen = dropdowns[ i ].querySelector( '.icon-text--open' ); + const textClose = dropdowns[ i ].querySelector( '.icon-text--close' ); + + textOpen.setAttribute( 'aria-hidden', 'false' ); + textClose.setAttribute( 'aria-hidden', 'true' ); + dropdowns[ i ].setAttribute( 'aria-expanded', 'false' ); + if ( dropdowns[ i ].classList.contains( 'active-accordion' ) ) { + dropdowns[ i ].classList.remove( 'active-accordion' ); + } + + dropDownContent.classList.add( 'is-hidden' ); + + if ( dropdowns[ i ].classList.contains( 'is-hidden' ) + && dropdowns[ i ].classList.contains( 'accordion--table-initialized' ) ) { + + const accordionTables = dropDownContent.getElementsByTagName( 'table' ); + + if ( accordionTables.length > 0 ) { + new Indicate( accordionTables, { arrows: true } ); + + dropdowns[ i ].classList.remove( 'accordion--table-initialized' ); + } + } + } + + openAllButton.classList.remove( 'is-hidden' ); + closeAllButton.classList.add( 'is-hidden' ); + } + + /** + * Updates "Close all" or "Open all" -button states depending on open accordion dropdowns. + * + * @param {HTMLDivElement} mainContainer Main container for accordion dropdowns. + * @param {HTMLButtonElement} openAllButton The open all -button. + * @param {HTMLButtonElement} closeAllButton The close all -button. + * + * @return {void} + */ + updateButtonStates( mainContainer, openAllButton, closeAllButton ) { + const dropdowns = mainContainer.getElementsByClassName( 'accordion__title-button' ); + const openDropdowns = mainContainer.getElementsByClassName( 'active-accordion' ); + + if ( openDropdowns.length === dropdowns.length ) { + closeAllButton.classList.remove( 'is-hidden' ); + openAllButton.classList.add( 'is-hidden' ); + } + else { + openAllButton.classList.remove( 'is-hidden' ); + closeAllButton.classList.add( 'is-hidden' ); + } } /** @@ -58,7 +208,11 @@ export default class Accordion { toggleDropdown( clickedToggler ) { const containerId = clickedToggler.getAttribute( 'aria-controls' ); const dropDownContent = document.querySelector( `#${ containerId }` ); + const textOpen = clickedToggler.querySelector( '.icon-text--open' ); + const textClose = clickedToggler.querySelector( '.icon-text--close' ); + this.toggleAriaHidden( textOpen ); + this.toggleAriaHidden( textClose ); this.toggleAriaExpanded( clickedToggler ); dropDownContent.classList.toggle( 'is-hidden' ); @@ -96,6 +250,18 @@ export default class Accordion { } + /** + * Get the icon-texts aria-hidden current state and set a new opposite state to it. + * + * @param {HTMLElement} iconText The icon-text element. + * + * @return {void} + */ + toggleAriaHidden( iconText ) { + const ariaHiddenState = iconText.getAttribute( 'aria-hidden' ) === 'false' ? true : false; + iconText.setAttribute( 'aria-hidden', ariaHiddenState ); + } + /** * Add an unique identifier to each accordion. * diff --git a/assets/styles/blocks/custom/_accordion.scss b/assets/styles/blocks/custom/_accordion.scss index 106a35ba..e10edb38 100644 --- a/assets/styles/blocks/custom/_accordion.scss +++ b/assets/styles/blocks/custom/_accordion.scss @@ -1,4 +1,22 @@ .accordion { + &__open-all, + &__close-all { + color: $primary !important; + background-color: transparent !important; + border: none !important; + border-radius: 0 !important; + + .icon { + margin-left: $theme-spacing-three-quarters !important; + } + + &:hover { + filter: none !important; + box-shadow: none !important; + text-decoration: underline !important; + } + } + &__content { p { clear: both; @@ -25,6 +43,14 @@ .icon { transform: rotate(180deg); } + + .icon-text--open { + display: none; + } + + .icon-text--close { + display: inline-block; + } } &:hover, @@ -34,8 +60,19 @@ } &__title-icon { - .icon { - transition: transform ease-in .2s; + align-items: center; + } + + &__icon-text { + color: $primary; + font-size: $base-size; + + &.icon-text--open { + display: inline-block; + } + + &.icon-text--close { + display: none; } } diff --git a/lang/fi.mo b/lang/fi.mo index 4bb8dcec..3381c6e1 100644 Binary files a/lang/fi.mo and b/lang/fi.mo differ diff --git a/lang/fi.po b/lang/fi.po index 35f4874e..6a82ba07 100644 --- a/lang/fi.po +++ b/lang/fi.po @@ -1,8 +1,8 @@ msgid "" msgstr "" "Project-Id-Version: TMS Theme Base\n" -"POT-Creation-Date: 2024-03-25 14:09+0200\n" -"PO-Revision-Date: 2024-03-25 14:10+0200\n" +"POT-Creation-Date: 2024-05-29 12:12+0300\n" +"PO-Revision-Date: 2024-05-29 12:13+0300\n" "Last-Translator: \n" "Language-Team: \n" "Language: fi\n" @@ -54,7 +54,7 @@ msgstr "Sivun komponentit" #: lib/ACF/FrontPageGroup.php:90 lib/ACF/OnepagerGroup.php:126 #: lib/ACF/PageGroup.php:157 lib/ACF/PageProjectGroup.php:60 #: lib/ACF/PostGroup.php:173 lib/ACF/ProgramGroup.php:304 -#: lib/ACF/ProjectGroup.php:394 +#: lib/ACF/ProjectGroup.php:425 msgctxt "theme ACF" msgid "Components" msgstr "Komponentit" @@ -74,7 +74,7 @@ msgctxt "theme ACF" msgid "Asetukset" msgstr "" -#: lib/ACF/PostGroup.php:129 lib/ACF/ProjectGroup.php:448 +#: lib/ACF/PostGroup.php:129 lib/ACF/ProjectGroup.php:479 msgid "Related posts" msgstr "Luitko jo nämä?" @@ -127,6 +127,26 @@ msgctxt "pagination" msgid "Previous" msgstr "Edellinen" +#: lib/Formatters/AccordionFormatter.php:57 +msgctxt "theme-frontend" +msgid "Expand" +msgstr "Avaa" + +#: lib/Formatters/AccordionFormatter.php:58 +msgctxt "theme-frontend" +msgid "Collapse" +msgstr "Sulje" + +#: lib/Formatters/AccordionFormatter.php:59 +msgctxt "theme-frontend" +msgid "Expand all sections" +msgstr "Avaa kaikki sisällöt" + +#: lib/Formatters/AccordionFormatter.php:60 +msgctxt "theme-frontend" +msgid "Collapse all sections" +msgstr "Sulje kaikki sisällöt" + #: lib/Formatters/CountdownFormatter.php:80 msgctxt "theme-frontend" msgid "Days" @@ -522,7 +542,7 @@ msgstr "Valitse salkku" msgid "Also show completed projects" msgstr "Näytä myös päättyneet projektit" -#: models/page-project.php:322 +#: models/page-project.php:323 #, php-format msgctxt "filter with search clause results summary" msgid "%1$1s result found for \"%2$2s\"" @@ -530,7 +550,7 @@ msgid_plural "%1$1s results found for \"%2$2s\"" msgstr[0] "%1$1s tulos haulle “%2$2s”" msgstr[1] "%1$1s tulosta haulle “%2$2s”" -#: models/page-project.php:336 +#: models/page-project.php:337 #, php-format msgctxt "filter results summary" msgid "%1$1s result found" diff --git a/lang/tms-theme-base.pot b/lang/tms-theme-base.pot index 40f1f0e5..fc8d7ba1 100644 --- a/lang/tms-theme-base.pot +++ b/lang/tms-theme-base.pot @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: TMS Theme Base\n" -"POT-Creation-Date: 2024-03-25 14:09+0200\n" +"POT-Creation-Date: 2024-05-29 12:12+0300\n" "PO-Revision-Date: 2022-01-12 10:08+0200\n" "Last-Translator: \n" "Language-Team: \n" @@ -54,7 +54,7 @@ msgstr "" #: lib/ACF/FrontPageGroup.php:90 lib/ACF/OnepagerGroup.php:126 #: lib/ACF/PageGroup.php:157 lib/ACF/PageProjectGroup.php:60 #: lib/ACF/PostGroup.php:173 lib/ACF/ProgramGroup.php:304 -#: lib/ACF/ProjectGroup.php:394 +#: lib/ACF/ProjectGroup.php:425 msgctxt "theme ACF" msgid "Components" msgstr "" @@ -74,7 +74,7 @@ msgctxt "theme ACF" msgid "Asetukset" msgstr "" -#: lib/ACF/PostGroup.php:129 lib/ACF/ProjectGroup.php:448 +#: lib/ACF/PostGroup.php:129 lib/ACF/ProjectGroup.php:479 msgid "Related posts" msgstr "" @@ -127,6 +127,26 @@ msgctxt "pagination" msgid "Previous" msgstr "" +#: lib/Formatters/AccordionFormatter.php:57 +msgctxt "theme-frontend" +msgid "Expand" +msgstr "" + +#: lib/Formatters/AccordionFormatter.php:58 +msgctxt "theme-frontend" +msgid "Collapse" +msgstr "" + +#: lib/Formatters/AccordionFormatter.php:59 +msgctxt "theme-frontend" +msgid "Expand all sections" +msgstr "" + +#: lib/Formatters/AccordionFormatter.php:60 +msgctxt "theme-frontend" +msgid "Collapse all sections" +msgstr "" + #: lib/Formatters/CountdownFormatter.php:80 msgctxt "theme-frontend" msgid "Days" @@ -516,7 +536,7 @@ msgstr "" msgid "Also show completed projects" msgstr "" -#: models/page-project.php:322 +#: models/page-project.php:323 #, php-format msgctxt "filter with search clause results summary" msgid "%1$1s result found for \"%2$2s\"" @@ -524,7 +544,7 @@ msgid_plural "%1$1s results found for \"%2$2s\"" msgstr[0] "" msgstr[1] "" -#: models/page-project.php:336 +#: models/page-project.php:337 #, php-format msgctxt "filter results summary" msgid "%1$1s result found" diff --git a/lib/Formatters/AccordionFormatter.php b/lib/Formatters/AccordionFormatter.php index 6926c3ad..211745ca 100644 --- a/lib/Formatters/AccordionFormatter.php +++ b/lib/Formatters/AccordionFormatter.php @@ -53,6 +53,13 @@ public function format( array $data ) : array { return $section; }, $sections ); + $data['strings'] = [ + 'expand' => \_x( 'Expand', 'theme-frontend', 'tms-theme-tredu' ), + 'collapse' => \_x( 'Collapse', 'theme-frontend', 'tms-theme-tredu' ), + 'expand_all' => \_x( 'Expand all sections', 'theme-frontend', 'tms-theme-tredu' ), + 'collapse_all' => \_x( 'Collapse all sections', 'theme-frontend', 'tms-theme-tredu' ), + ]; + return $data; } } diff --git a/partials/blocks/block-accordion.dust b/partials/blocks/block-accordion.dust index 326583e2..869561a8 100644 --- a/partials/blocks/block-accordion.dust +++ b/partials/blocks/block-accordion.dust @@ -13,6 +13,20 @@ {?sections} + + + +