update components and partials

This commit is contained in:
madrilene 2024-06-03 11:20:20 +02:00
parent a71962675c
commit 5247213da7
28 changed files with 321 additions and 214 deletions

View file

@ -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>

View file

@ -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>

View file

@ -1,3 +0,0 @@
<time datetime="{{ definedDate | toIsoString }}">
{{ definedDate | formatDate('MMMM D, YYYY') }}
</time>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View 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>

View file

@ -0,0 +1 @@
<script src="{% getBundleFileUrl "js", "defer" %}" type="module"></script>

View 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 %}

View file

@ -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 }}" />

View 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 %}

View 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 %}

View file

@ -0,0 +1 @@
<time datetime="{{ definedDate | toIsoString }}"> {{ definedDate | formatDate('MMMM D, YYYY') }} </time>

View 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 %}

View file

@ -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>

View file

@ -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 }}">
&copy; {% 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>

View 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>

View file

@ -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>

View file

@ -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 %}

View file

@ -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 %}

View 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>

View file

@ -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();})();

View 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>

View 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>

View 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>

View 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 -->

View 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>