Skip to content

Commit c20b1a7

Browse files
author
AJ Griffiths
committed
Merge branch 'feature/gateway-services' into staging
2 parents 738e05b + c25afd6 commit c20b1a7

File tree

15 files changed

+1732
-231
lines changed

15 files changed

+1732
-231
lines changed

package-lock.json

Lines changed: 1293 additions & 216 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
"dependencies": {
7171
"js-cookie": "^3.0.5",
7272
"lite-youtube-embed": "^0.3.2",
73+
"micromodal": "^0.6.1",
7374
"swiper": "^11.2.1"
7475
}
7576
}

tbx/core/blocks.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ def get_button_link(self):
221221
# Ensure page exists and is live.
222222
if block.value and block.value.live:
223223
return block.value.url
224-
elif block_type == "external_link":
224+
elif block_type == "external_link" or block_type == "modal_iframe":
225225
return block.value
226226
elif block_type == "email":
227227
return f"mailto:{block.value}"
@@ -248,6 +248,7 @@ class CallToActionBlock(blocks.StructBlock):
248248
("external_link", blocks.URLBlock()),
249249
("email", blocks.EmailBlock()),
250250
("document_link", DocumentChooserBlock()),
251+
("modal_iframe", blocks.URLBlock()),
251252
],
252253
required=True,
253254
max_num=1,
@@ -268,6 +269,26 @@ class Meta:
268269
template = "patterns/molecules/streamfield/blocks/contact_call_to_action.html"
269270

270271

272+
class StickyCTABlock(blocks.StructBlock):
273+
sticky_text = blocks.CharBlock(max_length=40)
274+
sticky_subtext = blocks.CharBlock(max_length=55)
275+
button_link = blocks.StreamBlock(
276+
[
277+
("internal_link", blocks.PageChooserBlock()),
278+
("external_link", blocks.URLBlock()),
279+
("email", blocks.EmailBlock()),
280+
("document_link", DocumentChooserBlock()),
281+
("modal_iframe", blocks.URLBlock()),
282+
],
283+
required=True,
284+
max_num=1,
285+
)
286+
287+
class Meta:
288+
template = "patterns/molecules/streamfield/blocks/sticky_call_to_action.html"
289+
value_class = ButtonLinkStructValue
290+
291+
271292
class DynamicHeroBlock(blocks.StructBlock):
272293
"""
273294
This block displays text that will be cycled through.
@@ -1233,6 +1254,11 @@ class StoryBlock(blocks.StreamBlock):
12331254
template="patterns/molecules/streamfield/blocks/contact_call_to_action.html",
12341255
group="Calls to action",
12351256
)
1257+
sticky_call_to_action = StickyCTABlock(
1258+
label="Sticky Call to Action",
1259+
template="patterns/molecules/streamfield/blocks/sticky_call_to_action.html",
1260+
group="Calls to action",
1261+
)
12361262
pullquote = PullQuoteBlock(
12371263
template="patterns/molecules/streamfield/blocks/pullquote_block.html",
12381264
group="Basics",
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{% extends "atoms/icon_buttons/icon_button.html" %}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<button class="icon-button{% if modifier %} icon-button--{{ modifier }}{% endif %}{% if inverse %} icon-button--inverse{% endif %}{% if hidden %} hidden{% endif %}" {% if modifier and name %}data-{{ name }}-{{ modifier }}{% endif %}{% if data %} {{ data }}{% endif %}{% if aria %} {{ aria }}{% endif %}>
2+
<span class="u-sr-only">
3+
{% if modifier %}{{ modifier }}{% endif %}
4+
</span>
5+
{% if modifier == 'next' %}
6+
<span class="rotate">{% include "patterns/atoms/icons/icon.html" with name="chevron" %}</span>
7+
{% elif modifier == 'previous' %}
8+
<span class="rotate rotate--left">{% include "patterns/atoms/icons/icon.html" with name="chevron" %}</span>
9+
{% elif modifier == 'down' %}
10+
<span>{% include "patterns/atoms/icons/icon.html" with name="chevron" %}</span>
11+
{% elif modifier %}
12+
<span>{% include "patterns/atoms/icons/icon.html" with name=modifier %}</span>
13+
{% endif %}
14+
</button>

tbx/project_styleguide/templates/patterns/molecules/streamfield/blocks/call_to_action.html

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,38 @@ <h2 class="heading heading--two-b call-to-action__heading">{{ value.text }}</h2>
1111
{% endif %}
1212
</div>
1313
{% if value.button_text and value.button_link %}
14-
<a href="{{ value.get_button_link }}" class="call-to-action__button button">
15-
{{ value.button_text }}
16-
{% if value.get_button_link_block.block_type == "document_link" %}
17-
({{ value.get_button_file_size|filesizeformat }})
18-
{% endif %}
19-
</a>
14+
{% if value.get_button_link_block.block_type == "modal_iframe" %}
15+
<button class="call-to-action__button button" data-micromodal-trigger="iframe-embed-modal">{{ value.button_text }}</button>
16+
{% else %}
17+
<a href="{{ value.get_button_link }}" class="call-to-action__button button">
18+
{{ value.button_text }}
19+
{% if value.get_button_link_block.block_type == "document_link" %}
20+
({{ value.get_button_file_size|filesizeformat }})
21+
{% endif %}
22+
</a>
23+
{% endif %}
2024
{% endif %}
2125
</div>
2226
</div>
27+
28+
<!-- Modal content -->
29+
<div class="modal" id="iframe-embed-modal" aria-hidden="true">
30+
<div class="modal__overlay" tabindex="-1" data-micromodal-close></div>
31+
<div class="modal__container" role="dialog" aria-modal="true" aria-labelledby="modal-title" >
32+
<header class="modal__header">
33+
<h2 class="modal__heading heading heading--two" id="modal-title">Service Enquiry</h2>
34+
<div class="modal__close">
35+
{% include "patterns/atoms/icon_buttons/icon_button.html" with modifier="close" data="data-micromodal-close" aria='aria-label="Close modal"' %}
36+
</div>
37+
</header>
38+
<main class="modal__content" id="filters-content">
39+
<iframe
40+
src="{{ cta.value.get_button_link }}"
41+
width="100%"
42+
height="650px"
43+
frameborder="0"
44+
title="Modal Webform">
45+
</iframe>
46+
</main>
47+
</div>
48+
</div>

tbx/project_styleguide/templates/patterns/molecules/streamfield/blocks/contact_call_to_action.html

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,40 @@ <h2 class="heading heading--two-b contact-cta__heading">{{ cta.value.text }}</h2
3030

3131
{# CTA button #}
3232
{% if cta.value.button_text and cta.value.button_link %}
33-
<a href="{{ cta.value.get_button_link }}" class="contact-cta__button button">
34-
{{ cta.value.button_text }}
35-
{% if cta.value.get_button_link_block.block_type == "document_link" %}
36-
({{ cta.value.get_button_file_size|filesizeformat }})
37-
{% endif %}
38-
</a>
33+
{% if cta.value.get_button_link_block.block_type == "modal_iframe" %}
34+
<button class="contact-cta__button button" data-micromodal-trigger="iframe-embed-modal">{{ cta.value.button_text }}</button>
35+
{% else %}
36+
<a href="{{ cta.value.get_button_link }}" class="contact-cta__button button">
37+
{{ cta.value.button_text }}
38+
{% if cta.value.get_button_link_block.block_type == "document_link" %}
39+
({{ cta.value.get_button_file_size|filesizeformat }})
40+
{% endif %}
41+
</a>
42+
{% endif %}
43+
{% endif %}
44+
</div>
45+
{% if cta.value.get_button_link_block.block_type == "modal_iframe" %}
46+
<!-- Modal content -->
47+
<div class="modal" id="iframe-embed-modal" aria-hidden="true">
48+
<div class="modal__overlay" tabindex="-1" data-micromodal-close></div>
49+
<div class="modal__container" role="dialog" aria-modal="true" aria-labelledby="modal-title" >
50+
<header class="modal__header">
51+
<h2 class="modal__heading heading heading--two" id="modal-title">Service Enquiry</h2>
52+
<div class="modal__close">
53+
{% include "patterns/atoms/icon_buttons/icon_button.html" with modifier="close" data="data-micromodal-close" aria='aria-label="Close modal"' %}
54+
</div>
55+
</header>
56+
<main class="modal__content" id="filters-content">
57+
<iframe
58+
src="{{ cta.value.get_button_link }}"
59+
width="100%"
60+
height="650px"
61+
frameborder="0"
62+
title="Modal Webform">
63+
</iframe>
64+
</main>
65+
</div>
66+
</div>
3967
{% endif %}
4068
{% endwith %}
4169
</div>
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{% load wagtailcore_tags %}
2+
{# call_to_action is a required field (streamblock) in the block definition #}
3+
4+
<!-- Sticky block -->
5+
<div class="call-to-action__sticky">
6+
<div class="call-to-action__inner">
7+
{% if value.get_button_link_block.block_type == "modal_iframe" %}
8+
<button class="call-to-action__stickybutton button" data-micromodal-trigger="iframe-embed-modal">
9+
<span class="call-to-action__stickyheading">{{ value.sticky_text }}</span>
10+
{% if value.sticky_subtext %}
11+
<br><span class="call-to-action__stickysubtext">{{ value.sticky_subtext }}</span>
12+
{% endif %}
13+
</button>
14+
{% else %}
15+
<a href="{{ value.get_button_link }}" class="call-to-action__button button">
16+
<span class="call-to-action__stickyheading">{{ value.sticky_text }}</span>
17+
{% if value.get_button_link_block.block_type == "document_link" %}
18+
({{ value.get_button_file_size|filesizeformat }})
19+
{% endif %}
20+
{% if value.sticky_subtext %}
21+
<br><span class="call-to-action__stickysubtext">{{ value.sticky_subtext }}</span>
22+
{% endif %}
23+
</a>
24+
{% endif %}
25+
</div>
26+
</div>
27+
28+
<!-- Modal content -->
29+
<div class="modal" id="iframe-embed-modal" aria-hidden="true">
30+
<div class="modal__overlay" tabindex="-1" data-micromodal-close></div>
31+
<div class="modal__container" role="dialog" aria-modal="true" aria-labelledby="modal-title" >
32+
<header class="modal__header">
33+
<h2 class="modal__heading heading heading--two" id="modal-title">Service Enquiry</h2>
34+
<div class="modal__close">
35+
{% include "patterns/atoms/icon_buttons/icon_button.html" with modifier="close" data="data-micromodal-close" aria='aria-label="Close modal"' %}
36+
</div>
37+
</header>
38+
<main class="modal__content" id="filters-content">
39+
<iframe
40+
src="{{ value.get_button_link }}"
41+
width="100%"
42+
height="650px"
43+
frameborder="0"
44+
title="Modal Webform">
45+
</iframe>
46+
</main>
47+
</div>
48+
</div>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
context:
2+
value:
3+
sticky_text: Get in touch
4+
sticky_subtext: learn about our journey
5+
button_link:
6+
- modal_iframe:
7+
url: 'https://example.com'
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import MicroModal from 'micromodal'; // es6 module
2+
3+
// Assumes a strcuture as follows
4+
// <div class="modal" id="filters" aria-hidden="true">
5+
// <div class="modal__overlay" tabindex="-1" data-micromodal-close></div>
6+
// <div class="modal__container" role="dialog" aria-modal="true" aria-labelledby="modal-title" >
7+
// <header class="modal__header">
8+
// <h2 class="modal__heading heading heading--two" id="modal-title">Title<h2>
9+
// <div class="modal__close">
10+
// {% include "atoms/icon_buttons/icon_button.html" with modifier="close" data="data-micromodal-close" aria='aria-label="Close modal"' %}
11+
// </div>
12+
// </header>
13+
// <main class="modal__content" id="filters-content">
14+
// Content
15+
// </main>
16+
// <footer class="modal__footer">
17+
// <button class="modal__btn" data-micromodal-close>Close</button>
18+
// </footer>
19+
// </div>
20+
// </div>
21+
22+
class Modal {
23+
static selector() {
24+
return '[data-micromodal-trigger]';
25+
}
26+
27+
constructor() {
28+
if (typeof MicroModal !== 'undefined') {
29+
MicroModal.init({
30+
openTrigger: 'data-micromodal-trigger',
31+
disableScroll: true,
32+
});
33+
}
34+
35+
Modal.bindEvents();
36+
}
37+
38+
static bindEvents() {
39+
// Listen for clicks on the document instead of using micromodel default, which doesn't work with htmx
40+
document.body.addEventListener('click', Modal.handleEvent);
41+
document.body.addEventListener('touchstart', Modal.handleEvent);
42+
document.body.addEventListener('keydown', Modal.handleKeyDown);
43+
}
44+
45+
static handleEvent(event) {
46+
const trigger = event.target.closest('[data-micromodal-trigger]');
47+
if (trigger) {
48+
event.preventDefault();
49+
event.stopPropagation(); // Stop the event from bubbling up
50+
51+
// Get the modal ID and open the correct modal
52+
const modalId = trigger.getAttribute('data-micromodal-trigger');
53+
if (modalId && typeof MicroModal !== 'undefined') {
54+
MicroModal.show(modalId);
55+
}
56+
}
57+
58+
// Close modal when clicking on close buttons
59+
const closeButton = event.target.closest(
60+
'[data-micromodal-close], [data-listing-submit]',
61+
);
62+
if (closeButton) {
63+
const modal = closeButton.closest('.modal');
64+
if (modal) {
65+
MicroModal.close(modal.id); // Close the modal
66+
document.body.style.overflow = ''; // Remove overflow hidden from body
67+
}
68+
}
69+
}
70+
71+
// Prevent Enter from closing modal unless on button
72+
static handleKeyDown(event) {
73+
if (event.key === 'Enter') {
74+
const modal = event.target.closest('.modal');
75+
if (modal) {
76+
// Allow Enter on buttons and prevent it on everything else
77+
if (event.target.tagName !== 'BUTTON') {
78+
event.preventDefault();
79+
event.stopPropagation();
80+
}
81+
}
82+
}
83+
}
84+
}
85+
86+
export default Modal;

0 commit comments

Comments
 (0)