diff --git a/site/layouts/partials/crumbs.html b/site/layouts/partials/crumbs.html
index ac212b9db..87b1d2ae9 100644
--- a/site/layouts/partials/crumbs.html
+++ b/site/layouts/partials/crumbs.html
@@ -1,7 +1,8 @@
-{{ range $index, $element := split .Permalink "/" }}
- {{- $.Scratch.Add "path" $element }}
+{{ $.Scratch.Set "path" "/" }}
+{{ range $index, $element := split .RelPermalink "/" }}
{{- if ne $element "" }}
+ {{- $.Scratch.Add "path" $element }}
-
{{- with $.Site.GetPage ( $.Scratch.Get "path") }}
{{ .Title }}
diff --git a/site/layouts/partials/tree.html b/site/layouts/partials/tree.html
index 6c00cd7c7..3a06f3d62 100644
--- a/site/layouts/partials/tree.html
+++ b/site/layouts/partials/tree.html
@@ -20,6 +20,15 @@
{{- $activeLink := $.root.Permalink }}
{{- $className := "" }}
{{- $deprecated := true }}
+ {{- $hasValidChildren := false }}
+ {{- $stat := os.Stat .path }}
+ {{- if $stat.IsDir }}
+ {{- range (readDir .path) }}
+ {{- if not (in .Name "image" | or (eq .Name "_index.md")) }}
+ {{- $hasValidChildren = true }}
+ {{- end }}
+ {{- end }}
+ {{- end }}
{{- with $.root.Site.GetPage .url }}
{{- if not .Params.deprecated }}
{{- $deprecated = false }}
@@ -30,11 +39,19 @@
{{- if eq $activeLink $branchLink }}
{{- $className = "tree-active tree-branch-active" -}}
{{- end -}}
-
-
+ {{- if $hasValidChildren }}
+
-
+
+ {{ .Title }}
+ {{- else }}
+ -
{{ .Title }}
+
+ {{- end }}
{{- end }}
{{- end }}
{{- if not $deprecated }}
+ {{- if $hasValidChildren }}
{{- range (readDir .path) }}
{{- if in .Name "image" | or (eq .Name "_index.md") }}
@@ -48,7 +65,7 @@
{{- else }}
{{- with $.root.Site.GetPage $fullUrl }}
{{- $link := printf "%s" .Permalink }}
- -
+
-
{{ .Title }}
{{- end }}
@@ -56,6 +73,8 @@
{{- end }}
{{- end }}
+
+ {{- end }}
{{- end }}
{{ end }}
\ No newline at end of file
diff --git a/src/css/components/_tree.scss b/src/css/components/_tree.scss
index b634d087f..c9e683482 100644
--- a/src/css/components/_tree.scss
+++ b/src/css/components/_tree.scss
@@ -1,43 +1,121 @@
-.tree-branch {
- display: none;
+.tree-menu {
+ position: sticky;
+ top: 20px;
+ max-height: calc(100vh - 40px);
+ overflow-y: auto;
+ padding-right: 8px; /* space for scrollbar */
+
+ &::-webkit-scrollbar {
+ width: 6px;
}
-
- .tree-branch-active {
-
- .tree-branch {
- display: block;
- }
+ &::-webkit-scrollbar-thumb {
+ background-color: rgba(0,0,0,0.2);
+ border-radius: 4px;
}
-
- .tree-active > a {
- font-weight: bold;
+
+ .tree-root {
+ padding: 0 0 0 5px; /* Align closer to the left edge of the search input */
+ margin-top: 16px; /* Add space between search input and the list */
}
-
- .tree-menu {
- ul {
- padding: 0 0 0 16px;
+
+ ul.tree-branch {
+ padding: 0 0 0 24px; /* Indent submenus further to the right */
+ }
+
+ ul {
+ margin: 0;
+ }
+
+ .tree-branch-item {
+ list-style: none !important; /* Hide native bullet if any */
+
+ &::before {
+ content: '' !important; /* Hide the blue dot generated by _type.scss */
+ display: none !important;
}
+ }
- @media (max-width:850px) {
- max-height: Min(30vh, 300px);
- border-radius: var(--radius);
- border: solid 4px #eee;
- overflow: auto;
- margin-bottom: 16px;
-
- input[name="filter"] {
- position: -webkit-sticky; /* Safari */
- position: sticky;
- width: 100%;
- top: 0;
+ li {
+ margin: 2px 0; /* Slight gap */
+ }
+
+ details {
+ & > summary {
+ list-style: none;
+ cursor: pointer;
+ display: flex;
+ align-items: flex-start;
+ padding: 2px 0;
+
+ &::-webkit-details-marker {
+ display: none;
}
- ul {
- padding: 0 0 0 30px;
+ &::before {
+ content: "";
+ display: inline-block;
+ flex-shrink: 0;
+ width: 14px;
+ height: 14px;
+ margin-right: 6px;
+ margin-top: 4px;
+ /* Chevron Right icon */
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='9 18 15 12 9 6'%3E%3C/polyline%3E%3C/svg%3E");
+ background-size: contain;
+ background-repeat: no-repeat;
+ background-position: center;
+ transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+ opacity: 0.6;
}
}
+
+ &[open] > summary::before {
+ transform: rotate(90deg); /* Rotate down */
+ }
}
-
+
+ details[open] summary ~ ul {
+ animation: tree-sweep 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+ }
+
+ .tree-active {
+ & > a {
+ font-weight: bold;
+ color: var(--blue-dark);
+ }
+
+ & > details > summary {
+ font-weight: bold;
+ color: var(--blue-dark);
+ }
+ }
+
+ @media (max-width: 850px) {
+ max-height: Min(30vh, 300px);
+ border-radius: var(--radius);
+ border: solid 4px #eee;
+ overflow: auto;
+ margin-bottom: 16px;
+
+ input[name="filter"] {
+ position: -webkit-sticky; /* Safari */
+ position: sticky;
+ width: 100%;
+ top: 0;
+ z-index: 10;
+ }
+
+ ul {
+ padding: 0 0 0 16px;
+ }
+ }
+}
+
+@keyframes tree-sweep {
+ 0% { opacity: 0; transform: translateY(-5px); }
+ 100% { opacity: 1; transform: translateY(0); }
+}
+
.is-filtering {
li {
display: none;
@@ -49,7 +127,5 @@
.tree-filter-match{
display: block;
- > a {
- }
}
}
\ No newline at end of file
diff --git a/src/index.js b/src/index.js
index c8afc1f74..635654652 100644
--- a/src/index.js
+++ b/src/index.js
@@ -144,6 +144,13 @@ document.addEventListener("DOMContentLoaded", function() {
Array.from(menu.getElementsByTagName('ul')).map(function(el) {
el.classList.remove("tree-branch-filter");
});
+ Array.from(menu.getElementsByTagName('details')).map(function(el) {
+ if (el.parentElement.classList.contains('tree-branch-active')) {
+ el.setAttribute('open', '');
+ } else {
+ el.removeAttribute('open');
+ }
+ });
}
function applyFilter(menu, filter) {
@@ -152,6 +159,13 @@ document.addEventListener("DOMContentLoaded", function() {
const text = el.textContent.toLowerCase();
if (text.indexOf(filter) !== -1) {
el.classList.add("tree-filter-match");
+ let parent = el.parentElement;
+ while (parent && parent !== menu) {
+ if (parent.tagName.toLowerCase() === 'details') {
+ parent.setAttribute('open', '');
+ }
+ parent = parent.parentElement;
+ }
} else {
el.classList.remove("tree-filter-match");
}
@@ -227,4 +241,25 @@ document.addEventListener("DOMContentLoaded", function() {
.forEach(tr => tr.style.display = input.checked ? '' : 'none');
})));
+ // Auto-collapse siblings in tree menu
+ const treeMenus = document.querySelectorAll('.tree-menu');
+ treeMenus.forEach(menu => {
+ menu.addEventListener('click', (e) => {
+ const summary = e.target.closest('summary');
+ if (summary) {
+ const details = summary.parentElement;
+ if (!details.hasAttribute('open')) {
+ const ul = details.parentElement.parentElement;
+ if (ul) {
+ ul.querySelectorAll(':scope > li > details').forEach(sibling => {
+ if (sibling !== details) {
+ sibling.removeAttribute('open');
+ }
+ });
+ }
+ }
+ }
+ });
+ });
+
});
\ No newline at end of file