From f00351706e67fa242e59ab5141991845a4c66215 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Fromme?= Date: Mon, 17 Aug 2026 16:07:26 +0200 Subject: [PATCH] feat: extract collapsible container into partial --- assets/controllers/toggle_controller.js | 6 +- assets/images/icons.svg | 1 + templates/_partials/_collapsible.html.twig | 35 ++++++++++ templates/groups/booking/offer.html.twig | 77 ++++++++-------------- 4 files changed, 69 insertions(+), 50 deletions(-) create mode 100644 templates/_partials/_collapsible.html.twig diff --git a/assets/controllers/toggle_controller.js b/assets/controllers/toggle_controller.js index 3801722..2befb7d 100644 --- a/assets/controllers/toggle_controller.js +++ b/assets/controllers/toggle_controller.js @@ -2,7 +2,7 @@ import {Controller} from '@hotwired/stimulus' export default class extends Controller { static classes = ['closed', 'open', 'iconOpen'] - static targets = ['content', 'icon', 'container'] + static targets = ['content', 'icon', 'container', 'trigger'] static values = { open: { type: Boolean, @@ -43,6 +43,10 @@ export default class extends Controller { this.iconTarget.classList.toggle(iconClass, true === open) } + if (this.hasTriggerTarget) { + this.triggerTarget.setAttribute('aria-expanded', String(open)) + } + // Toggle class on container element (or controller element) if specified if (this.hasOpenClass) { const container = this.hasContainerTarget ? this.containerTarget : this.element diff --git a/assets/images/icons.svg b/assets/images/icons.svg index 0861f14..748de87 100644 --- a/assets/images/icons.svg +++ b/assets/images/icons.svg @@ -21,6 +21,7 @@ + diff --git a/templates/_partials/_collapsible.html.twig b/templates/_partials/_collapsible.html.twig new file mode 100644 index 0000000..f7b2582 --- /dev/null +++ b/templates/_partials/_collapsible.html.twig @@ -0,0 +1,35 @@ +{# + Collapsible section with a heading trigger and a chevron. + + heading string visible heading text (required) + id string unique per page; wires aria-controls (required) + open bool initial state (default false) + headingLevel int aria-level of the heading (default 2) + contentClass string classes on the body wrapper (default 'rte-content') + storageKey string persist open state in sessionStorage (default '') +#} +
+ + +
+ {% block body %}{% endblock %} +
+
diff --git a/templates/groups/booking/offer.html.twig b/templates/groups/booking/offer.html.twig index 595b5f9..62ae2ca 100644 --- a/templates/groups/booking/offer.html.twig +++ b/templates/groups/booking/offer.html.twig @@ -97,25 +97,11 @@ {# hotel description #} {% if ctx.hotelCmsData is not null %} -
- - -
+ {% embed '_partials/_collapsible.html.twig' with { + heading: 'Die Unterkunft', + id: 'accommodation', + } %} + {% block body %} {% set icons = ctx.hotelCmsData.icons %} {% set iconMap = { bedsCount: { icon: 'bed', label: 'Anzahl Betten' }, @@ -167,15 +153,8 @@ {{ ctx.hotelCmsData.roomTypes | raw }} {% endif %} - - {% if ctx.hotelCmsData.additionalInformation|striptags|trim is not empty %} -

- Weitere Infos -

- {{ ctx.hotelCmsData.additionalInformation | raw }} - {% endif %} -
-
+ {% endblock %} + {% endembed %} {{ macros.imageGallery(ctx.hotelCmsData.images.resized.l, ctx.hotelCmsData.images.resized.m, ctx.accommodation.name) }} {% endif %} @@ -183,25 +162,12 @@ {# region description #} {% if ctx.hotelCmsData is not null and ctx.hotelCmsData.region is not null %} {% set region = ctx.hotelCmsData.region %} -
- - -
+ {% embed '_partials/_collapsible.html.twig' with { + heading: 'Die Region ' ~ region.name, + id: 'region', + region: region, + } %} + {% block body %} {% if region.altitude or region.length or region.lifts %}
    {% if region.altitude %} @@ -229,8 +195,8 @@

    Aktuelles aus der Region

    {{ region.news | raw }} {% endif %} -
-
+ {% endblock %} + {% endembed %} {% if region.regionMaps is not null and region.regionMaps | length > 0 %} {% set regionMapImages = region.regionMaps | map(url => {url: url}) %} @@ -239,6 +205,19 @@ {{ macros.imageGallery(region.images.resized.l ?? [], region.images.resized.m ?? [], region.name) }} {% endif %} + + {# additional information #} + {% if ctx.hotelCmsData is not null and ctx.hotelCmsData.additionalInformation|striptags|trim is not empty %} + {% embed '_partials/_collapsible.html.twig' with { + heading: 'Zusatzinformationen', + id: 'additional-information', + } %} + {% block body %} + {{ ctx.hotelCmsData.additionalInformation | raw }} + {% endblock %} + {% endembed %} + {% endif %} +