Skip to content

Commit 913bf7c

Browse files
committed
refactor: Move all templates directly into web components
Signed-off-by: Felicitas Pojtinger <felicitas@pojtinger.com>
1 parent 39d514a commit 913bf7c

7 files changed

Lines changed: 188 additions & 244 deletions

File tree

assets/js/events.js

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,4 @@ export const makeCoverImg = (coverUrl, alt) => {
3838
img.style.cssText =
3939
"width: 4rem; height: 4rem; object-fit: cover; border-radius: var(--pf-t--global--border--radius--medium);";
4040
return img;
41-
};
42-
43-
export const makeCell = (className, ...children) => {
44-
const td = document.createElement("td");
45-
td.className = className;
46-
td.setAttribute("role", "cell");
47-
td.style.verticalAlign = "middle";
48-
for (const child of children) {
49-
if (child) td.append(child);
50-
}
51-
return td;
52-
};
41+
};

assets/js/icons.js

Lines changed: 29 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,42 @@
1-
const inButton = (el) => el.closest(".pf-v6-c-button__icon") !== null;
2-
const renderFaIcon = (el, faClasses) => {
3-
const i = `<i class="${faClasses}" aria-hidden="true"></i>`;
4-
if (inButton(el)) {
5-
el.innerHTML = i;
6-
} else {
7-
el.style.display = "inline";
8-
el.style.whiteSpace = "nowrap";
9-
el.innerHTML = "\u2060" + i;
10-
el.querySelector("i").classList.add("pf-v6-u-ml-xs");
1+
class FaIcon extends HTMLElement {
2+
static faClass = "";
3+
4+
connectedCallback() {
5+
const inButton = this.closest(".pf-v6-c-button__icon") !== null;
6+
const faClass = this.constructor.faClass || this.dataset.icon;
7+
const icon = document.createElement("i");
8+
icon.className = faClass;
9+
icon.setAttribute("aria-hidden", "true");
10+
11+
if (inButton) {
12+
this.replaceChildren(icon);
13+
} else {
14+
this.style.display = "inline";
15+
this.style.whiteSpace = "nowrap";
16+
icon.classList.add("pf-v6-u-ml-xs");
17+
this.replaceChildren("\u2060", icon);
18+
}
1119
}
12-
};
13-
const brandIcons = {
20+
}
21+
22+
const icons = {
1423
"icon-discourse": "fa-brands fa-discourse",
1524
"icon-signal": "fa-brands fa-signal-messenger",
1625
"icon-mastodon": "fa-brands fa-mastodon",
1726
"icon-bluesky": "fa-brands fa-bluesky",
1827
"icon-linkedin": "fa-brands fa-linkedin",
1928
"icon-paypal": "fa-brands fa-paypal",
29+
"icon-external": "fa-solid fa-arrow-up-right-from-square",
30+
"icon-email": "fa-solid fa-envelope",
2031
};
21-
for (const [tag, cls] of Object.entries(brandIcons)) {
32+
33+
for (const [tag, cls] of Object.entries(icons)) {
2234
customElements.define(
2335
tag,
24-
class extends HTMLElement {
25-
connectedCallback() {
26-
renderFaIcon(this, cls);
27-
}
36+
class extends FaIcon {
37+
static faClass = cls;
2838
},
2939
);
3040
}
31-
customElements.define(
32-
"icon-external",
33-
class extends HTMLElement {
34-
connectedCallback() {
35-
renderFaIcon(this, "fa-solid fa-arrow-up-right-from-square");
36-
}
37-
},
38-
);
39-
customElements.define(
40-
"icon-email",
41-
class extends HTMLElement {
42-
connectedCallback() {
43-
renderFaIcon(this, "fa-solid fa-envelope");
44-
}
45-
},
46-
);
47-
customElements.define(
48-
"icon-custom",
49-
class extends HTMLElement {
50-
connectedCallback() {
51-
renderFaIcon(this, this.dataset.icon);
52-
}
53-
},
54-
);
41+
42+
customElements.define("icon-custom", FaIcon);

assets/js/luma-next-event.js

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,44 @@
11
import { formatEvent } from "./events.js";
22

3-
const eventTemplate = document.getElementById("next-event-template");
3+
const template = document.createElement("template");
4+
template.innerHTML = `
5+
<div class="pf-v6-c-card pf-m-compact pf-m-flat">
6+
<div class="pf-v6-c-card__header">
7+
<div class="pf-v6-c-card__header-main">
8+
<div class="pf-v6-l-flex pf-m-gap-lg pf-m-align-items-center pf-m-nowrap">
9+
<div class="pf-v6-l-flex pf-m-gap-lg pf-m-align-items-center pf-m-justify-content-center">
10+
<img data-slot="cover" alt=""
11+
style="width: 4rem; height: 4rem; object-fit: cover;
12+
border-radius: var(--pf-t--global--border--radius--medium); flex-shrink: 0;" />
13+
<div class="pf-v6-l-flex pf-m-column pf-m-align-items-center pf-m-gap-xs">
14+
<span class="pf-v6-c-label pf-m-green pf-m-outline">
15+
<span class="pf-v6-c-label__content">
16+
<span class="pf-v6-c-label__text" data-slot="date"></span>
17+
</span>
18+
</span>
19+
<span class="pf-v6-u-font-size-xs" data-slot="relative"></span>
20+
</div>
21+
</div>
22+
<div class="pf-v6-l-flex pf-m-column pf-m-gap-sm">
23+
<div class="pf-v6-c-content">
24+
<h4 data-slot="name"></h4>
25+
<p><small data-slot="detail"></small></p>
26+
</div>
27+
<a data-slot="rsvp" target="_blank" rel="noopener"
28+
class="pf-v6-c-button pf-m-link pf-m-inline">
29+
<span class="pf-v6-c-button__text">RSVP on Luma</span>
30+
<span class="pf-v6-c-button__icon pf-m-end"><icon-external></icon-external></span>
31+
</a>
32+
</div>
33+
</div>
34+
</div>
35+
</div>
36+
</div>`;
437

538
const renderEventCard = (evt) => {
639
const { name, date, time, relative, lumaUrl, location, coverUrl } =
740
formatEvent(evt);
8-
const clone = eventTemplate.content.cloneNode(true);
41+
const clone = template.content.cloneNode(true);
942
const $ = (s) => clone.querySelector(`[data-slot="${s}"]`);
1043
const cover = $("cover");
1144
if (coverUrl) {

assets/js/luma-upcoming-events.js

Lines changed: 38 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,49 @@
1-
import { formatEvent, makeCoverImg, makeCell } from "./events.js";
1+
import { formatEvent, makeCoverImg } from "./events.js";
2+
3+
const rowTemplate = document.createElement("template");
4+
rowTemplate.innerHTML = `
5+
<tr class="pf-v6-c-table__tr" role="row">
6+
<td class="pf-v6-c-table__td pf-v6-u-display-none pf-v6-u-display-table-cell-on-md" role="cell" style="vertical-align: middle;" data-slot="cover-desktop"></td>
7+
<td class="pf-v6-c-table__td" role="cell" style="vertical-align: middle;">
8+
<div class="pf-v6-l-flex pf-m-gap-md pf-m-align-items-center">
9+
<span class="pf-v6-u-display-inline-block pf-v6-u-display-none-on-md" data-slot="cover-mobile"></span>
10+
<div>
11+
<div class="pf-v6-u-font-weight-bold pf-v6-u-display-block pf-v6-u-display-none-on-md" data-slot="name-mobile"></div>
12+
<div><span data-slot="date"></span> <span class="pf-v6-u-font-size-xs" data-slot="relative"></span></div>
13+
<small class="pf-v6-u-text-color-subtle" data-slot="time"></small>
14+
</div>
15+
</div>
16+
</td>
17+
<td class="pf-v6-c-table__td pf-v6-u-display-none pf-v6-u-display-table-cell-on-md" role="cell" style="vertical-align: middle;" data-slot="name-desktop"></td>
18+
<td class="pf-v6-c-table__td" role="cell" style="vertical-align: middle;" data-slot="location"></td>
19+
<td class="pf-v6-c-table__td" role="cell" style="vertical-align: middle;">
20+
<a data-slot="rsvp" target="_blank" rel="noopener" class="pf-v6-c-button pf-m-link pf-m-inline pf-m-small">
21+
RSVP<span class="pf-v6-c-button__icon pf-m-end"><icon-external></icon-external></span>
22+
</a>
23+
</td>
24+
</tr>`;
225

326
const renderEventRow = (evt) => {
427
const { name, date, time, relative, lumaUrl, location, coverUrl } =
528
formatEvent(evt);
29+
const clone = rowTemplate.content.cloneNode(true);
30+
const $ = (s) => clone.querySelector(`[data-slot="${s}"]`);
631

7-
const tr = document.createElement("tr");
8-
tr.className = "pf-v6-c-table__tr";
9-
tr.setAttribute("role", "row");
32+
const desktopCover = makeCoverImg(coverUrl, name);
33+
if (desktopCover) $("cover-desktop").append(desktopCover);
1034

11-
tr.append(
12-
makeCell(
13-
"pf-v6-c-table__td pf-v6-u-display-none pf-v6-u-display-table-cell-on-md",
14-
makeCoverImg(coverUrl, name),
15-
),
16-
);
35+
const mobileCover = makeCoverImg(coverUrl, name);
36+
if (mobileCover) $("cover-mobile").append(mobileCover);
1737

18-
const mobileCover = document.createElement("span");
19-
mobileCover.className =
20-
"pf-v6-u-display-inline-block pf-v6-u-display-none-on-md";
21-
const mobileCoverImg = makeCoverImg(coverUrl, name);
22-
if (mobileCoverImg) mobileCover.append(mobileCoverImg);
38+
$("name-mobile").textContent = name;
39+
$("date").textContent = date;
40+
$("relative").textContent = relative;
41+
$("time").textContent = time;
42+
$("name-desktop").textContent = name;
43+
$("location").textContent = location;
44+
$("rsvp").href = lumaUrl;
2345

24-
const mobileName = document.createElement("div");
25-
mobileName.className =
26-
"pf-v6-u-font-weight-bold pf-v6-u-display-block pf-v6-u-display-none-on-md";
27-
mobileName.textContent = name;
28-
29-
const relativeSpan = document.createElement("span");
30-
relativeSpan.className = "pf-v6-u-font-size-xs";
31-
relativeSpan.textContent = relative;
32-
33-
const dateLine = document.createElement("div");
34-
dateLine.append(`${date} `, relativeSpan);
35-
36-
const timeLine = document.createElement("small");
37-
timeLine.className = "pf-v6-u-text-color-subtle";
38-
timeLine.textContent = time;
39-
40-
const textBlock = document.createElement("div");
41-
textBlock.append(mobileName, dateLine, timeLine);
42-
43-
const flex = document.createElement("div");
44-
flex.className = "pf-v6-l-flex pf-m-gap-md pf-m-align-items-center";
45-
flex.append(mobileCover, textBlock);
46-
47-
tr.append(makeCell("pf-v6-c-table__td", flex));
48-
49-
const nameCell = makeCell(
50-
"pf-v6-c-table__td pf-v6-u-display-none pf-v6-u-display-table-cell-on-md",
51-
);
52-
nameCell.textContent = name;
53-
tr.append(nameCell);
54-
55-
const locCell = makeCell("pf-v6-c-table__td");
56-
locCell.textContent = location;
57-
tr.append(locCell);
58-
59-
const rsvpLink = document.createElement("a");
60-
rsvpLink.href = lumaUrl;
61-
rsvpLink.target = "_blank";
62-
rsvpLink.rel = "noopener";
63-
rsvpLink.className = "pf-v6-c-button pf-m-link pf-m-inline pf-m-small";
64-
rsvpLink.append("RSVP", document.createElement("icon-external"));
65-
tr.append(makeCell("pf-v6-c-table__td", rsvpLink));
66-
67-
return tr;
46+
return clone;
6847
};
6948

7049
customElements.define(

0 commit comments

Comments
 (0)