From 732487b598d6f3b6909e93bf04ebc0fbe36b6ef5 Mon Sep 17 00:00:00 2001 From: Julia Ogris Date: Mon, 26 Aug 2024 16:30:17 +1000 Subject: [PATCH] labsite: Update JS and CSS for Next button Add a bit new CSS and JS to the labsite (JS is shared with playsite via symlink), that hides all Notes content after the first Next button on load and only reveals content until the next button. It also tweaks styling for the `
` blocks to align with the Next buttons. Sneak in a few other CSS updates. Never ending story. --- frontend/lab/css/overrides.css | 64 ++++++++++++++++++++++++---------- frontend/play/index.js | 61 +++++++++++++++++++++++--------- 2 files changed, 90 insertions(+), 35 deletions(-) diff --git a/frontend/lab/css/overrides.css b/frontend/lab/css/overrides.css index 7400d242..a1ec846f 100644 --- a/frontend/lab/css/overrides.css +++ b/frontend/lab/css/overrides.css @@ -3,6 +3,9 @@ --notes-max-width: min(25vw, calc(20rem + 32px)); --editor-max-width: calc(36rem + 16px); } +html { + scroll-behavior: smooth; +} .max-width-wrapper:not(:has(.main > .hidden)) { max-width: calc(var(--editor-max-width) + var(--notes-max-width) + var(--canvas-size) + 64px); @@ -22,6 +25,7 @@ overflow-y: auto; height: 100%; padding: 8px 16px var(--editor-padding-bottom) 16px; + scroll-behavior: smooth; } @media (min-width: 768px) { @@ -40,34 +44,28 @@ margin-bottom: 16px; font-size: 1.5rem; } -.notes :is(h2, h3, h4, summary) { +.notes :is(h2, h3) { color: var(--color); font-size: 1rem; - font-weight: 400; + font-weight: 600; margin-top: 16px; margin-bottom: 12px; } -.notes h2 { - font-weight: 600; +.notes h3 { + font-size: 0.875rem; } .notes details { - margin-top: 16px; margin-bottom: 12px; } -.notes summary { +.notes details pre { margin: 0; - cursor: pointer; - font-weight: 600; - color: var(--color-slightly-dimmed); - font-size: 0.875rem; } -.notes summary + p { - margin-top: 12px; +.notes details[open] > summary + * { + margin-top: 8px; } -.notes p + details { - margin-top: -8px; - margin-bottom: 20px; +.notes details[open] { + margin-bottom: 16px; } .notes h4 { @@ -124,7 +122,7 @@ .notes code { padding: 0.25em; - font-size: 0.85rem; + font-size: 0.875em; background-color: var(--background-inline-code); border-radius: 4px; color: var(--color); @@ -135,6 +133,7 @@ color: var(--color); background: none; margin-bottom: 24px; + pointer-events: none; } .notes img { @@ -191,7 +190,31 @@ border: 1px solid var(--border-color); border-radius: 6px; } - +.notes summary { + list-style: none; + display: block; +} +summary::-webkit-details-marker { + display: none; +} +.notes summary, +.notes .next-btn { + background: none; + border: 1px solid var(--color-accent-hover); + color: var(--color-accent-hover); + border-radius: 10px; + padding: 4px; + min-width: 100px; + margin-left: auto; + margin-right: 0; + display: block; + width: fit-content; + text-align: center; + font-size: 1rem; +} +.next-btn.hidden { + display: none; +} @media (max-width: 767px) { .notes { display: none; @@ -203,10 +226,13 @@ } @media (hover: hover) { - .notes summary { + .notes summary, + .notes .next-btn { &:hover, &:hover code { - color: var(--color-accent); + color: hsl(201deg 100% 78%); + border-color: hsl(201deg 100% 78%); + cursor: pointer; } } } diff --git a/frontend/play/index.js b/frontend/play/index.js index 6d0f63a6..2ff8857b 100644 --- a/frontend/play/index.js +++ b/frontend/play/index.js @@ -423,30 +423,43 @@ async function handleHashChangeNoFormat() { } const { source, notes } = await fetchSourceWithNotes(opts) updateNotes(notes) - updateEditorContent(source) + updateEditor(source, opts) updateSampleTitle() clearOutput() - editor.onUpdate(clearHash) - editorHidden = opts.editor === "none" - const classList = document.querySelector(".editor-wrap").classList - editorHidden ? classList.add("hidden") : classList.remove("hidden") } function updateNotes(notes) { + hasNotes(notes) ? addNotes(notes) : removeNotes() +} + +function hasNotes(notes) { + return !!notes && !!document.querySelector("#notes") +} + +function removeNotes() { + notesHidden = true const notesEl = document.querySelector("#notes") - if (!notesEl) { - notesHidden = true - return - } - if (!notes) { - notesHidden = true - notesEl.classList.add("hidden") - notesEl.innerHTML = "" - return - } + if (!notesEl) return + notesEl.classList.add("hidden") + notesEl.innerHTML = "" +} + +function addNotes(notes) { notesHidden = false + const notesEl = document.querySelector("#notes") notesEl.classList.remove("hidden") notesEl.innerHTML = notes + + // hide all notes after first "next" button: + //

+ let el = notesEl.querySelector(".next-btn")?.parentElement?.nextElementSibling + while (el) { + el.classList.add("hidden") + el = el.nextElementSibling + } + notesEl.querySelectorAll(".next-btn").forEach((btn) => { + btn.onclick = handleNotesNextClick + }) notesEl.querySelectorAll(".language-evy").forEach((el) => { el.innerHTML = highlightEvy(el.textContent) }) @@ -456,11 +469,27 @@ function updateNotes(notes) { notesEl.scrollTo(0, 0) } -function updateEditorContent(content) { +function handleNotesNextClick(e) { + const btn = e.target + let el = btn?.parentElement?.nextElementSibling + // show until following "next" button or end + while (el && !el.classList.contains("next-btn")) { + el.classList.remove("hidden") + if (el.querySelector(".next-btn")) break + el = el.nextElementSibling + } + btn.nextElementSibling?.scrollIntoView({ behavior: "smooth" }) +} + +function updateEditor(content, opts) { !editor && initEditor() editor.onUpdate(null) editor.update({ value: content, errorLines: {} }) document.querySelector(".editor-wrap").scrollTo(0, 0) + editor.onUpdate(clearHash) + editorHidden = opts.editor === "none" + const classList = document.querySelector(".editor-wrap").classList + editorHidden ? classList.add("hidden") : classList.remove("hidden") } // parseHash parses URL fragment into object e.g.: