Skip to content

Commit 109f899

Browse files
authored
Merge pull request #12 from aemsites/footer
feat: footer
2 parents 7b7b673 + 95d293c commit 109f899

2 files changed

Lines changed: 258 additions & 19 deletions

File tree

blocks/footer/footer.css

Lines changed: 193 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,207 @@
11
footer {
2-
background-color: var(--rbc-cool-white);
2+
--footer-columns-bg: var(--rbc-blue);
3+
--footer-bar-bg: #595959;
4+
35
font-size: var(--body-font-size-xs);
46
}
57

6-
footer .footer > div {
8+
footer .footer-columns-band {
9+
background-color: var(--footer-columns-bg);
10+
color: var(--rbc-white);
11+
}
12+
13+
footer .footer-bar-band {
14+
background-color: var(--footer-bar-bg);
15+
color: var(--rbc-white);
16+
}
17+
18+
footer .footer-inner {
719
margin: auto;
820
max-width: 1200px;
9-
padding: var(--space-2xl) var(--space-l) var(--space-l);
21+
padding: var(--space-xl) var(--space-l);
22+
}
23+
24+
footer .footer-columns-band .footer-inner {
25+
padding: var(--space-2xl) var(--space-l) var(--space-xl);
26+
}
27+
28+
footer .footer-columns {
29+
display: grid;
30+
grid-template-columns: 1fr;
31+
gap: var(--space-xl);
32+
}
33+
34+
footer .footer-col h2,
35+
footer .footer-col h3 {
36+
margin: 0 0 var(--space-m);
37+
color: var(--rbc-white);
38+
font-size: var(--body-font-size-l);
39+
font-weight: 500;
40+
font-family: var(--body-font-family);
1041
}
1142

12-
footer .footer p {
43+
footer .footer-col ul {
1344
margin: 0;
45+
padding: 0;
46+
list-style: none;
47+
}
48+
49+
footer .footer-col li {
50+
margin-bottom: var(--space-m);
51+
}
52+
53+
footer .footer-col a {
54+
display: grid;
55+
grid-template-columns: 12px 1fr;
56+
gap: var(--space-xs);
57+
align-items: start;
58+
color: var(--rbc-white);
59+
text-decoration: none;
60+
font-size: var(--body-font-size-s);
61+
}
62+
63+
footer .footer-col a::before {
64+
content: "";
65+
width: 14px;
66+
height: 14px;
67+
padding-top: 4px;
68+
background-color: currentcolor;
69+
mask: url('../../icons/chevron-down.svg') center / contain no-repeat;
70+
transform: rotate(-90deg);
71+
}
72+
73+
footer .footer-col a:hover,
74+
footer .footer-col a:focus-visible {
75+
text-decoration: underline;
76+
}
77+
78+
footer .footer-col p {
79+
margin: var(--space-m) 0 0;
80+
}
81+
82+
footer .footer-col .icon-cdic-sadc {
83+
width: 116px;
84+
height: 54px;
85+
}
86+
87+
footer .footer-bar {
88+
display: flex;
89+
flex-direction: column;
90+
align-items: center;
91+
gap: var(--space-m);
92+
text-align: center;
93+
}
94+
95+
footer .footer-bar-left,
96+
footer .footer-bar-right {
97+
display: flex;
98+
flex-direction: column;
99+
align-items: center;
100+
gap: var(--space-s);
101+
}
102+
103+
footer .footer-bar p {
104+
margin: 0;
105+
font-size: var(--body-font-size-s);
106+
}
107+
108+
footer .footer-legal {
109+
display: flex;
110+
flex-wrap: wrap;
111+
justify-content: center;
112+
gap: var(--space-2xs) var(--space-s);
113+
color: rgb(255 255 255 / 75%);
114+
}
115+
116+
footer .footer-bar .footer-legal a {
117+
color: rgb(255 255 255 / 75%);
118+
text-decoration: none;
119+
}
120+
121+
footer .footer-bar .footer-legal a:not(:last-child)::after {
122+
content: "|";
123+
margin-left: var(--space-s);
124+
color: rgb(255 255 255 / 40%);
125+
}
126+
127+
footer .footer-bar-right {
128+
width: 100%;
129+
padding-top: var(--space-l);
130+
border-top: 1px solid rgb(255 255 255 / 25%);
131+
}
132+
133+
footer .footer-social {
134+
display: flex;
135+
gap: var(--space-l);
136+
align-items: center;
137+
justify-content: center;
138+
}
139+
140+
footer .footer-social .icon {
141+
width: 22px;
142+
height: 22px;
143+
}
144+
145+
footer .footer-bar .footer-totop a {
146+
display: inline-flex;
147+
flex-direction: column;
148+
gap: var(--space-3xs);
149+
align-items: center;
150+
color: var(--rbc-white);
151+
text-decoration: none;
152+
}
153+
154+
footer .footer-totop .icon {
155+
width: 20px;
156+
height: 20px;
157+
}
158+
159+
footer .footer-bar .icon svg,
160+
footer .footer-bar .icon svg * {
161+
fill: var(--rbc-white);
162+
}
163+
164+
footer .footer-bar a:hover,
165+
footer .footer-bar a:focus-visible {
166+
text-decoration: underline;
14167
}
15168

16169
@media (width >= 768px) {
17-
footer .footer > div {
18-
padding: var(--space-2xl) var(--space-xl) var(--space-l);
170+
footer .footer-columns-band .footer-inner {
171+
padding: var(--space-2xl) var(--space-xl) var(--space-xl);
172+
}
173+
174+
footer .footer-columns {
175+
grid-template-columns: repeat(4, 1fr);
176+
}
177+
178+
footer .footer-bar {
179+
flex-direction: row;
180+
justify-content: space-between;
181+
align-items: center;
182+
text-align: left;
183+
}
184+
185+
footer .footer-bar-left,
186+
footer .footer-bar-right {
187+
align-items: flex-start;
188+
}
189+
190+
footer .footer-legal {
191+
justify-content: flex-start;
192+
}
193+
194+
footer .footer-bar-right {
195+
flex-direction: row;
196+
align-items: center;
197+
gap: var(--space-l);
198+
width: auto;
199+
padding-top: 0;
200+
border-top: 0;
201+
}
202+
203+
footer .footer-totop {
204+
padding-left: var(--space-l);
205+
border-left: 1px solid rgb(255 255 255 / 30%);
19206
}
20207
}

blocks/footer/footer.js

Lines changed: 65 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,72 @@
11
import { getMetadata } from '../../scripts/aem.js';
22
import { loadFragment } from '../fragment/fragment.js';
3+
import { createElement as el } from '../../utils/dom.js';
34

4-
/**
5-
* loads and decorates the footer
6-
* @param {Element} block The footer block element
7-
*/
8-
export default async function decorate(block) {
9-
// load footer as fragment
10-
const footerMeta = getMetadata('footer');
11-
const footerPath = footerMeta ? new URL(footerMeta, window.location).pathname : '/footer';
12-
const fragment = await loadFragment(footerPath);
5+
const BAR_BY_LANG = { 'fr-CA': '/fr/footer' };
6+
7+
function buildColumns(fragment) {
8+
const columns = el('div', { class: 'footer-columns' });
9+
fragment.querySelectorAll(':scope > .section').forEach((section) => {
10+
const content = section.querySelector(':scope > div') || section;
11+
if (!content.querySelector('h2, h3')) return;
12+
const col = el('div', { class: 'footer-col' });
13+
col.append(...content.children);
14+
columns.append(col);
15+
});
16+
return columns.children.length ? columns : null;
17+
}
1318

14-
// decorate footer DOM
19+
function buildBar(fragment) {
20+
const source = el('div');
21+
fragment.querySelectorAll(':scope > .section > div').forEach((group) => {
22+
source.append(...group.children);
23+
});
24+
25+
const left = el('div', { class: 'footer-bar-left' });
26+
const right = el('div', { class: 'footer-bar-right' });
27+
source.querySelectorAll('p').forEach((p) => {
28+
if (p.querySelector('a[href="#skip-nav"]')) {
29+
p.className = 'footer-totop';
30+
p.querySelector('a').addEventListener('click', (e) => {
31+
e.preventDefault();
32+
window.scrollTo({ top: 0, behavior: 'smooth' });
33+
});
34+
right.append(p);
35+
} else if (p.querySelector('.icon')) {
36+
p.className = 'footer-social';
37+
right.append(p);
38+
} else if (p.querySelector('a')) {
39+
p.className = 'footer-legal';
40+
left.append(p);
41+
} else {
42+
p.className = 'footer-copyright';
43+
p.textContent = p.textContent.replace(/(©\s*\d{4})-\d{4}/, `$1-${new Date().getFullYear()}`);
44+
left.append(p);
45+
}
46+
});
47+
48+
if (!left.children.length && !right.children.length) return null;
49+
return el('div', { class: 'footer-bar' }, [left, right]);
50+
}
51+
52+
function band(name, child) {
53+
const wrap = el('div', { class: name });
54+
wrap.append(el('div', { class: 'footer-inner' }, child));
55+
return wrap;
56+
}
57+
58+
export default async function decorate(block) {
1559
block.textContent = '';
16-
const footer = document.createElement('div');
17-
while (fragment.firstElementChild) footer.append(fragment.firstElementChild);
1860

19-
block.append(footer);
61+
const sectionMeta = getMetadata('footer');
62+
if (sectionMeta) {
63+
const fragment = await loadFragment(new URL(sectionMeta, window.location).pathname);
64+
const columns = fragment && buildColumns(fragment);
65+
if (columns) block.append(band('footer-columns-band', columns));
66+
}
67+
68+
const barPath = BAR_BY_LANG[getMetadata('lang') || document.documentElement.lang] || '/footer';
69+
const barFragment = await loadFragment(barPath);
70+
const bar = barFragment && buildBar(barFragment);
71+
if (bar) block.append(band('footer-bar-band', bar));
2072
}

0 commit comments

Comments
 (0)