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:
+92
-3
@@ -170,6 +170,7 @@ var shellTmpl = template.Must(template.New("shell").Parse(`<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{{.Title}}</title>
|
||||
{{if .Theme}}
|
||||
<link rel="stylesheet" href="/apps/theming/css/default.css">
|
||||
@@ -219,7 +220,32 @@ var shellTmpl = template.Must(template.New("shell").Parse(`<!DOCTYPE html>
|
||||
}
|
||||
body { margin: 0; font: 15px/1.4 var(--font-face, system-ui, sans-serif); }
|
||||
#app-nav { display: flex; flex-direction: column; min-height: 100vh; background: transparent; }
|
||||
#nav-header { padding: 8px 12px; border-bottom: 1px solid var(--color-border); }
|
||||
#nav-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 8px 12px;
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
}
|
||||
#nav-header-text { flex: 1; min-width: 0; }
|
||||
#nav-toggle {
|
||||
display: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
flex: none;
|
||||
background: transparent;
|
||||
color: inherit;
|
||||
cursor: pointer;
|
||||
border-radius: var(--border-radius-element);
|
||||
}
|
||||
#nav-toggle:hover { background: var(--color-background-hover); }
|
||||
#nav-toggle svg { width: 20px; height: 20px; }
|
||||
#nav-backdrop { display: none; }
|
||||
#app-nav-body { display: flex; flex: 1; min-height: 0; }
|
||||
nav.app-navigation {
|
||||
width: var(--navigation-width, 300px);
|
||||
@@ -294,14 +320,47 @@ var shellTmpl = template.Must(template.New("shell").Parse(`<!DOCTYPE html>
|
||||
li[data-expanded="false"] > .app-navigation-entry__children { display: none; }
|
||||
li[data-expanded="false"] button.fold svg { transform: rotate(-90deg); }
|
||||
#nav-missing { margin: 0 0 1rem; }
|
||||
@media (max-width: 1024px) {
|
||||
#nav-header {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 2100;
|
||||
background-color: var(--color-main-background);
|
||||
}
|
||||
#nav-toggle { display: flex; }
|
||||
nav.app-navigation {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 2000;
|
||||
top: var(--nav-header-offset, 0px);
|
||||
bottom: 0;
|
||||
inset-inline-start: 0;
|
||||
width: min(var(--navigation-width, 300px), 85vw);
|
||||
}
|
||||
body.nav-open nav.app-navigation { display: block; }
|
||||
body.nav-open #nav-backdrop {
|
||||
display: block;
|
||||
position: fixed;
|
||||
z-index: 1990;
|
||||
top: var(--nav-header-offset, 0px);
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background: rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body data-selected="{{.Selected}}" data-address="{{.Address}}">
|
||||
{{.Dialog}}
|
||||
<div id="app-nav">
|
||||
<div id="nav-header">{{.Header}}</div>
|
||||
<div id="nav-header">
|
||||
<button type="button" id="nav-toggle" aria-controls="app-navigation" aria-expanded="false" aria-label="Open navigation"><svg viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2z"/></svg></button>
|
||||
<div id="nav-header-text">{{.Header}}</div>
|
||||
</div>
|
||||
<div id="nav-backdrop"></div>
|
||||
<div id="app-nav-body">
|
||||
<nav class="app-navigation" aria-label="App navigation">
|
||||
<nav id="app-navigation" class="app-navigation" aria-label="App navigation">
|
||||
<ul class="app-navigation-list">{{template "items" .Items}}</ul>
|
||||
</nav>
|
||||
<main>
|
||||
@@ -325,6 +384,36 @@ var shellTmpl = template.Must(template.New("shell").Parse(`<!DOCTYPE html>
|
||||
btn.setAttribute("aria-expanded", open ? "false" : "true");
|
||||
});
|
||||
});
|
||||
var toggle = document.getElementById("nav-toggle");
|
||||
var backdrop = document.getElementById("nav-backdrop");
|
||||
function placeNav() {
|
||||
var header = document.getElementById("nav-header");
|
||||
if (!header) return;
|
||||
document.documentElement.style.setProperty("--nav-header-offset", header.offsetHeight + "px");
|
||||
}
|
||||
function setNavOpen(open) {
|
||||
placeNav();
|
||||
document.body.classList.toggle("nav-open", open);
|
||||
if (!toggle) return;
|
||||
toggle.setAttribute("aria-expanded", open ? "true" : "false");
|
||||
toggle.setAttribute("aria-label", open ? "Close navigation" : "Open navigation");
|
||||
}
|
||||
placeNav();
|
||||
window.addEventListener("resize", placeNav);
|
||||
var narrow = window.matchMedia("(max-width: 1024px)");
|
||||
if (narrow.addEventListener) narrow.addEventListener("change", placeNav);
|
||||
if (toggle) {
|
||||
toggle.addEventListener("click", function () {
|
||||
setNavOpen(!document.body.classList.contains("nav-open"));
|
||||
});
|
||||
}
|
||||
if (backdrop) backdrop.addEventListener("click", function () { setNavOpen(false); });
|
||||
document.addEventListener("keydown", function (e) {
|
||||
if (e.key !== "Escape") return;
|
||||
var dialog = document.getElementById("exapp-dialog");
|
||||
if (dialog && dialog.open) return;
|
||||
setNavOpen(false);
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user