diff --git a/assets/js/header-modal.js b/assets/js/header-modal.js new file mode 100644 index 0000000..4654410 --- /dev/null +++ b/assets/js/header-modal.js @@ -0,0 +1,116 @@ +// header-modal.js - Share modal + mobile search behaviour for the site header. +// Extracted from layouts/partials/header.html. + +(function () { + "use strict"; + + function init() { + const modal = document.getElementById("share-modal"); + const btn = document.getElementById("share-link-btn"); + const copyBtn = document.getElementById("copy-url-btn"); + const input = document.getElementById("share-url"); + + // Mobile search elements + const mobileSearchBtn = document.getElementById("mobile-search-btn"); + const mobileSearchOverlay = document.getElementById("mobile-search-overlay"); + const mobileSearchInput = document.getElementById("mobile-search-input"); + + // Mobile search toggle + if (mobileSearchBtn && mobileSearchOverlay) { + mobileSearchBtn.addEventListener("click", function () { + mobileSearchOverlay.style.display = "block"; + setTimeout(function () { + mobileSearchOverlay.classList.add("active"); + if (mobileSearchInput) { + mobileSearchInput.focus(); + } + }, 10); + document.body.style.overflow = "hidden"; + }); + + const closeMobileSearch = function () { + mobileSearchOverlay.classList.remove("active"); + setTimeout(function () { + mobileSearchOverlay.style.display = "none"; + document.body.style.overflow = ""; + }, 300); + }; + + mobileSearchOverlay.addEventListener("click", function (event) { + if (event.target === mobileSearchOverlay) { + closeMobileSearch(); + } + }); + + document.addEventListener("keydown", function (event) { + if (event.key === "Escape" && mobileSearchOverlay.classList.contains("active")) { + closeMobileSearch(); + } + }); + } + + // Share modal + if (btn && modal) { + btn.addEventListener("click", function () { + modal.style.display = "block"; + modal.classList.add("active"); + document.body.style.overflow = "hidden"; + }); + + const closeModal = function () { + modal.classList.remove("active"); + setTimeout(function () { + modal.style.display = "none"; + document.body.style.overflow = ""; + }, 200); + }; + + window.addEventListener("click", function (event) { + if (event.target === modal) { + closeModal(); + } + }); + + document.addEventListener("keydown", function (event) { + if (event.key === "Escape" && modal.style.display === "block") { + closeModal(); + } + }); + } + + // Copy-link button + if (copyBtn && input) { + const originalLabel = copyBtn.dataset.labelCopy || "Copy URL"; + const copiedLabel = copyBtn.dataset.labelCopied || "Copied!"; + const iconHTML = + ''; + + copyBtn.addEventListener("click", function () { + input.select(); + if (navigator.clipboard && navigator.clipboard.writeText) { + navigator.clipboard.writeText(input.value).catch(function () {}); + } else { + try { + document.execCommand("copy"); + } catch (e) { + // Clipboard unavailable — selection still allows manual copy. + } + } + copyBtn.textContent = copiedLabel; + + setTimeout(function () { + copyBtn.innerHTML = (iconHTML + " " + originalLabel).trim(); + }, 2000); + }); + } + } + + if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", init); + } else { + init(); + } +})(); diff --git a/i18n/en.toml b/i18n/en.toml new file mode 100644 index 0000000..ddf8e69 --- /dev/null +++ b/i18n/en.toml @@ -0,0 +1,26 @@ +[SearchPlaceholder] +other = "Search..." + +[Share] +other = "Share" + +[ShareThisPage] +other = "Share this page" + +[ToggleTheme] +other = "Toggle dark/light mode" + +[CopyLink] +other = "Copy URL" + +[LinkCopied] +other = "Copied!" + +[QRCodeFor] +other = "QR code for" + +[ToggleMenu] +other = "Toggle menu" + +[Home] +other = "Home" diff --git a/layouts/partials/header.html b/layouts/partials/header.html index c4f6d6b..669bb34 100644 --- a/layouts/partials/header.html +++ b/layouts/partials/header.html @@ -1,11 +1,10 @@