Hide App navigation on a narrow screen until the user opens it.

A width at or below Nextcloud's 1024px breakpoint keeps the tree off the page so the content stays usable, and the navigation button brings it back.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-29 18:56:44 +02:00
co-authored by Cursor
parent 4e05fb1c6a
commit fad9806585
5 changed files with 162 additions and 5 deletions
+67
View File
@@ -8,6 +8,9 @@ import (
"strings"
"testing"
"github.com/chromedp/chromedp"
"github.com/chromedp/chromedp/kb"
"gitea.neitzel.de/konrad/go-nc-exapp"
)
@@ -201,3 +204,67 @@ func TestAppNavigationHeaderPrecedesTree(t *testing.T) {
t.Fatalf("header %d tree %d in %s", header, tree, body)
}
}
func TestAppNavigationOffersNarrowScreenToggle(t *testing.T) {
body := navBody(t, "/")
for _, need := range []string{
`<meta name="viewport" content="width=device-width, initial-scale=1">`,
`id="nav-toggle"`,
`aria-controls="app-navigation"`,
`aria-expanded="false"`,
`aria-label="Open navigation"`,
`id="nav-backdrop"`,
`id="app-navigation"`,
`max-width: 1024px`,
} {
if !strings.Contains(body, need) {
t.Errorf("missing %s", need)
}
}
}
// navLayoutJS reports how App navigation is laid out: "wide", "closed", or "open".
const navLayoutJS = `(() => {
const nav = document.querySelector("nav.app-navigation");
const btn = document.getElementById("nav-toggle");
const narrow = window.matchMedia("(max-width: 1024px)").matches;
const box = nav.getBoundingClientRect();
const navShown = getComputedStyle(nav).display !== "none" && box.width > 0 && box.left < window.innerWidth && box.right > 0;
const btnShown = getComputedStyle(btn).display !== "none";
const expanded = btn.getAttribute("aria-expanded") === "true";
if (!narrow && navShown && !btnShown && !expanded) return "wide";
if (narrow && !navShown && btnShown && !expanded) return "closed";
if (narrow && navShown && btnShown && expanded) return "open";
return "narrow=" + narrow + " nav=" + navShown + " btn=" + btnShown + " expanded=" + expanded + " width=" + window.innerWidth;
})()`
func TestAppNavigationWideScreenKeepsTheTreeVisible(t *testing.T) {
drive(t, "/nav",
chromedp.EmulateViewport(1280, 800),
waitJS(navLayoutJS, "wide", false),
)
}
func TestAppNavigationNarrowScreenOpensTheTreeOnDemand(t *testing.T) {
drive(t, "/nav",
chromedp.EmulateViewport(390, 800),
waitJS(navLayoutJS, "closed", false),
chromedp.Click("#nav-toggle", chromedp.ByQuery),
waitJS(navLayoutJS, "open", false),
chromedp.Click("#nav-toggle", chromedp.ByQuery),
waitJS(navLayoutJS, "closed", false),
chromedp.Click("#nav-toggle", chromedp.ByQuery),
waitJS(navLayoutJS, "open", false),
chromedp.MouseClickXY(370, 400),
waitJS(navLayoutJS, "closed", false),
chromedp.Click("#nav-toggle", chromedp.ByQuery),
waitJS(navLayoutJS, "open", false),
chromedp.KeyEvent(kb.Escape),
waitJS(navLayoutJS, "closed", false),
chromedp.Click("#nav-toggle", chromedp.ByQuery),
waitJS(navLayoutJS, "open", false),
chromedp.Click(`a.app-navigation-entry-link[href*="item=keys"]`, chromedp.ByQuery),
waitJS(`document.querySelector("main").textContent`, "keys-page", true),
waitJS(navLayoutJS, "closed", false),
)
}