From 15d3a4da5ecd5f0f67ad807af635eb959a6d83ce Mon Sep 17 00:00:00 2001 From: Xin Date: Sun, 20 Aug 2023 00:42:46 +0100 Subject: [PATCH] feat: implement collapsible sidebar chore: basic sidebar toggle button chore: update compiled css --- assets/css/compiled/main.css | 104 +++++++++++++++++++++-- assets/css/components/sidebar.css | 12 +++ assets/js/sidebar.js | 12 +++ exampleSite/content/docs/guide/_index.md | 2 + exampleSite/hugo_stats.json | 11 +++ layouts/partials/scripts.html | 3 +- layouts/partials/sidebar.html | 51 +++++------ 7 files changed, 163 insertions(+), 32 deletions(-) create mode 100644 assets/js/sidebar.js diff --git a/assets/css/compiled/main.css b/assets/css/compiled/main.css index c0293a4..e296fde 100644 --- a/assets/css/compiled/main.css +++ b/assets/css/compiled/main.css @@ -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)); diff --git a/assets/css/components/sidebar.css b/assets/css/components/sidebar.css index 5495018..af5da35 100644 --- a/assets/css/components/sidebar.css +++ b/assets/css/components/sidebar.css @@ -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; + } +} diff --git a/assets/js/sidebar.js b/assets/js/sidebar.js new file mode 100644 index 0000000..3b10eb4 --- /dev/null +++ b/assets/js/sidebar.js @@ -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") + } + }); + }); +}); diff --git a/exampleSite/content/docs/guide/_index.md b/exampleSite/content/docs/guide/_index.md index 41a7af5..76cb7f4 100644 --- a/exampleSite/content/docs/guide/_index.md +++ b/exampleSite/content/docs/guide/_index.md @@ -1,6 +1,8 @@ --- title: Guide weight: 2 +sidebar: + open: true --- Guide to using Hextra to build your site. diff --git a/exampleSite/hugo_stats.json b/exampleSite/hugo_stats.json index 6a33fce..3df6ec5 100644 --- a/exampleSite/hugo_stats.json +++ b/exampleSite/hugo_stats.json @@ -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", diff --git a/layouts/partials/scripts.html b/layouts/partials/scripts.html index ea523bf..6cacaca 100644 --- a/layouts/partials/scripts.html +++ b/layouts/partials/scripts.html @@ -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 -}} diff --git a/layouts/partials/sidebar.html b/layouts/partials/sidebar.html index 80a8e94..ca42ffe 100644 --- a/layouts/partials/sidebar.html +++ b/layouts/partials/sidebar.html @@ -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) -}} @@ -37,7 +37,7 @@ {{ .context.Scratch.Set "enableFooterSwitches" true }} {{- else -}} {{ end -}} @@ -57,7 +57,7 @@ {{- 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 -}} -
  • + {{- $shouldOpen := or (.Params.sidebar.open) (.IsAncestor $page) $active | default true }} +
  • {{- 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 -}}
  • {{- end -}} {{- else -}} -
    +
      {{- range $items.ByWeight }} {{- $active := eq $pageURL .RelPermalink -}} + {{- $shouldOpen := or (.Params.sidebar.open) (.IsAncestor $page) $active | default true }} {{- $title := .LinkTitle | default .File.BaseFileName -}} -
    • +
    • {{- 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 }}
    • {{- end -}}
    @@ -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 -}} -
  • - {{ template "sidebar-item-link" dict "active" $active "title" $title "link" $link }} - {{ if and $toc $active }} - {{ template "sidebar-toc" dict "page" .item }} - {{ end }} -
  • -{{- end -}} - {{- define "sidebar-item-link" -}} - {{ $external := strings.HasPrefix .link "http" }} + {{- $external := strings.HasPrefix .link "http" -}} + {{- $open := .open | default true -}} {{- .title -}} + {{- with .context }} + {{- if or .RegularPages .Sections }} + + {{- template "sidebear-collapsible-button" -}} + + {{- end }} + {{ end -}} {{- end -}} {{- define "sidebar-separator" -}}
    {{- end -}} + +{{- define "sidebear-collapsible-button" -}} + +{{- end -}}