update components and partials
This commit is contained in:
parent
a71962675c
commit
5247213da7
28 changed files with 321 additions and 214 deletions
|
|
@ -1,24 +0,0 @@
|
|||
<!-- template element holding a button that needs to be injected when JavaScript is finally available. -->
|
||||
<!-- based on an article by Manuel Matuzovic, https://web.dev/website-navigation/ -->
|
||||
<!-- see also: https://kittygiraudel.com/2022/09/30/templating-in-html/ -->
|
||||
|
||||
<template id="burger-template">
|
||||
<button type="button" aria-expanded="false" aria-label="Menu" aria-controls="mainnav">
|
||||
<span>{{ meta.navigation.navLabel }}</span>
|
||||
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="1em"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M5 12h14" />
|
||||
<path d="M12 5v14" />
|
||||
</svg>
|
||||
</button>
|
||||
</template>
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
<li class="card">
|
||||
<div class="flow">
|
||||
{% if headingContext === "h2" %}
|
||||
<h2>
|
||||
<a href="{{ item.url | url }}">{{ item.data.title }}</a>
|
||||
</h2>
|
||||
{% else %}
|
||||
<h3>
|
||||
<a href="{{ item.url | url }}">{{ item.data.title }}</a>
|
||||
</h3>
|
||||
{% endif %}
|
||||
<div class="cluster text-step-min-1">
|
||||
{% set definedDate = item.date %}
|
||||
{% include "components/date.njk" %}
|
||||
{%
|
||||
if
|
||||
activateTags and item.data.tags.length > 1
|
||||
%}
|
||||
{% for tag in item.data.tags %}
|
||||
{% if tag != "posts" %}
|
||||
<span class="button post-tag"> {{ tag }} </span>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<p>{{ item.data.description }}</p>
|
||||
</div>
|
||||
</li>
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
<time datetime="{{ definedDate | toIsoString }}">
|
||||
{{ definedDate | formatDate('MMMM D, YYYY') }}
|
||||
</time>
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
<ul class="control | cluster" aria-label="{{ meta.details.aria }}">
|
||||
<button id="expandAll" class="button post-tag">{{ meta.details.expand }}</button>
|
||||
<button id="collapseAll" class="button post-tag">{{ meta.details.collapse }}</button>
|
||||
</ul>
|
||||
|
||||
{% for item in itemList %}
|
||||
<details id="{{ item.data.title | slugify }}">
|
||||
<summary>{{ item.data.title }}</summary>
|
||||
{{ item.templateContent | safe }}
|
||||
</details>
|
||||
{% endfor %}
|
||||
|
||||
<script>
|
||||
const expandAllButton = document.querySelector('#expandAll');
|
||||
const collapseAllButton = document.querySelector('#collapseAll');
|
||||
const details = document.querySelectorAll('details');
|
||||
|
||||
expandAllButton.addEventListener('click', () => {
|
||||
details.forEach(detail => (detail.open = true));
|
||||
});
|
||||
|
||||
collapseAllButton.addEventListener('click', () => {
|
||||
details.forEach(detail => (detail.open = false));
|
||||
});
|
||||
|
||||
details.forEach(detail => {
|
||||
detail.addEventListener('toggle', () => {
|
||||
const hash = detail.open ? `#${detail.id}` : '#';
|
||||
history.pushState(null, null, hash);
|
||||
});
|
||||
});
|
||||
|
||||
const id = window.location.hash.slice(1);
|
||||
const detail = document.getElementById(id);
|
||||
if (detail) detail.open = true;
|
||||
</script>
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
<div
|
||||
class="grid mt-l-xl"
|
||||
role="list"
|
||||
style="--grid-min-item-size: clamp(16rem, 50vw, 20rem)"
|
||||
>
|
||||
{% for item in gallery %}
|
||||
<dialog class="flow modal{{ loop.index }}">
|
||||
<button class="button" autofocus>Close</button>
|
||||
{% eleventyImage item.image, item.alt, item.caption %}
|
||||
</dialog>
|
||||
|
||||
<button data-index="{{ loop.index }}">
|
||||
{% eleventyImage item.image, item.alt %}
|
||||
</button>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const buttons = document.querySelectorAll('button[data-index]');
|
||||
const modals = document.querySelectorAll('dialog');
|
||||
const closeButtons = document.querySelectorAll('dialog button');
|
||||
|
||||
buttons.forEach((button, index) => {
|
||||
button.addEventListener('click', () => {
|
||||
modals[index].showModal();
|
||||
});
|
||||
});
|
||||
|
||||
closeButtons.forEach((button, index) => {
|
||||
button.addEventListener('click', () => {
|
||||
modals[index].close();
|
||||
});
|
||||
});
|
||||
|
||||
window.addEventListener('click', event => {
|
||||
modals.forEach(modal => {
|
||||
if (event.target === modal) {
|
||||
modal.close();
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
<div
|
||||
role="region"
|
||||
class="theme-switch | cluster mt-xs"
|
||||
style="--cluster-horizontal-alignment: center; --gutter: 0.5rem"
|
||||
aria-labelledby="theme-switcher-label"
|
||||
data-theme-switcher
|
||||
hidden
|
||||
>
|
||||
<h2 id="theme-switcher-label">{{ meta.themeSwitch.title }}</h2>
|
||||
<button class="button" id="light-theme-toggle" data-theme="light">
|
||||
<span>{{ meta.themeSwitch.light }}</span>
|
||||
</button>
|
||||
<button class="button" id="dark-theme-toggle" data-theme="dark">
|
||||
<span>{{ meta.themeSwitch.dark }}</span>
|
||||
</button>
|
||||
</div>
|
||||
13
src/_includes/head/css-inline.njk
Normal file
13
src/_includes/head/css-inline.njk
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
{%- if eleventy.env.runMode === "serve" %}
|
||||
<!-- External CSS for local dev (refresh without page reload) -->
|
||||
<link rel="stylesheet" href="{% getBundleFileUrl "css", "global" %}">
|
||||
{%- else %}
|
||||
<!-- Inlined CSS (fastest site performance in production) -->
|
||||
<style>{% getBundle "css", "global" %}</style>
|
||||
{%- endif %}
|
||||
|
||||
{% css "global" %}{% include "css/global.css" %}{% endcss %}
|
||||
|
||||
<!-- opt-in for inlined CSS -->
|
||||
<style>{% getBundle "css", "inline" %}</style>
|
||||
1
src/_includes/head/js-defer.njk
Normal file
1
src/_includes/head/js-defer.njk
Normal file
|
|
@ -0,0 +1 @@
|
|||
<script src="{% getBundleFileUrl "js", "defer" %}" type="module"></script>
|
||||
7
src/_includes/head/js-inline.njk
Normal file
7
src/_includes/head/js-inline.njk
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
<script>{% getBundle "js", "inline" %}</script>
|
||||
|
||||
{%- js "inline" %} <!-- inlined for all pages -->
|
||||
{% include "scripts/is-land.js" %}
|
||||
{% include "scripts/theme-toggle.js" %}
|
||||
{% endjs %}
|
||||
|
|
@ -1,18 +1,14 @@
|
|||
<base href="{{ page.url }}" />
|
||||
|
||||
<meta
|
||||
name="description"
|
||||
content="
|
||||
{% if discover.description %}
|
||||
{{ discover.description }}
|
||||
{% elif description %}
|
||||
{{ description }}
|
||||
{% else %}
|
||||
{{ meta.siteDescription }}
|
||||
{% endif %}
|
||||
"
|
||||
/>
|
||||
{% set metaDescription %}
|
||||
{%- if discover.description -%}
|
||||
{{- discover.description -}}
|
||||
{%- elif description -%}
|
||||
{{- description -}}
|
||||
{%- else -%}
|
||||
{{- meta.siteDescription -}}
|
||||
{%- endif -%}
|
||||
{% endset %}
|
||||
|
||||
<meta name="description" content="{{ metaDescription }}" />
|
||||
<meta name="theme-color" content="{{ meta.themeColor }}" />
|
||||
<!-- Search Engines -->
|
||||
<meta name="robots" content="index,follow" />
|
||||
|
|
@ -25,10 +21,8 @@
|
|||
<meta name="color-scheme" content="light dark" />
|
||||
<!-- activates page transitions -->
|
||||
<meta name="view-transition" content="same-origin" />
|
||||
|
||||
<!-- Helps prevent duplicate content issues -->
|
||||
<link rel="canonical" href="{{ meta.url }}{{ page.url }}" />
|
||||
|
||||
<!-- Links to information about the author(s) of the document -->
|
||||
<link rel="author" href="humans.txt" />
|
||||
|
||||
|
|
@ -50,7 +44,6 @@
|
|||
{{- meta.siteName -}}
|
||||
{%- endif -%}"
|
||||
/>
|
||||
|
||||
<meta
|
||||
property="og:image"
|
||||
content="{%- if layout == 'post' -%}
|
||||
|
|
@ -69,10 +62,7 @@
|
|||
/>
|
||||
<meta property="og:image:width" content="1200" />
|
||||
<meta property="og:image:height" content="630" />
|
||||
<meta
|
||||
property="og:description"
|
||||
content="{% if description %}{{ description }}{% else %}{{ meta.siteDescription }}{% endif %}"
|
||||
/>
|
||||
<meta property="og:description" content="{{ metaDescription }}" />
|
||||
<meta property="og:site_name" content="{{ meta.siteName }}" />
|
||||
<meta property="og:locale" content="{{ meta.locale }}" />
|
||||
<meta property="article:author" content="{{ meta.author.name }}" />
|
||||
25
src/_includes/head/preloads.njk
Normal file
25
src/_includes/head/preloads.njk
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<link
|
||||
rel="preload"
|
||||
href="/assets/fonts/redhat/red-hat-display-v7-latin-900.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossorigin
|
||||
/>
|
||||
|
||||
<link
|
||||
rel="preload"
|
||||
href="/assets/fonts/inclusive/inclusivesans-regular.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossorigin
|
||||
/>
|
||||
|
||||
<!-- preloads in page data -->
|
||||
{%- if preloads -%}
|
||||
<!-- prettier-ignore -->
|
||||
<link rel="preload"
|
||||
href="{{ preloads.href }}"
|
||||
as="{{ preloads.as }}"
|
||||
{% if preloads.type %}type={{ preloads.type }}{% endif %}{% if preloads.imagesrcset %}imagesrcset="{{ preloads.imagesrcset }}"{% endif %}
|
||||
{% if preloads.crossorigin %}crossorigin{% endif %} />
|
||||
{% endif %}
|
||||
5
src/_includes/head/schema.njk
Normal file
5
src/_includes/head/schema.njk
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<!-- inline base schema -->
|
||||
{% include "schemas/base-schema.njk" %}
|
||||
|
||||
<!-- inline blogpost schema -->
|
||||
{% if schema == 'blog' %}{%- include "schemas/blogpost-schema.njk" -%}{% endif %}
|
||||
1
src/_includes/partials/date.njk
Normal file
1
src/_includes/partials/date.njk
Normal file
|
|
@ -0,0 +1 @@
|
|||
<time datetime="{{ definedDate | toIsoString }}"> {{ definedDate | formatDate('MMMM D, YYYY') }} </time>
|
||||
20
src/_includes/partials/details.njk
Normal file
20
src/_includes/partials/details.njk
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<div class="details flow">
|
||||
<div class="control | cluster" aria-label="{{ meta.details.aria }}">
|
||||
<button id="expandAll" class="button post-tag">{{ meta.details.expand }}</button>
|
||||
<button id="collapseAll" class="button post-tag">{{ meta.details.collapse }}</button>
|
||||
</div>
|
||||
{%- for item in itemList | alphabetic -%}
|
||||
<details id="{{ item.data.title | slugify }}">
|
||||
<summary>{{ item.data.title }}</summary>
|
||||
{{- item.templateContent | safe -}}
|
||||
</details>
|
||||
{%- endfor -%}
|
||||
</div>
|
||||
|
||||
{% css "inline" %}
|
||||
{% include "css/details.css" %}
|
||||
{% endcss %}
|
||||
|
||||
{% js "defer" %}
|
||||
{% include "scripts/details.js" %}
|
||||
{% endjs %}
|
||||
|
|
@ -2,8 +2,7 @@
|
|||
<hr />
|
||||
<p class="text-step-min-1">
|
||||
{{ meta[page.lang].blog.githubEdit }}
|
||||
<a
|
||||
href="{{ pkg.repository.url | url | replace('.git', '/tree/main/') }}{{ page.inputPath }}"
|
||||
<a href="{{ pkg.repository.url | url | replace('.git', '/tree/main/') }}{{ page.inputPath }}"
|
||||
>{{ meta.viewRepo.infoText }}</a
|
||||
>.
|
||||
</p>
|
||||
|
|
@ -1,13 +1,10 @@
|
|||
<footer class="site-foot">
|
||||
<footer class="site-footer ">
|
||||
<div class="wrapper">
|
||||
<div class="site-foot__inner">
|
||||
<nav
|
||||
class="site-foot__inner text-step-0"
|
||||
aria-label="{{ meta.navigation.ariaBottom }}"
|
||||
>
|
||||
<div class="footer__meta | cluster">
|
||||
<nav class="footer__meta | cluster text-step-0" aria-label="{{ meta.navigation.ariaBottom }}">
|
||||
© {% year %}
|
||||
<a href="/" {% if page.url == "/" %}aria-current="page"{% endif %}
|
||||
>{{ meta.siteName }} <small>{{ pkg.version }}</small>
|
||||
><span class="font-display">{{ meta.siteName }}</span> <small>{{ pkg.version }}</small>
|
||||
</a>
|
||||
|
||||
{% for item in navigation.bottom %}
|
||||
|
|
@ -24,15 +21,11 @@
|
|||
{% endfor %}
|
||||
</nav>
|
||||
|
||||
<nav class="site-foot__inner" aria-label="{{ meta.navigation.ariaPlatforms }}">
|
||||
<nav class="footer__meta | cluster" aria-label="{{ meta.navigation.ariaPlatforms }}">
|
||||
<!-- gets the first item from the feed loop set in meta -->
|
||||
<a
|
||||
href="{{ meta.blog.feedLinks[0].url }}"
|
||||
rel="alternate"
|
||||
type="{{ meta.blog.feedLinks[0].type }}"
|
||||
>
|
||||
<a href="{{ meta.blog.feedLinks[0].url }}" rel="alternate" type="{{ meta.blog.feedLinks[0].type }}">
|
||||
<span class="visually-hidden">{{ meta.blog.feedLinks[0].title }}</span>
|
||||
<div aria-hidden="true">{% include 'svg/rss.svg' %}</div>
|
||||
{% svg "misc/rss" %}
|
||||
</a>
|
||||
|
||||
{% for key, value in personal.platforms %}
|
||||
|
|
@ -40,7 +33,7 @@
|
|||
<!-- regular platforms -->
|
||||
<a href="{{ value }}" rel="me">
|
||||
<span class="visually-hidden">{{ key | capitalize }}</span>
|
||||
<div aria-hidden="true">{% include 'svg/platform-' + key + '.svg' %}</div>
|
||||
{% svg 'platform/' + key %}
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
|
@ -48,13 +41,13 @@
|
|||
</div>
|
||||
|
||||
<!-- theme switch -->
|
||||
{% include 'components/theme-switch.njk' %}
|
||||
{% include 'partials/theme-switch.njk' %}
|
||||
|
||||
<div class="text-center mt-m-l">
|
||||
<a class="creator text-step-min-1" href="{{ meta.creator.website }}"
|
||||
>Made with <span>{% include 'svg/heart.svg' %}</span> by
|
||||
<aside class="creator">
|
||||
<a class="cluster" href="{{ meta.creator.website }}"
|
||||
>Made with <span class="visually-hidden">love</span> <span>{% svg "misc/heart" %}</span> by
|
||||
{{ meta.creator.name }}</a
|
||||
>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
</footer>
|
||||
|
|
|
|||
19
src/_includes/partials/gallery.njk
Normal file
19
src/_includes/partials/gallery.njk
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<is-land on:idle>
|
||||
<div class="gallery | grid mt-l-xl" role="list" style="--grid-min-item-size: clamp(16rem, 50vw, 20rem)">
|
||||
{%- for item in gallery -%}
|
||||
<dialog class="flow modal{{ loop.index }}">
|
||||
<button class="button" autofocus>Close</button>
|
||||
{%- image item.image, item.alt, item.caption -%}
|
||||
</dialog>
|
||||
<button data-index="{{ loop.index }}">{%- image item.image, item.alt -%}</button>
|
||||
{%- endfor -%}
|
||||
</div>
|
||||
|
||||
{% css "inline" %}
|
||||
{% include "css/gallery.css" %}
|
||||
{% endcss %}
|
||||
|
||||
{% js "defer" %}
|
||||
{% include "scripts/gallery.js" %}
|
||||
{% endjs %}
|
||||
</is-land>
|
||||
|
|
@ -2,13 +2,10 @@
|
|||
|
||||
<header class="wrapper">
|
||||
<div class="repel ontop">
|
||||
<a
|
||||
href="/"
|
||||
class="logo | cluster"
|
||||
{% if page.url == "/" %}aria-current="page"{% endif %}
|
||||
>
|
||||
{% include "svg/star.svg" %}
|
||||
<span>{{ meta.siteName }}</span>
|
||||
<a href="/" class="logo | cluster" {% if page.url == "/" %}aria-current="page"{% endif %}>
|
||||
{% svg "misc/star" %}
|
||||
|
||||
<span class="font-display">{{ meta.siteName }}</span>
|
||||
</a>
|
||||
{% include "partials/main-nav.njk" %}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,15 +1,7 @@
|
|||
<!-- toggle drawer menu in _data/meta.js -->
|
||||
{% set drawerNav = meta.navigation.drawerNav %}
|
||||
|
||||
{% if drawerNav %}
|
||||
<!-- check for drawer menu being activated in meta.js -->
|
||||
{% set drawerClass = "site-nav-drawer" %}
|
||||
{% endif %}
|
||||
|
||||
<nav
|
||||
id="mainnav"
|
||||
class=" {{ drawerClass or 'site-nav' }}"
|
||||
aria-label="{{ meta.navigation.ariaTop }}"
|
||||
>
|
||||
<nav id="mainnav" class="mainnav" aria-label="{{ meta.navigation.ariaTop }}">
|
||||
<ul class="cluster" role="list">
|
||||
{% for item in navigation.top %}
|
||||
<li>
|
||||
|
|
@ -30,5 +22,42 @@
|
|||
</nav>
|
||||
|
||||
{% if drawerNav %}
|
||||
{% include "components/burger-template.njk" %}
|
||||
<!-- template element holding a button that needs to be injected when JavaScript is finally available. -->
|
||||
<!-- based on an article by Manuel Matuzovic, https://web.dev/website-navigation/ -->
|
||||
<!-- see also: https://kittygiraudel.com/2022/09/30/templating-in-html/ -->
|
||||
|
||||
<template id="burger-template">
|
||||
<button type="button" aria-expanded="false" aria-label="Menu" aria-controls="mainnav">
|
||||
<span>{{ meta.navigation.navLabel }}</span>
|
||||
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="1em"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M5 12h14" />
|
||||
<path d="M12 5v14" />
|
||||
</svg>
|
||||
</button>
|
||||
</template>
|
||||
{% endif %}
|
||||
|
||||
{% css "inline" %}
|
||||
{% if drawerNav %}
|
||||
{% include "css/nav-drawer.css" %}
|
||||
{% else %}
|
||||
{% include "css/nav-pills.css" %}
|
||||
{% endif %}
|
||||
{% endcss %}
|
||||
|
||||
{% if drawerNav %}
|
||||
{% js "defer" %}
|
||||
{% include "scripts/nav-drawer-inline.js" %}
|
||||
{% endjs %}
|
||||
{% endif %}
|
||||
|
|
|
|||
|
|
@ -5,9 +5,7 @@
|
|||
<ol class="pagination | cluster" role="list">
|
||||
<li>
|
||||
{% if pagination.href.previous %}
|
||||
<a href="{{ pagination.href.previous }}">
|
||||
{{ meta[metaKey].paginationPrevious }}
|
||||
</a>
|
||||
<a href="{{ pagination.href.previous }}"> {{ meta[metaKey].paginationPrevious }} </a>
|
||||
{% else %}
|
||||
{{ meta[metaKey].paginationPrevious }}
|
||||
{% endif %}
|
||||
|
|
@ -36,3 +34,7 @@
|
|||
</ol>
|
||||
</nav>
|
||||
</section>
|
||||
|
||||
{% css "inline" %}
|
||||
{% include "css/pagination.css" %}
|
||||
{% endcss %}
|
||||
17
src/_includes/partials/theme-switch.njk
Normal file
17
src/_includes/partials/theme-switch.njk
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<is-land on:idle
|
||||
><div
|
||||
role="region"
|
||||
class="theme-switch | cluster mt-xs"
|
||||
style="--cluster-horizontal-alignment: center; --gutter: 0.5rem"
|
||||
aria-labelledby="theme-switcher-label"
|
||||
data-theme-switcher
|
||||
>
|
||||
<h2 id="theme-switcher-label">{{ meta.themeSwitch.title }}</h2>
|
||||
<button class="button" id="light-theme-toggle" data-theme="light">
|
||||
<span>{{ meta.themeSwitch.light }}</span>
|
||||
</button>
|
||||
<button class="button" id="dark-theme-toggle" data-theme="dark">
|
||||
<span>{{ meta.themeSwitch.dark }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</is-land>
|
||||
|
|
@ -1 +0,0 @@
|
|||
(()=>{var r="theme-preference",n="{{ meta.themeSwitch.light }}",d="{{ meta.themeSwitch.dark }}",t={value:s()};window.onload=()=>{let e=document.querySelector("#light-theme-toggle"),l=document.querySelector("#dark-theme-toggle"),o=document.querySelector("[data-theme-switcher]");o&&(o.removeAttribute("hidden"),a(),e.addEventListener("click",()=>c("light")),l.addEventListener("click",()=>c("dark")),e.setAttribute("aria-pressed",t.value==="light"),l.setAttribute("aria-pressed",t.value==="dark"))};window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",({matches:e})=>{t.value=e?"dark":"light",i()});function c(e){t.value=e,document.querySelector("#light-theme-toggle").setAttribute("aria-pressed",e==="light"),document.querySelector("#dark-theme-toggle").setAttribute("aria-pressed",e==="dark"),i()}function s(){return localStorage.getItem(r)?localStorage.getItem(r):window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}function i(){localStorage.setItem(r,t.value),a()}function a(){document.firstElementChild.setAttribute("data-theme",t.value),document.querySelector("#light-theme-toggle")?.setAttribute("aria-label",n),document.querySelector("#dark-theme-toggle")?.setAttribute("aria-label",d)}a();})();
|
||||
10
src/_includes/webc/custom-card.webc
Normal file
10
src/_includes/webc/custom-card.webc
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<custom-card class="flow no-indicator" webc:root>
|
||||
<slot name="image"></slot>
|
||||
<slot name="headline"></slot>
|
||||
<div class="meta | cluster"><slot name="date"></slot><slot name="tag"></slot></div>
|
||||
<slot name="content"></slot>
|
||||
<slot name="footer"></slot>
|
||||
|
||||
<!-- TODO: find out why is this not being hoisted into the webc css bundle? -->
|
||||
<link rel="stylesheet" href="/assets/css/components/custom-card.css" />
|
||||
</custom-card>
|
||||
9
src/_includes/webc/custom-masonry.webc
Normal file
9
src/_includes/webc/custom-masonry.webc
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<is-land on:visible>
|
||||
<custom-masonry class="grid" data-rows="masonry" :data-layout="layout" webc:root webc:keep>
|
||||
<slot></slot>
|
||||
|
||||
<template data-island="once" webc:raw>
|
||||
<script src="/assets/scripts/components/custom-masonry.js" type="module"></script>
|
||||
</template>
|
||||
</custom-masonry>
|
||||
</is-land>
|
||||
45
src/_includes/webc/custom-svg.webc
Normal file
45
src/_includes/webc/custom-svg.webc
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
<!-- by Ryan Mulligan: https://github.com/hexagoncircle/start-me-up/blob/main/src/_includes/inline-svg.webc -->
|
||||
|
||||
<script webc:type="render" webc:is="template">
|
||||
const Image = require('@11ty/eleventy-img');
|
||||
const {optimize} = require('svgo');
|
||||
|
||||
module.exports = async function () {
|
||||
const meta = await Image(this.src, {
|
||||
formats: ['svg'],
|
||||
dryRun: true
|
||||
});
|
||||
|
||||
const plugins = [];
|
||||
const excludeAttributes = ['src', 'uid'];
|
||||
const svgContents = meta.svg[0].buffer.toString();
|
||||
|
||||
const getAttributes = () => {
|
||||
const arr = [];
|
||||
|
||||
for (const prop in this.webc.attributes) {
|
||||
if (!excludeAttributes.includes(prop)) {
|
||||
const attribute = this.slugify(prop, {decamelize: true});
|
||||
const value = this.webc.attributes[prop];
|
||||
|
||||
arr.push({[attribute]: value});
|
||||
}
|
||||
}
|
||||
|
||||
return arr;
|
||||
};
|
||||
|
||||
if (this.webc.attributes) {
|
||||
plugins.push({
|
||||
name: 'addAttributesToSVGElement',
|
||||
params: {
|
||||
attributes: getAttributes()
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const result = optimize(svgContents, {plugins});
|
||||
|
||||
return result.data;
|
||||
};
|
||||
</script>
|
||||
16
src/_includes/webc/custom-youtube-link.webc
Normal file
16
src/_includes/webc/custom-youtube-link.webc
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<style>
|
||||
custom-youtube-link {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: var(--space-xs);
|
||||
font-size: var(--size-step-min-1);
|
||||
}
|
||||
custom-youtube-link svg {
|
||||
font-size: var(--size-step-0);
|
||||
}
|
||||
</style>
|
||||
|
||||
<custom-svg aria-hidden="true" src="./src/assets/svg/platform/youtube.svg"></custom-svg>
|
||||
<a :href="href"><span webc:if="label" @text="label" webc:nokeep></span></a>
|
||||
|
||||
<!-- Inspired by https://github.com/zachleat/zachleat.com -->
|
||||
59
src/_includes/webc/custom-youtube.webc
Normal file
59
src/_includes/webc/custom-youtube.webc
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
<!-- component composition by: https://github.com/zachleat/zachleat.com -->
|
||||
|
||||
<script webc:setup>
|
||||
function getPosterImage(slug, posterSize = 'auto') {
|
||||
let videoUrl = `https://youtube.com/watch?v=${slug}`;
|
||||
return `https://v1.opengraph.11ty.dev/${encodeURIComponent(videoUrl)}/${posterSize}/jpeg/`;
|
||||
}
|
||||
function getLinkUrl(slug, start) {
|
||||
return `https://youtube.com/watch?v=${slug}${start ? `&t=${start}s` : ''}`;
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
/* Hide without JS */
|
||||
is-land:not(:defined).video-wrapper {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<custom-youtube webc:root class="flow">
|
||||
<is-land on:visible class="video-wrapper">
|
||||
<lite-youtube
|
||||
:videoid="slug"
|
||||
:js-api="jsapi !== 'undefined' ? '' : false"
|
||||
:params="start ? `start=${start}` : false"
|
||||
:playlabel="`Play${label ? `: ${label}` : ''}`"
|
||||
:style="`background-image: var(--yt-poster-img-url);--yt-poster-img-url-lazy: url('${poster || getPosterImage(slug, posterSize)}');`"
|
||||
></lite-youtube>
|
||||
|
||||
<template data-island="once" webc:raw>
|
||||
<style>
|
||||
lite-youtube {
|
||||
max-inline-size: 100% !important;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
is-land lite-youtube {
|
||||
background-color: #eee;
|
||||
border-radius: 0.5em;
|
||||
background-size: cover;
|
||||
}
|
||||
is-land[ready] lite-youtube {
|
||||
/* gotta set in `style` to override the 480w image from lite-youtube */
|
||||
--yt-poster-img-url: var(--yt-poster-img-url-lazy);
|
||||
}
|
||||
|
||||
.video-wrapper {
|
||||
aspect-ratio: 16 / 9;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
is-land.video-wrapper {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="/assets/components/lite-yt-embed.css" />
|
||||
<script type="module" src="/assets/components/lite-yt-embed.js"></script>
|
||||
</template>
|
||||
</is-land>
|
||||
</custom-youtube>
|
||||
<custom-youtube-link @raw="label" :label="label" :href="getLinkUrl(slug, start)"></custom-youtube-link>
|
||||
Loading…
Reference in a new issue