- {% for block in self.session_items %}
- {% with session_item=block count=self.session_items|length %}
- {% image session_item.image fill-350x197 as img %}
-
-
-

-
-
-
{{ session_item.title }}
-
Author Subheading: {{ session_item.author_subheading }}
-
Body: {{ session_item.body }}
-
Video URL: {{ session_item.video.url }}
-
Link: {{ session_item.link.0.value.link_url }}
-
-
-
+
+ {# Additional required wrapper #}
+
+
+ {# Slides #}
+ {% for item in self.session_items %}
+ {% image item.image fill-250x140 as img %}
+
+ {% include 'fragments/session_card.html' with title=item.title url=item.video.url image=img.url text=item.body animated_thumbnail=item.video.url %}
- {% endwith %}
- {% endfor %}
-
-
-
-
Button Label: {{ value.button.0.value.label }}
-
Button Link URL: {{ value.button.0.value.link_url }}
+ {% endfor %}
+
+
+ {# Pagination #}
+
+
-{% endblock %}
+
diff --git a/package.json b/package.json
index fad0147b3d1..f762f9c9a2e 100644
--- a/package.json
+++ b/package.json
@@ -95,7 +95,7 @@
"react-ga": "3.3.0",
"sass": "^1.38.2",
"shx": "^0.3.3",
- "swiper": "^6.7.5",
+ "swiper": "^6.8.4",
"tailwindcss": "^2.2.9",
"uuid": "^8.3.2",
"whatwg-fetch": "^3.6.2"
diff --git a/source/images/mozfest/play-triangle.svg b/source/images/mozfest/play-triangle.svg
new file mode 100644
index 00000000000..437f0c0cb31
--- /dev/null
+++ b/source/images/mozfest/play-triangle.svg
@@ -0,0 +1,5 @@
+
diff --git a/source/js/components/carousel/carousel.js b/source/js/components/carousel/carousel.js
new file mode 100644
index 00000000000..a59f42a6780
--- /dev/null
+++ b/source/js/components/carousel/carousel.js
@@ -0,0 +1,52 @@
+import Swiper, {
+ A11y,
+ Autoplay,
+ Pagination,
+ Navigation,
+ Keyboard,
+} from "swiper";
+
+Swiper.use([A11y, Autoplay, Pagination, Navigation, Keyboard]);
+
+class Carousel {
+ constructor(node) {
+ this.node = node;
+ this.swiper = new Swiper(this.node, {
+ spaceBetween: 20,
+ watchOverflow: true,
+ centeredSlides: false,
+ simulateTouch: true,
+ slidesPerView: 1,
+ autoHeight: true,
+ keyboard: {
+ enabled: true,
+ },
+ pagination: {
+ el: ".swiper-pagination",
+ clickable: true,
+ },
+ navigation: {
+ nextEl: ".swiper-button-next",
+ prevEl: ".swiper-button-prev",
+ },
+ // Responsive breakpoints
+ breakpoints: {
+ 992: {
+ slidesPerView: 2,
+ spaceBetween: 30,
+ },
+ },
+ });
+ this.slideTotal = this.node.dataset.slidetotal;
+ }
+}
+
+const MozfestCarousels = {
+ init: function () {
+ document
+ .querySelectorAll(`[data-carousel]`)
+ .forEach((e) => new Carousel(e));
+ },
+};
+
+export default MozfestCarousels;
diff --git a/source/js/main.js b/source/js/main.js
index 9bf2ec01e52..d371234152c 100644
--- a/source/js/main.js
+++ b/source/js/main.js
@@ -16,6 +16,7 @@ import {
import primaryNav from "./primary-nav.js";
import EmbedTypeform from "./embed-typeform.js";
import Dropdowns from "./dropdowns.js";
+import MozfestCarousels from "./components/carousel/carousel.js";
import initializeSentry from "./common/sentry-config.js";
import YouTubeRegretsTunnel from "./foundation/pages/youtube-regrets/intro-tunnel";
import RegretsReporterTimeline from "./foundation/pages/youtube-regrets/regrets-reporter/timeline";
@@ -138,6 +139,11 @@ let main = {
if (document.querySelector("#view-dear-internet")) {
bindDearInternetEventHandlers();
}
+
+ // Mozfest pages
+ if (document.querySelector(`.mozfest`)) {
+ MozfestCarousels.init();
+ }
},
};
diff --git a/source/sass/mozfest.scss b/source/sass/mozfest.scss
index c767574e55a..4882ad86303 100644
--- a/source/sass/mozfest.scss
+++ b/source/sass/mozfest.scss
@@ -1,6 +1,11 @@
// MozFest-specific styling
// https://www.mozillafestival.org
+// Carousel
+@import "../../node_modules/swiper/swiper-vars.scss";
+@import "../../node_modules/swiper/swiper.scss";
+@import "../../node_modules/swiper/components/pagination/pagination.scss";
+
body.mozfest {
.primary-nav-container {
// The following overrides are to make sure
@@ -174,4 +179,43 @@ body.mozfest {
}
}
}
+
+ .swiper-button-next,
+ .swiper-button-prev {
+ @apply tw-border-2 tw-text-blue tw-flex tw-flex-col tw-justify-center tw-items-center tw-w-[40px] tw-h-[40px] tw-transition;
+
+ &.swiper-button-disabled {
+ @apply tw-border-gray-20;
+ }
+
+ &::after {
+ content: "";
+ }
+
+ &:hover {
+ @apply tw-opacity-75;
+ }
+ }
+
+ .swiper-button-icon {
+ @apply tw-text-blue tw-w-4 tw-h-4;
+ }
+
+ .swiper-button-disabled {
+ .swiper-button-icon {
+ @apply tw-text-gray-20;
+ }
+ }
+
+ .swiper-button-prev {
+ @apply tw-mr-5;
+ }
+
+ .swiper-pagination-bullet {
+ @apply tw-w-3 tw-h-3;
+ }
+
+ .swiper-pagination-bullet-active {
+ @apply tw-bg-festival-blue-100;
+ }
}
diff --git a/tailwind.config.js b/tailwind.config.js
index 80ab675f422..9717258ae84 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -104,7 +104,10 @@ module.exports = {
purple: "#a66efd",
},
festival: {
- blue: "#0e11bf",
+ blue: {
+ DEFAULT: "#0e11bf",
+ 100: "#4C56EC",
+ },
purple: "#8f14fb",
},
"dear-internet": {