feat: implement collapsible sidebar

chore: basic sidebar toggle button
chore: update compiled css
This commit is contained in:
Xin 2023-08-20 00:42:46 +01:00
parent 1c7962494d
commit 15d3a4da5e
7 changed files with 163 additions and 32 deletions

View File

@ -265,11 +265,11 @@
margin-top: 0.5rem;
margin-bottom: 0.5rem;
}
.content .not-prose ul, .content ol {
.content .not-prose ul, .content .not-prose ol {
margin: 0px;
list-style-type: none;
}
.content .not-prose ul li, .content ol li {
.content .not-prose ul li, .content .not-prose ol li {
margin: 0px;
}
.content kbd {
@ -290,6 +290,32 @@
border-color: rgb(255 255 255 / 0.1);
background-color: rgb(255 255 255 / 0.1);
}
.content pre:not(.code-block pre).mermaid {
border-radius: 0px;
background-color: transparent;
}
:is(html[class~="dark"] .content pre:not(.code-block pre).mermaid) {
background-color: transparent;
}
.content img {
margin-left: auto;
margin-right: auto;
margin-top: 1rem;
margin-bottom: 1rem;
border-radius: 0.375rem;
}
.content figure figcaption {
margin-top: 0.5rem;
display: block;
text-align: center;
font-size: .875rem;
--tw-text-opacity: 1;
color: rgb(107 114 128 / var(--tw-text-opacity));
}
:is(html[class~="dark"] .content figure figcaption) {
--tw-text-opacity: 1;
color: rgb(156 163 175 / var(--tw-text-opacity));
}
.subheading-anchor {
opacity: 0;
@ -1119,8 +1145,9 @@ article details > summary::before {
padding-bottom: 1rem;
}
.chroma .lnt,
.chroma .ln {
.chroma .ln,
.chroma .lnt:not(.hl > .lnt),
.chroma .hl {
min-width: 2.6rem;
padding-left: 1rem;
padding-right: 1rem;
@ -1128,8 +1155,9 @@ article details > summary::before {
color: rgb(82 82 82 / var(--tw-text-opacity));
}
:is(html[class~="dark"] .chroma .lnt),:is(html[class~="dark"]
.chroma .ln) {
:is(html[class~="dark"] .chroma .ln),:is(html[class~="dark"]
.chroma .lnt:not(.hl > .lnt)),:is(html[class~="dark"]
.chroma .hl) {
--tw-text-opacity: 1;
color: rgb(212 212 212 / var(--tw-text-opacity));
}
@ -1378,6 +1406,19 @@ article details > summary::before {
}
}
.sidebar-container li > div {
height: 0px;
}
.sidebar-container li.open > div {
height: auto;
}
.sidebar-container li.open > a > span > svg > path {
--tw-rotate: 90deg;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
nav .search-wrapper {
display: none;
}
@ -2177,6 +2218,10 @@ video {
height: 1.75rem;
}
.h-\[18px\] {
height: 18px;
}
.h-full {
height: 100%;
}
@ -2237,6 +2282,10 @@ video {
min-width: 0px;
}
.min-w-\[18px\] {
min-width: 18px;
}
.min-w-\[24px\] {
min-width: 24px;
}
@ -2269,6 +2318,10 @@ video {
flex-grow: 1;
}
.origin-center {
transform-origin: center;
}
.cursor-default {
cursor: default;
}
@ -2391,6 +2444,10 @@ video {
border-radius: 0.375rem;
}
.rounded-sm {
border-radius: 0.125rem;
}
.rounded-xl {
border-radius: 0.75rem;
}
@ -2500,6 +2557,14 @@ video {
background-color: rgb(254 252 232 / var(--tw-bg-opacity));
}
.p-0 {
padding: 0px;
}
.p-0\.5 {
padding: 0.125rem;
}
.p-1 {
padding: 0.25rem;
}
@ -2640,6 +2705,10 @@ video {
text-align: center;
}
.align-text-bottom {
vertical-align: text-bottom;
}
.font-mono {
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}
@ -2880,10 +2949,20 @@ video {
transition-duration: 150ms;
}
.transition-transform {
transition-property: transform;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
.duration-200 {
transition-duration: 200ms;
}
.ease-in-out {
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
.\[-webkit-tap-highlight-color\:transparent\] {
-webkit-tap-highlight-color: transparent;
}
@ -3000,6 +3079,10 @@ body {
background-color: rgb(243 244 246 / var(--tw-bg-opacity));
}
.hover\:bg-gray-800\/5:hover {
background-color: rgb(31 41 55 / 0.05);
}
.hover\:bg-primary-50:hover {
--tw-bg-opacity: 1;
background-color: hsl(var(--primary-hue) 100% 97% / var(--tw-bg-opacity));
@ -3221,6 +3304,11 @@ body {
margin-right: auto;
}
:is([dir="rtl"] .rtl\:-rotate-180) {
--tw-rotate: -180deg;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
:is([dir="rtl"] .rtl\:pl-2) {
padding-left: 0.5rem;
}
@ -3503,6 +3591,10 @@ body {
border-color: rgb(38 38 38 / var(--tw-border-opacity));
}
:is(html[class~="dark"] .dark\:hover\:bg-gray-100\/5:hover) {
background-color: rgb(243 244 246 / 0.05);
}
:is(html[class~="dark"] .dark\:hover\:bg-neutral-900:hover) {
--tw-bg-opacity: 1;
background-color: rgb(23 23 23 / var(--tw-bg-opacity));

View File

@ -7,3 +7,15 @@
backface-visibility: hidden;
}
}
.sidebar-container {
li > div {
@apply h-0;
}
li.open > div {
@apply h-auto;
}
li.open > a > span > svg > path {
@apply rotate-90;
}
}

12
assets/js/sidebar.js Normal file
View File

@ -0,0 +1,12 @@
document.addEventListener("DOMContentLoaded", function () {
const buttons = document.querySelectorAll(".hextra-sidebar-collapsible-button");
buttons.forEach(function (button) {
button.addEventListener("click", function (e) {
e.preventDefault();
const list = button.parentElement.parentElement;
if (list) {
list.classList.toggle("open")
}
});
});
});

View File

@ -1,6 +1,8 @@
---
title: Guide
weight: 2
sidebar:
open: true
---
Guide to using Hextra to build your site.

View File

@ -162,6 +162,7 @@
"dark:border-yellow-200/30",
"dark:contrast-more:border-neutral-400",
"dark:focus:bg-dark",
"dark:hover:bg-gray-100/5",
"dark:hover:bg-neutral-900",
"dark:hover:bg-primary-100/5",
"dark:hover:border-neutral-700",
@ -197,6 +198,7 @@
"data-[state=selected]:text-primary-600",
"decoration-from-font",
"duration-200",
"ease-in-out",
"filename",
"first:mt-0",
"flex",
@ -228,6 +230,7 @@
"h-4",
"h-5",
"h-7",
"h-[18px]",
"h-full",
"hamburger-menu",
"hextra-card",
@ -235,10 +238,12 @@
"hextra-filetree",
"hextra-filetree-folder",
"hextra-footer",
"hextra-sidebar-collapsible-button",
"hextra-toc",
"hidden",
"highlight",
"hover:bg-gray-100",
"hover:bg-gray-800/5",
"hover:bg-primary-50",
"hover:bg-slate-50",
"hover:border-gray-200",
@ -330,6 +335,7 @@
"min-h-[calc(100vh-4rem)]",
"min-h-[calc(100vh-var(--navbar-height))]",
"min-w-0",
"min-w-[18px]",
"min-w-[24px]",
"min-w-full",
"ml-1",
@ -358,12 +364,14 @@
"opacity-80",
"open",
"order-last",
"origin-center",
"overflow-auto",
"overflow-hidden",
"overflow-x-auto",
"overflow-x-hidden",
"overflow-y-auto",
"overscroll-contain",
"p-0.5",
"p-1.5",
"p-2",
"p-4",
@ -403,9 +411,11 @@
"rounded",
"rounded-lg",
"rounded-md",
"rounded-sm",
"rounded-t",
"rounded-xl",
"rtl:-ml-4",
"rtl:-rotate-180",
"rtl:before:right-0",
"rtl:left-1.5",
"rtl:left-3",
@ -481,6 +491,7 @@
"transition-all",
"transition-colors",
"transition-opacity",
"transition-transform",
"typesetting-article",
"underline",
"underline-offset-2",

View File

@ -4,8 +4,9 @@
{{- $jsLang := resources.Get "js/lang.js" -}}
{{- $jsCodeCopy := resources.Get "js/code-copy.js" -}}
{{- $jsFileTree := resources.Get "js/filetree.js" -}}
{{- $jsSidebar := resources.Get "js/sidebar.js" -}}
{{- $scripts := slice $jsTheme $jsMenu $jsCodeCopy $jsTabs $jsLang $jsFileTree | resources.Concat "js/main.js" -}}
{{- $scripts := slice $jsTheme $jsMenu $jsCodeCopy $jsTabs $jsLang $jsFileTree $jsSidebar | resources.Concat "js/main.js" -}}
{{- if hugo.IsProduction -}}
{{- $scripts = $scripts | minify | fingerprint -}}
{{- end -}}

View File

@ -21,7 +21,7 @@
{{- end -}}
{{- end -}}
{{ template "sidebar-separator" -}}
{{ template "sidebar-main" (dict "context" $navRoot "pageURL" $pageURL "toc" true) -}}
{{ template "sidebar-main" (dict "context" $navRoot "pageURL" $pageURL "page" $context "toc" true) -}}
<!-- Sidebar footer -->
@ -37,7 +37,7 @@
{{ .context.Scratch.Set "enableFooterSwitches" true }}
{{- else -}}
<ul class="flex flex-col gap-1 max-md:hidden">
{{ template "sidebar-main" (dict "context" $navRoot "pageURL" $pageURL) }}
{{ template "sidebar-main" (dict "context" $navRoot "page" $context "pageURL" $pageURL) }}
{{ template "sidebar-footer" }}
</ul>
{{ end -}}
@ -57,7 +57,7 @@
</aside>
{{- define "sidebar-main" -}}
{{ template "sidebar-tree" (dict "context" .context "level" 0 "pageURL" .pageURL "toc" (.toc | default false)) }}
{{ template "sidebar-tree" (dict "context" .context "level" 0 "page" .page "pageURL" .pageURL "toc" (.toc | default false)) }}
{{- end -}}
{{- define "sidebar-tree" -}}
@ -66,35 +66,37 @@
{{- end -}}
{{- $context := .context -}}
{{- $pageURL := .pageURL -}}
{{- $page := .page }}
{{- $pageURL := .page.RelPermalink -}}
{{- $level := .level -}}
{{- $toc := .toc | default false -}}
{{- $items := union .context.RegularPages .context.Sections -}}
{{- with $items -}}
{{- with $items := union .context.RegularPages .context.Sections -}}
{{- if eq $level 0 -}}
{{- range $items.ByWeight }}
{{- $active := eq $pageURL .RelPermalink -}}
<li class="open">
{{- $shouldOpen := or (.Params.sidebar.open) (.IsAncestor $page) $active | default true }}
<li class="{{ if $shouldOpen }}open{{ end }}">
{{- template "sidebar-item-link" dict "context" . "active" $active "title" .LinkTitle "link" .RelPermalink -}}
{{- if and $toc $active -}}
{{- template "sidebar-toc" dict "page" . -}}
{{- end -}}
{{- template "sidebar-tree" dict "context" . "pageURL" $pageURL "level" (add $level 1) "toc" $toc -}}
{{- template "sidebar-tree" dict "context" . "page" $page "pageURL" $pageURL "level" (add $level 1) "toc" $toc -}}
</li>
{{- end -}}
{{- else -}}
<div class="pt-1 ltr:pr-0">
<div class="pt-1 ltr:pr-0 overflow-hidden transition-all ease-in-out duration-200">
<ul class='relative flex flex-col gap-1 before:absolute before:inset-y-1 before:w-px before:bg-gray-200 before:content-[""] ltr:ml-3 ltr:pl-3 ltr:before:left-0 rtl:mr-3 rtl:pr-3 rtl:before:right-0 dark:before:bg-neutral-800'>
{{- range $items.ByWeight }}
{{- $active := eq $pageURL .RelPermalink -}}
{{- $shouldOpen := or (.Params.sidebar.open) (.IsAncestor $page) $active | default true }}
{{- $title := .LinkTitle | default .File.BaseFileName -}}
<li class="flex flex-col gap-1">
<li class="flex flex-col gap-1 {{ if $shouldOpen }}open{{ end }}">
{{- template "sidebar-item-link" dict "context" . "active" $active "title" $title "link" .RelPermalink -}}
{{- if and $toc $active -}}
{{ template "sidebar-toc" dict "page" . }}
{{- end }}
{{ template "sidebar-tree" dict "context" . "pageURL" $pageURL "level" (add $level 1) "toc" $toc }}
{{ template "sidebar-tree" dict "context" . "page" $page "pageURL" $pageURL "level" (add $level 1) "toc" $toc }}
</li>
{{- end -}}
</ul>
@ -137,21 +139,9 @@
{{- end -}}
{{- end -}}
{{- define "sidebar-item" }}
{{- $active := eq .pageURL .item.RelPermalink -}}
{{- $title := .item.LinkTitle | default .item.File.BaseFileName -}}
{{- $link := .item.RelPermalink -}}
{{- $toc := .toc | default false -}}
<li class="open">
{{ template "sidebar-item-link" dict "active" $active "title" $title "link" $link }}
{{ if and $toc $active }}
{{ template "sidebar-toc" dict "page" .item }}
{{ end }}
</li>
{{- end -}}
{{- define "sidebar-item-link" -}}
{{ $external := strings.HasPrefix .link "http" }}
{{- $external := strings.HasPrefix .link "http" -}}
{{- $open := .open | default true -}}
<a
class="flex items-center justify-between gap-2 cursor-pointer rounded px-2 py-1.5 text-sm transition-colors [-webkit-tap-highlight-color:transparent] [-webkit-touch-callout:none] [word-break:break-word]
{{- if .active }}
@ -163,9 +153,20 @@
{{ if $external }}target="_blank" rel="noreferer"{{ end }}
>
{{- .title -}}
{{- with .context }}
{{- if or .RegularPages .Sections }}
<span class="hextra-sidebar-collapsible-button">
{{- template "sidebear-collapsible-button" -}}
</span>
{{- end }}
{{ end -}}
</a>
{{- end -}}
{{- define "sidebar-separator" -}}
<div class="mt-4 border-t py-4 dark:border-neutral-800 contrast-more:border-neutral-400 dark:contrast-more:border-neutral-400" />
{{- end -}}
{{- define "sidebear-collapsible-button" -}}
<svg fill="none" viewBox="0 0 24 24" stroke="currentColor" class="h-[18px] min-w-[18px] rounded-sm p-0.5 hover:bg-gray-800/5 dark:hover:bg-gray-100/5"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" class="origin-center transition-transform rtl:-rotate-180"></path></svg>
{{- end -}}