From 638da336a1a6a45200037de4bcd9c2758bcf948c Mon Sep 17 00:00:00 2001 From: Richard Helm Date: Fri, 23 Feb 2024 16:02:49 +0000 Subject: [PATCH] feat(docs): speed up navigation through turbolinks (VIV-1585) --- apps/docs/_layouts/base.njk | 5 ++- .../assets/bundled-scripts/icons-gallery.js | 42 ++++++++++++++++-- .../assets/bundled-scripts/live-sample.js | 23 +++++++--- .../docs/assets/bundled-scripts/turbolinks.js | 31 +++++++++++++ apps/docs/assets/scripts/main.js | 44 ++++++++++++------- apps/docs/assets/scripts/scroll-handler.js | 14 ------ apps/docs/rollup.config.js | 2 + docs/icon/icons-gallery.md | 31 ++----------- package-lock.json | 13 ++++++ package.json | 1 + 10 files changed, 136 insertions(+), 70 deletions(-) create mode 100644 apps/docs/assets/bundled-scripts/turbolinks.js diff --git a/apps/docs/_layouts/base.njk b/apps/docs/_layouts/base.njk index 2705ceaa01..4b3025c1be 100644 --- a/apps/docs/_layouts/base.njk +++ b/apps/docs/_layouts/base.njk @@ -76,11 +76,12 @@ {% block header %}{% endblock %} + - + @@ -106,7 +107,7 @@ {% include "navigation.njk" %} -
+
{% block banner %}{% endblock %}
diff --git a/apps/docs/assets/bundled-scripts/icons-gallery.js b/apps/docs/assets/bundled-scripts/icons-gallery.js index 04fd516a12..c8a9d3af7b 100644 --- a/apps/docs/assets/bundled-scripts/icons-gallery.js +++ b/apps/docs/assets/bundled-scripts/icons-gallery.js @@ -6,9 +6,7 @@ let jsonData; let index = 0; let numShown = NUM_TO_SHOW; -fetchJSONData(); - -async function fetchJSONData() { +export async function initIconsGallery() { try { const response = await fetch(`${BASE_URL}/v${ICON_SET_VERSION}/manifest.json`); jsonData = await response.json(); @@ -44,6 +42,7 @@ function addOption(categoryName) { function showIcons(data) { index = 0; + let last; while (last = iconsLayout.lastChild) iconsLayout.removeChild(last); while (index < data.length) { addIcon(data[index].id); @@ -145,4 +144,41 @@ function filterIconsByTag(iconsArray) { window.showMore = showMore; window.onClickFilter = onClickFilter; +customElements.define('vivid-icons-gallery', class VividIconsGallery extends HTMLElement { + constructor() { + super(); + this.innerHTML = ` +
+ + + + + + + +
+ + Filter By Style: + + + + + Filter By Color: + + + +
+ + +
+ +
+ +
`; + } + + connectedCallback() { + initIconsGallery(); + } +}); diff --git a/apps/docs/assets/bundled-scripts/live-sample.js b/apps/docs/assets/bundled-scripts/live-sample.js index 1199f0688b..79d4b42b1c 100644 --- a/apps/docs/assets/bundled-scripts/live-sample.js +++ b/apps/docs/assets/bundled-scripts/live-sample.js @@ -5,12 +5,6 @@ import { html } from "@codemirror/lang-html" import { Compartment } from '@codemirror/state' import { oneDark } from '@codemirror/theme-one-dark' -window.onload = () => { - addSamplesEditors(); - addButtonsHandlers(); - addLocaleSwitcher(); -}; - const samplesEditors = new Map(); const theme = new Compartment(); @@ -159,3 +153,20 @@ function switchLocale(event) { iframe.contentWindow.setLocale(iframe.contentWindow.locales[select.value]); iframe.contentWindow.document.documentElement.lang = select.value; } + +function cleanupEditors() { + for (const { view } of samplesEditors.values()) { + view.destroy(); + } + samplesEditors.clear(); +} + +function setupLiveSamples() { + cleanupEditors(); + addSamplesEditors(); + addButtonsHandlers(); + addLocaleSwitcher(); +} + +window.addEventListener('load', setupLiveSamples); +window.addEventListener('htmx:afterSwap', setupLiveSamples); diff --git a/apps/docs/assets/bundled-scripts/turbolinks.js b/apps/docs/assets/bundled-scripts/turbolinks.js new file mode 100644 index 0000000000..89e79ddbe8 --- /dev/null +++ b/apps/docs/assets/bundled-scripts/turbolinks.js @@ -0,0 +1,31 @@ +import 'htmx.org'; + +window.addEventListener('DOMContentLoaded', () => { + const navItems = document.querySelectorAll('vwc-nav-item'); + for (const navItem of navItems) { + navItem.setAttribute('hx-get', navItem.href); + navItem.setAttribute('hx-push-url', 'true'); + navItem.addEventListener('click', (e) => { e.preventDefault() }); + window.htmx.process(navItem); + } +}); + +const handleLocationChange = () => { + for (const el of document.querySelectorAll('vwc-nav-item[aria-current="page"], vwc-nav-disclosure[aria-current="page"]')) { + el.removeAttribute('aria-current'); + } + + let current = document.querySelector(` + vwc-nav-item[href="${location.pathname}"], + vwc-nav-item[href="${location.pathname.replace(/\/$/, '')}"] + `); + while (current) { + if (current.tagName === 'VWC-NAV-ITEM' || current.tagName === 'VWC-NAV-DISCLOSURE') { + current.setAttribute('aria-current', 'page'); + } + current = current.parentElement; + } +} + +window.addEventListener("popstate", handleLocationChange); +window.addEventListener("htmx:pushedIntoHistory", handleLocationChange); diff --git a/apps/docs/assets/scripts/main.js b/apps/docs/assets/scripts/main.js index 8f3ac3aef5..6115bcad32 100644 --- a/apps/docs/assets/scripts/main.js +++ b/apps/docs/assets/scripts/main.js @@ -24,16 +24,12 @@ const codeBlockButtonClick = (button) => { button.ariaExpanded = details.open; }; -const onloadIframe = (iFrame) => { - const toggle = document.querySelector('vwc-button#dark-mode-toggle'); - const menu = document.querySelector('vwc-menu#dark-mode-menu'); - - setCurrentIframeTheme(toggle, iFrame); - menu.addEventListener('click', () => { - setCurrentIframeTheme(toggle, iFrame); - }); - window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => setCurrentIframeTheme(toggle, iFrame)); +const getCurrentTheme = () => + document.querySelector('vwc-button#dark-mode-toggle').icon === 'dark-mode-solid' ? 'dark' : 'light'; +const onloadIframe = (iFrame) => { + iFrame.setAttribute('data-vivid-iframe', ''); + setCurrentIframeTheme(getCurrentTheme(), iFrame); autoResize(iFrame); }; @@ -51,16 +47,30 @@ const autoResize = (iFrame) => { }).observe(iFrame.contentWindow.document.documentElement); }; -const setCurrentIframeTheme = (toggle, iFrame) => { +const setCurrentIframeTheme = (displayMode, iFrame) => { const iframeHead = iFrame.contentWindow.document.head; - const displayMode = toggle.icon === "dark-mode-solid" ? 'dark' : 'light'; - const theme = ``; + const theme = ``; const themeLink = iframeHead.querySelector('#theme-link'); - if (themeLink) { - themeLink.outerHTML = theme; - } else { - iframeHead.insertAdjacentHTML("beforeend", theme); - } + if (!themeLink) { + iframeHead.insertAdjacentHTML("beforeend", theme); + } else if (themeLink.dataset.theme !== displayMode) { + themeLink.outerHTML = theme; + } +} + +const updateThemeOfAllIframes = () => { + const newTheme = getCurrentTheme(); + for (const iframe of document.querySelectorAll('[data-vivid-iframe]')) { + setCurrentIframeTheme(newTheme, iframe); + } +} + +const setupIframeThemeUpdates = () => { + document + .querySelector('vwc-menu#dark-mode-menu') + .addEventListener('change', updateThemeOfAllIframes); + window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', updateThemeOfAllIframes); } +window.addEventListener('load', setupIframeThemeUpdates); diff --git a/apps/docs/assets/scripts/scroll-handler.js b/apps/docs/assets/scripts/scroll-handler.js index 64f3fb9200..edc3c1f667 100644 --- a/apps/docs/assets/scripts/scroll-handler.js +++ b/apps/docs/assets/scripts/scroll-handler.js @@ -11,19 +11,6 @@ const onScroll = () => { const isWindowScrolled = window.scrollY > 0; const isSideDrawerScrolled = getSideDrawerBase().scrollTop > 0; updateHeaderElevationShadow(isWindowScrolled || isSideDrawerScrolled); - // save sideDrawer's scroll in sessionStorage - if (getSideDrawerBase().scrollTop) { - sessionStorage.setItem("scroll", getSideDrawerBase().scrollTop); - } -} - -const setScrollFromSessionStorage = () => { - // set sideDrawer's scroll from sessionStorage - if (getSideDrawerBase().offsetHeight > 0) { - getSideDrawerBase().scrollTop = sessionStorage.getItem('scroll') ?? 0; - } else { - requestAnimationFrame(setScrollFromSessionStorage); - } } (() => { @@ -31,7 +18,6 @@ const setScrollFromSessionStorage = () => { window.addEventListener('scroll', onScroll); customElements.whenDefined('vwc-side-drawer').then(() => { - setScrollFromSessionStorage(); getSideDrawerBase().addEventListener('scroll', onScroll); }); })(); diff --git a/apps/docs/rollup.config.js b/apps/docs/rollup.config.js index d88e640bb4..d7f6215e54 100644 --- a/apps/docs/rollup.config.js +++ b/apps/docs/rollup.config.js @@ -84,12 +84,14 @@ const DIRS = [ './dist/apps/docs/assets/scripts/', './dist/apps/docs/assets/scripts/', './dist/apps/docs/assets/scripts/', + './dist/apps/docs/assets/scripts/', './dist/apps/docs', ]; export default [ './apps/docs/assets/bundled-scripts/live-sample.js', './apps/docs/assets/bundled-scripts/cache-assets.js', './apps/docs/assets/bundled-scripts/icons-gallery.js', + './apps/docs/assets/bundled-scripts/turbolinks.js', 'vivid-components', './apps/docs/assets/bundled-scripts/sw.js', ].map((input, index) => { diff --git a/docs/icon/icons-gallery.md b/docs/icon/icons-gallery.md index 89cd5dc4c1..20e2970de6 100644 --- a/docs/icon/icons-gallery.md +++ b/docs/icon/icons-gallery.md @@ -9,32 +9,7 @@ As an example, you can use it as follows: -
- - - - - - - -
- - Filter By Style: - - - - - Filter By Color: - - - -
- - -
- -
- -
+ + + - \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 410bb6feb8..dc9748fcba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -103,6 +103,7 @@ "expr-eval": "^2.0.2", "glob": "^7.2.0", "highlight.js": "^11.5.1", + "htmx.org": "^1.9.10", "http-server": "^14.1.0", "jasmine-core": "4.1.1", "jasmine-spec-reporter": "~5.0.0", @@ -18119,6 +18120,12 @@ "entities": "^3.0.1" } }, + "node_modules/htmx.org": { + "version": "1.9.10", + "resolved": "https://registry.npmjs.org/htmx.org/-/htmx.org-1.9.10.tgz", + "integrity": "sha512-UgchasltTCrTuU2DQLom3ohHrBvwr7OqpwyAVJ9VxtNBng4XKkVsqrv0Qr3srqvM9ZNI3f1MmvVQQqK7KW/bTA==", + "dev": true + }, "node_modules/http-equiv-refresh": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/http-equiv-refresh/-/http-equiv-refresh-1.0.0.tgz", @@ -43241,6 +43248,12 @@ "entities": "^3.0.1" } }, + "htmx.org": { + "version": "1.9.10", + "resolved": "https://registry.npmjs.org/htmx.org/-/htmx.org-1.9.10.tgz", + "integrity": "sha512-UgchasltTCrTuU2DQLom3ohHrBvwr7OqpwyAVJ9VxtNBng4XKkVsqrv0Qr3srqvM9ZNI3f1MmvVQQqK7KW/bTA==", + "dev": true + }, "http-equiv-refresh": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/http-equiv-refresh/-/http-equiv-refresh-1.0.0.tgz", diff --git a/package.json b/package.json index 651254a547..bee16eee59 100644 --- a/package.json +++ b/package.json @@ -103,6 +103,7 @@ "expr-eval": "^2.0.2", "glob": "^7.2.0", "highlight.js": "^11.5.1", + "htmx.org": "^1.9.10", "http-server": "^14.1.0", "jasmine-core": "4.1.1", "jasmine-spec-reporter": "~5.0.0",