Skip to content

Commit 7f07345

Browse files
committed
Add support for video in hero
1 parent 721c347 commit 7f07345

File tree

5 files changed

+174
-1
lines changed

5 files changed

+174
-1
lines changed

assets-src/js/main.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {navigation} from "./main/navigation";
77
import {responsiveTables} from "./main/responsive-tables";
88
import {flashes} from "./main/flashes";
99
import {headingAnchors} from './main/heading-anchors';
10+
import {videoHero} from './main/video-hero';
1011

1112
function domLoadedActions() {
1213
accountMenu();
@@ -17,6 +18,7 @@ function domLoadedActions() {
1718
responsiveTables();
1819
flashes();
1920
headingAnchors();
21+
videoHero();
2022

2123
/* Create a navDoubleLevel object and initiate double-level navigation for a <ul> with the correct data-component attribute */
2224
const navDoubleIntro = document.querySelector('ul[data-component="nav-double-intro"]');

assets-src/js/main/video-hero.js

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
let videoHero = function () {
2+
/* My refactored code */
3+
var heroVid = document.querySelector('[data-video="hero"]');
4+
var heroVidControl = document.querySelector('[data-video-control="hero"]');
5+
6+
if (heroVid && heroVidControl) {
7+
// Remove native controls and show custom button
8+
heroVid.removeAttribute("controls");
9+
heroVidControl.removeAttribute("hidden");
10+
11+
// Media query for reduced motion preference
12+
var motionQuery = window.matchMedia("(prefers-reduced-motion)");
13+
14+
// Helper to update button text
15+
function updateButtonState(isPlaying) {
16+
const label = isPlaying ? "Pause" : "Play";
17+
heroVidControl.querySelector("span").innerText = label;
18+
heroVidControl.classList.toggle("js-play-video", isPlaying);
19+
}
20+
21+
// Play video with error handling
22+
function playHeroVid() {
23+
heroVid.play().then(() => {
24+
updateButtonState(true);
25+
}).catch((error) => {
26+
console.warn("Video play failed:", error);
27+
updateButtonState(false);
28+
});
29+
}
30+
31+
// Pause video
32+
function pauseHeroVid() {
33+
heroVid.pause();
34+
updateButtonState(false);
35+
}
36+
37+
// Handle user motion preference
38+
function handleReduceMotionChanged() {
39+
if (motionQuery.matches) {
40+
pauseHeroVid();
41+
} else {
42+
playHeroVid();
43+
}
44+
}
45+
46+
// Attempt to autoplay
47+
var promise = heroVid.play();
48+
if (promise !== undefined) {
49+
promise
50+
.then(() => {
51+
updateButtonState(true);
52+
})
53+
.catch((error) => {
54+
console.warn("Autoplay was prevented:", error);
55+
updateButtonState(false);
56+
});
57+
}
58+
59+
// Media query listener
60+
motionQuery.addEventListener("change", handleReduceMotionChanged);
61+
handleReduceMotionChanged();
62+
63+
// Toggle video playback on control click
64+
document.addEventListener("click", function (event) {
65+
const button = event.target.closest('[data-video-control="hero"]');
66+
if (button) {
67+
if (heroVid.paused) {
68+
playHeroVid();
69+
} else {
70+
pauseHeroVid();
71+
}
72+
}
73+
});
74+
75+
// Unregister media query listener on page unload to prevent memory leaks
76+
window.addEventListener("beforeunload", () => {
77+
motionQuery.removeEventListener("change", handleReduceMotionChanged);
78+
});
79+
}
80+
}
81+
export {videoHero}

assets-src/styles/sass/60-advanced-components/_hero.scss

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,32 @@
66
h2 {
77
display: none;
88
}
9+
}
10+
11+
.js .hero video {
12+
display: block;
13+
margin-left: auto;
14+
margin-right: auto;
15+
}
16+
17+
@media screen and (min-width: 48em) {
18+
.js .hero video {
19+
max-width: 31.25rem;
20+
}
21+
}
22+
23+
[data-video-control="hero"] > * {
24+
pointer-events: none;
25+
}
26+
27+
[data-video-control="hero"] .pause-icon {
28+
display: none;
29+
}
30+
31+
[data-video-control="hero"].js-play-video .pause-icon {
32+
display: block;
33+
}
34+
35+
[data-video-control="hero"].js-play-video .play-icon {
36+
display: none;
937
}

design-system-templates/components/hero-home.html.twig

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
<h2>Illustration Hero</h2>
12
<div class="u-full-width hero">
23
<div class="l-center">
34
<div class="l-sidebar">
@@ -14,3 +15,44 @@
1415
</div>
1516
</div>
1617
</div>
18+
19+
<h2>Video Hero</h2>
20+
<div class="u-full-width hero">
21+
<div class="l-center">
22+
<div class="l-sidebar">
23+
<div>
24+
<div class="not-sidebar">
25+
<h1>We believe in one web for all</h1>
26+
<p class="lead">We develop
27+
<a href="path/to/page">standards and guidelines</a>
28+
to help everyone build a web based on the principles of
29+
<a href="path/to/page">accessibility</a>,
30+
<a href="path/to/page">internationalization</a>,
31+
<a href="path/top/page">privacy</a>
32+
and
33+
<a href="path/top/page">security</a>.</p>
34+
<a href="path/to/page" class="button button--alt">Find out more about W3C</a>
35+
</div>
36+
<div class="sidebar">
37+
<div class="l-frame l-frame--16-9">
38+
<video controls loop muted playsinline preload="metadata" data-video="hero">
39+
<source src="https://videos.pexels.com/video-files/1481903/1481903-hd_1920_1080_25fps.mp4" type="video/mp4">
40+
Sorry, your browser does not support embedded videos. This is an animation of the W3C logo morphing into a new design.
41+
</video>
42+
</div>
43+
<button class="button button--ghost" data-video-control="hero" hidden>
44+
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 47 47" height="45" width="45" aria-hidden="true" focusable="false">
45+
<defs/>
46+
<g fill="none" fill-rule="evenodd">
47+
<path fill="#1E3773" fill-rule="nonzero" stroke="#FFF" stroke-opacity=".8" stroke-width="3.75" d="M23.914 2.818a21.222 21.222 0 0114.937 6.108c3.813 3.762 6.173 8.956 6.173 14.695 0 4.204-1.286 8.201-3.555 11.55a21.036 21.036 0 01-9.48 7.668 21.405 21.405 0 01-12.222 1.183 21.205 21.205 0 01-10.82-5.706 20.685 20.685 0 01-5.77-10.65 20.489 20.489 0 011.206-12.008 20.855 20.855 0 017.78-9.335 21.335 21.335 0 0111.751-3.505z" opacity=".8"/>
48+
<path class="play-icon" fill="#FFF" fill-rule="nonzero" d="M20.065 31.18l12.748-7.57-12.748-7.548z"/>
49+
<path class="pause-icon" fill="#FFF" d="M26.232 16.062h5v15h-5zM16.232 16.062h5v15h-5z"/>
50+
</g>
51+
</svg>
52+
<span class="visuallyhidden">Play</span>
53+
</button>
54+
</div>
55+
</div>
56+
</div>
57+
</div>
58+
</div>

templates/components/styles/hero.html.twig

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,27 @@
1111
<p class="lead">{{ page.pageLead|raw }}</p>
1212
{% endblock %}
1313
</div>
14-
{% if page.heroIllustration is defined and page.heroIllustration %}
14+
{% if page.heroVideo is defined and page.heroVideo %}
15+
<div class="sidebar">
16+
<div class="l-frame l-frame--16-9">
17+
<video controls loop muted playsinline preload="metadata" data-video="hero">
18+
<source src="{{ page.heroVideo.url }}" type="video/mp4">
19+
Sorry, your browser does not support embedded videos. This is an animation of the W3C logo morphing into a new design.
20+
</video>
21+
</div>
22+
<button class="button button--ghost" data-video-control="hero" hidden>
23+
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 47 47" height="45" width="45" aria-hidden="true" focusable="false">
24+
<defs/>
25+
<g fill="none" fill-rule="evenodd">
26+
<path fill="#1E3773" fill-rule="nonzero" stroke="#FFF" stroke-opacity=".8" stroke-width="3.75" d="M23.914 2.818a21.222 21.222 0 0114.937 6.108c3.813 3.762 6.173 8.956 6.173 14.695 0 4.204-1.286 8.201-3.555 11.55a21.036 21.036 0 01-9.48 7.668 21.405 21.405 0 01-12.222 1.183 21.205 21.205 0 01-10.82-5.706 20.685 20.685 0 01-5.77-10.65 20.489 20.489 0 011.206-12.008 20.855 20.855 0 017.78-9.335 21.335 21.335 0 0111.751-3.505z" opacity=".8"/>
27+
<path class="play-icon" fill="#FFF" fill-rule="nonzero" d="M20.065 31.18l12.748-7.57-12.748-7.548z"/>
28+
<path class="pause-icon" fill="#FFF" d="M26.232 16.062h5v15h-5zM16.232 16.062h5v15h-5z"/>
29+
</g>
30+
</svg>
31+
<span class="visuallyhidden">Play</span>
32+
</button>
33+
</div>
34+
{% elseif page.heroIllustration is defined and page.heroIllustration %}
1535
<div class="sidebar">
1636
<img src="{{ page.heroIllustration.url }}" alt/>
1737
</div>

0 commit comments

Comments
 (0)