From c42c56108ebac6673ec5c86f9f0d51f31e8eb2bd Mon Sep 17 00:00:00 2001 From: grm Date: Sat, 19 Sep 2026 00:04:08 +0300 Subject: Remove the menu fold MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The header menu no longer folds into a ☰ button: the nav_fold and nav_fold_label options, Layout.Fold/BurgerAt, the burger markup and its checkbox, the fold rules in blog.css and the measuring script on the public page are gone, and the Design tab's preview only sizes its frame again. The public page runs no script of its own once more. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Sd8UPWrvyYCLj97JexNw3A --- internal/i18n/el.go | 12 ++--- internal/web/layout.go | 18 ------- internal/web/static/blog.css | 47 ----------------- internal/web/templates/dashboard/design.html | 26 ++-------- internal/web/templates/layouts/blog.html | 44 ++++------------ internal/web/theme.go | 11 +--- internal/web/web_test.go | 76 +--------------------------- 7 files changed, 21 insertions(+), 213 deletions(-) (limited to 'internal') diff --git a/internal/i18n/el.go b/internal/i18n/el.go index 00af43d..5d8a14e 100644 --- a/internal/i18n/el.go +++ b/internal/i18n/el.go @@ -397,14 +397,10 @@ var el = map[string]string{ "Underlined": "Υπογραμμισμένη", "Boxed": "Σε πλαίσιο", "Not marked": "Χωρίς σήμανση", - "When the menu does not fit": "Όταν το μενού δεν χωράει", - "Fold the header menu into a button when its links do not fit on one line": "Δίπλωμα του μενού της κεφαλίδας σε κουμπί όταν οι σύνδεσμοί του δεν χωρούν σε μία γραμμή", - "Button": "Κουμπί", - "Wide screen": "Πλατιά οθόνη", - "Phone": "Κινητό", - "Preview unavailable.": "Η προεπισκόπηση δεν είναι διαθέσιμη.", - "Your header with the menu as set here; the phone view shows the folded menu. Nothing is saved until you press Save.": "Η κεφαλίδα σας με το μενού όπως ρυθμίζεται εδώ· η προβολή κινητού δείχνει το διπλωμένο μενού. Τίποτα δεν αποθηκεύεται μέχρι να πατήσετε Αποθήκευση.", - "The button sits at the right of the title or logo just above the menu, or in the menu bar itself when nothing is above it, and opens the links as a list. Readers whose browser runs no scripts get it on phones.": "Το κουμπί μπαίνει δεξιά από τον τίτλο ή το λογότυπο ακριβώς πάνω από το μενού, ή μέσα στη μπάρα του μενού όταν δεν υπάρχει τίποτα από πάνω, και ανοίγει τους συνδέσμους σε λίστα. Όσοι αναγνώστες έχουν πρόγραμμα περιήγησης χωρίς scripts το βλέπουν στα κινητά.", + "Wide screen": "Πλατιά οθόνη", + "Phone": "Κινητό", + "Preview unavailable.": "Η προεπισκόπηση δεν είναι διαθέσιμη.", + "Your header with the menu as set here, on a wide screen or a phone. Nothing is saved until you press Save.": "Η κεφαλίδα σας με το μενού όπως ρυθμίζεται εδώ, σε πλατιά οθόνη ή κινητό. Τίποτα δεν αποθηκεύεται μέχρι να πατήσετε Αποθήκευση.", "Uppercase, spaced": "Κεφαλαία, αραιά", "Show the date on posts": "Εμφάνιση ημερομηνίας στις δημοσιεύσεις", "Show tags with a # in front": "Εμφάνιση των ετικετών με # μπροστά", diff --git a/internal/web/layout.go b/internal/web/layout.go index d201758..91728ed 100644 --- a/internal/web/layout.go +++ b/internal/web/layout.go @@ -130,12 +130,6 @@ type Layout struct { // A header search box sits in the menu row when there is one, so the two // header modules need to know about each other. HeaderMenu, HeaderSearch bool - // Fold says the header menu folds into a button (theme nav_fold, and a - // menu in the header); BurgerAt is the index in Header of the module that - // carries the button: the title or logo block just before the menu, so it - // sits at the right of the brand, else the menu bar itself. - Fold bool - BurgerAt int } // buildLayout groups modules by area, dropping areas the theme has switched off. @@ -162,18 +156,6 @@ func buildLayout(t Theme, mods []store.Module) Layout { l.Footer = append(l.Footer, m) } } - if t.NavFold { - for j, m := range l.Header { - if m.Kind != "menu" { - continue - } - l.Fold, l.BurgerAt = true, j - if j > 0 && (l.Header[j-1].Kind == "title" || l.Header[j-1].Kind == "logo" && t.Logo != "") { // a logo module without a logo renders nothing - l.BurgerAt = j - 1 - } - break - } - } l.HasLeft = t.KeepColumns || len(l.Left) > 0 l.HasRight = t.KeepColumns || len(l.Right) > 0 return l diff --git a/internal/web/static/blog.css b/internal/web/static/blog.css index b3b0312..7b91dbe 100644 --- a/internal/web/static/blog.css +++ b/internal/web/static/blog.css @@ -49,53 +49,6 @@ img { max-width: 100%; height: auto; } .nav-spread .site-header .nav-inner { text-align: justify; line-height: 0; } .nav-spread .site-header .nav-inner > a, .nav-spread .site-header .search-form { line-height: 1.5; } .nav-spread .site-header .nav-inner::after { content: ""; display: inline-block; width: 100%; } -/* menu fold (theme nav_fold): the header menu becomes a button when its links - do not fit. The hidden (offscreen, still focusable) checkbox before the - header's blocks is the open/closed state; the label is the button, at the - right of the title or logo block above the menu (.has-burger on that - block), or in the bar when nothing is above it. Which state applies: - .nav-folded is set by the page's script when a link wraps, .nav-auto is the - no-script fallback (folded on phones only) the script removes; the two - blocks below must stay identical. */ -.nav-toggle { position: absolute; left: -9999px; } -.nav-burger { display: none; cursor: pointer; font-weight: bold; font-size: 1.2em; line-height: 2em; padding: 0 0.5em; white-space: nowrap; } -.burger-icon .nb-text, .burger-text .nb-icon { display: none; } -.burger-both .nb-icon { margin-right: 0.3em; } -.nav-toggle:focus-visible ~ .has-burger .nav-burger { outline: 2px solid; } /* the keyboard's focus ring, on the button */ -.nav-folded .nav-burger { display: block; } -.nav-folded .has-burger { position: relative; padding-right: 3.6em; } -.nav-folded.header-center .has-burger { padding-left: 3.6em; } /* the brand stays centred */ -.nav-folded .has-burger > .nav-burger { position: absolute; right: 1em; top: 50%; margin-top: -1em; } -.nav-folded .site-nav.has-burger { padding-right: 0; } -.nav-folded .site-nav.has-burger .nav-inner { padding-left: 0; padding-right: 0; } /* the button keeps its place when the panel opens */ -.nav-folded .site-nav.has-burger .nav-inner > .nav-burger { display: inline-block; margin-left: 0.5em; } -.nav-folded .site-nav .nav-inner > a, .nav-folded .site-nav .search-form { display: none; } -.nav-folded .site-nav:not(.has-burger) { border-bottom: 0; } /* the bar is nothing until opened */ -.nav-folded .site-nav:not(.has-burger) .nav-inner { padding: 0; } -.nav-folded .nav-toggle:checked ~ .site-nav { border-bottom: 1px solid rgba(0,0,0,0.1); } -.nav-folded .nav-toggle:checked ~ .site-nav .nav-inner { padding: 0.3em 0; text-align: left; line-height: 1.5; } -.nav-folded .nav-toggle:checked ~ .site-nav .nav-inner > a { display: block; padding: 0.6em 1.2em; } -.nav-folded .nav-toggle:checked ~ .site-nav .nav-inner::after { display: none; } -.nav-folded .nav-toggle:checked ~ .site-nav .search-form { display: block; float: none; margin: 0.4em 1.2em; } -.nav-folded .nav-toggle:checked ~ .site-nav .search-form input { width: 100%; } -@media (max-width: 700px) { - .nav-auto .nav-burger { display: block; } - .nav-auto .has-burger { position: relative; padding-right: 3.6em; } - .nav-auto.header-center .has-burger { padding-left: 3.6em; } - .nav-auto .has-burger > .nav-burger { position: absolute; right: 1em; top: 50%; margin-top: -1em; } - .nav-auto .site-nav.has-burger { padding-right: 0; } - .nav-auto .site-nav.has-burger .nav-inner { padding-left: 0; padding-right: 0; } /* the button keeps its place when the panel opens */ - .nav-auto .site-nav.has-burger .nav-inner > .nav-burger { display: inline-block; margin-left: 0.5em; } - .nav-auto .site-nav .nav-inner > a, .nav-auto .site-nav .search-form { display: none; } - .nav-auto .site-nav:not(.has-burger) { border-bottom: 0; } - .nav-auto .site-nav:not(.has-burger) .nav-inner { padding: 0; } - .nav-auto .nav-toggle:checked ~ .site-nav { border-bottom: 1px solid rgba(0,0,0,0.1); } - .nav-auto .nav-toggle:checked ~ .site-nav .nav-inner { padding: 0.3em 0; text-align: left; line-height: 1.5; } - .nav-auto .nav-toggle:checked ~ .site-nav .nav-inner > a { display: block; padding: 0.6em 1.2em; } - .nav-auto .nav-toggle:checked ~ .site-nav .nav-inner::after { display: none; } - .nav-auto .nav-toggle:checked ~ .site-nav .search-form { display: block; float: none; margin: 0.4em 1.2em; } - .nav-auto .nav-toggle:checked ~ .site-nav .search-form input { width: 100%; } -} .body-wrap { padding: 1.5em 1em; } .content { padding: 1.5em 2em; border-radius: 6px; box-shadow: 0 1px 3px rgba(0,0,0,0.15); } .page-title { margin-top: 0; } diff --git a/internal/web/templates/dashboard/design.html b/internal/web/templates/dashboard/design.html index 039eabe..1af90c4 100644 --- a/internal/web/templates/dashboard/design.html +++ b/internal/web/templates/dashboard/design.html @@ -158,7 +158,7 @@
-

{{t "When the menu does not fit"}}

-
- - - -
-

{{t "The button sits at the right of the title or logo just above the menu, or in the menu bar itself when nothing is above it, and opens the links as a list. Readers whose browser runs no scripts get it on phones."}}

@@ -380,18 +369,11 @@ .then(function () { pvBusy = false; if (pvAgain) { pvAgain = false; preview(); } }); } function schedule() { clearTimeout(pvTimer); pvTimer = setTimeout(preview, 300); } - function fitFrame() { // the frame runs no scripts, so fold the menu the way the blog's own script does, and size the frame to the header - try { - var d = frame.contentDocument, h = d.querySelector(".site-header.nav-fold"), links = h ? h.querySelectorAll(".site-nav .nav-inner a") : []; - if (links.length) { - h.classList.remove("nav-auto"); h.classList.remove("nav-folded"); - for (var i = 1; i < links.length; i++) if (links[i].offsetTop !== links[0].offsetTop) { h.classList.add("nav-folded"); break; } - } - frame.style.height = d.body.scrollHeight + "px"; - } catch (e) {} + function fitFrame() { // the frame is as tall as the header + try { frame.style.height = frame.contentDocument.body.scrollHeight + "px"; } catch (e) {} } if (frame) { - frame.addEventListener("load", function () { fitFrame(); try { frame.contentDocument.addEventListener("change", fitFrame); } catch (e) {} }); // change: the fold button opened or closed the panel + frame.addEventListener("load", fitFrame); qa("[data-pv]").forEach(function (b) { b.addEventListener("click", function () { frame.classList.toggle("phone", b.getAttribute("data-pv") === "phone"); qa("[data-pv]").forEach(function (o) { o.setAttribute("aria-pressed", String(o === b)); }); diff --git a/internal/web/templates/layouts/blog.html b/internal/web/templates/layouts/blog.html index 71a62b0..99bb13a 100644 --- a/internal/web/templates/layouts/blog.html +++ b/internal/web/templates/layouts/blog.html @@ -40,36 +40,12 @@ {{end}} -{{/* The header: the banner, then its modules in order. With the menu folding - (Layout.Fold) a hidden checkbox comes first: it is the open/closed state, - so the burger label toggles the menu with no script and in old browsers - (`:checked ~` reaches every block after it). Folding itself is decided by - the script below — any link on a second line means the menu does not fit — - which drops nav-auto, the no-script fallback blog.css folds on phones. */}} -{{define "siteheader"}}{{$l := .Data.layout}}{{$t := .Data.theme}}{{end}} {{define "notices"}}{{if .}}
{{range .}}