From e8b88d4e72a928f5022ae8e0db54a133a119691b Mon Sep 17 00:00:00 2001 From: Aditya Telange <21258296+adityatelange@users.noreply.github.com> Date: Sat, 11 Apr 2026 17:56:08 +0530 Subject: [PATCH] Improve table of contents - Convert the `.toc` class to a `
` element - Update styles for improved accessibility and interaction --- assets/css/common/post-single.css | 54 +++++++---- layouts/partials/toc.html | 156 +++++++++++++++--------------- 2 files changed, 114 insertions(+), 96 deletions(-) diff --git a/assets/css/common/post-single.css b/assets/css/common/post-single.css index b21b9b0f..6b974b28 100644 --- a/assets/css/common/post-single.css +++ b/assets/css/common/post-single.css @@ -45,40 +45,60 @@ -webkit-box-decoration-break: clone; } -.toc { +details.toc { margin-bottom: var(--content-gap); - border: 1px solid var(--border); background: var(--code-bg); border-radius: var(--radius); - padding: 0.4em; + border: 1px solid var(--border); } -[data-theme="dark"] .toc { +[data-theme="dark"] details.toc { background: var(--entry); } -.toc details summary { - cursor: zoom-in; - margin-inline-start: 10px; +details.toc summary { + padding: 0.5rem 1.2rem; + border-radius: var(--radius); +} + +details summary { + cursor: pointer; + display: list-item; + width: 100%; + margin-inline-start: 0; user-select: none; } -.toc details[open] summary { - cursor: zoom-out; -} - -.toc .details { +details .title { display: inline; font-weight: 500; + margin-inline-start: 0.2rem; } -.toc .inner { - margin: 5px 20px; - padding: 0 10px; - opacity: 0.9; +details { + interpolate-size: allow-keywords; } -.toc li ul { +details::details-content { + height: 0; + opacity: 0; + overflow: clip; + transition: height 150ms ease, + opacity 150ms ease, + content-visibility 150ms allow-discrete; +} + +details[open]::details-content { + height: auto; + opacity: 1; +} + +details .inner { + margin: 0 2.4rem; + padding-bottom: 0.6rem; +} + +details li ul { margin-inline-start: var(--gap); } diff --git a/layouts/partials/toc.html b/layouts/partials/toc.html index 28f8694c..a4decf7c 100644 --- a/layouts/partials/toc.html +++ b/layouts/partials/toc.html @@ -1,97 +1,95 @@ {{- $headers := findRE "(.|\n])+?" .Content -}} {{- $has_headers := ge (len $headers) 1 -}} {{- if $has_headers -}} -
-
- - {{- i18n "toc" | default "Table of Contents" }} - +
+ + {{- i18n "toc" | default "Table of Contents" }} + -
- {{- if (.Param "UseHugoToc") }} - {{- .TableOfContents -}} - {{- else }} - {{- $largest := 6 -}} - {{- range $headers -}} - {{- $headerLevel := index (findRE "[1-6]" . 1) 0 -}} - {{- $headerLevel := len (seq $headerLevel) -}} - {{- if lt $headerLevel $largest -}} - {{- $largest = $headerLevel -}} - {{- end -}} - {{- end -}} +
+ {{- if (.Param "UseHugoToc") }} + {{- .TableOfContents -}} + {{- else }} + {{- $largest := 6 -}} + {{- range $headers -}} + {{- $headerLevel := index (findRE "[1-6]" . 1) 0 -}} + {{- $headerLevel := len (seq $headerLevel) -}} + {{- if lt $headerLevel $largest -}} + {{- $largest = $headerLevel -}} + {{- end -}} + {{- end -}} - {{- $firstHeaderLevel := len (seq (index (findRE "[1-6]" (index $headers 0) 1) 0)) -}} + {{- $firstHeaderLevel := len (seq (index (findRE "[1-6]" (index $headers 0) 1) 0)) -}} - {{- $.Scratch.Set "bareul" slice -}} + {{- $.Scratch.Set "bareul" slice -}} +
    + {{- range seq (sub $firstHeaderLevel $largest) -}}
      - {{- range seq (sub $firstHeaderLevel $largest) -}} + {{- $.Scratch.Add "bareul" (sub (add $largest .) 1) -}} + {{- end -}} + {{- range $i, $header := $headers -}} + {{- $headerLevel := index (findRE "[1-6]" . 1) 0 -}} + {{- $headerLevel := len (seq $headerLevel) -}} + + {{/* get id="xyz" */}} + {{- $id := index (findRE "(id=\"(.*?)\")" $header 9) 0 }} + + {{- /* strip id="" to leave xyz, no way to get regex capturing groups in hugo */ -}} + {{- $cleanedID := replace (replace $id "id=\"" "") "\"" "" }} + {{- $header := replaceRE "((.|\n])+?)" "$1" $header -}} + + {{- if ne $i 0 -}} + {{- $prevHeaderLevel := index (findRE "[1-6]" (index $headers (sub $i 1)) 1) 0 -}} + {{- $prevHeaderLevel := len (seq $prevHeaderLevel) -}} + {{- if gt $headerLevel $prevHeaderLevel -}} + {{- range seq $prevHeaderLevel (sub $headerLevel 1) -}}
        - {{- $.Scratch.Add "bareul" (sub (add $largest .) 1) -}} + {{/* the first should not be recorded */}} + {{- if ne $prevHeaderLevel . -}} + {{- $.Scratch.Add "bareul" . -}} {{- end -}} - {{- range $i, $header := $headers -}} - {{- $headerLevel := index (findRE "[1-6]" . 1) 0 -}} - {{- $headerLevel := len (seq $headerLevel) -}} - - {{/* get id="xyz" */}} - {{- $id := index (findRE "(id=\"(.*?)\")" $header 9) 0 }} - - {{- /* strip id="" to leave xyz, no way to get regex capturing groups in hugo */ -}} - {{- $cleanedID := replace (replace $id "id=\"" "") "\"" "" }} - {{- $header := replaceRE "((.|\n])+?)" "$1" $header -}} - - {{- if ne $i 0 -}} - {{- $prevHeaderLevel := index (findRE "[1-6]" (index $headers (sub $i 1)) 1) 0 -}} - {{- $prevHeaderLevel := len (seq $prevHeaderLevel) -}} - {{- if gt $headerLevel $prevHeaderLevel -}} - {{- range seq $prevHeaderLevel (sub $headerLevel 1) -}} -
          - {{/* the first should not be recorded */}} - {{- if ne $prevHeaderLevel . -}} - {{- $.Scratch.Add "bareul" . -}} - {{- end -}} - {{- end -}} - {{- else -}} - - {{- if lt $headerLevel $prevHeaderLevel -}} - {{- range seq (sub $prevHeaderLevel 1) -1 $headerLevel -}} - {{- if in ($.Scratch.Get "bareul") . -}} -
        - {{/* manually do pop item */}} - {{- $tmp := $.Scratch.Get "bareul" -}} - {{- $.Scratch.Delete "bareul" -}} - {{- $.Scratch.Set "bareul" slice}} - {{- range seq (sub (len $tmp) 1) -}} - {{- $.Scratch.Add "bareul" (index $tmp (sub . 1)) -}} {{- end -}} {{- else -}} + + {{- if lt $headerLevel $prevHeaderLevel -}} + {{- range seq (sub $prevHeaderLevel 1) -1 $headerLevel -}} + {{- if in ($.Scratch.Get "bareul") . -}}
      - + {{/* manually do pop item */}} + {{- $tmp := $.Scratch.Get "bareul" -}} + {{- $.Scratch.Delete "bareul" -}} + {{- $.Scratch.Set "bareul" slice}} + {{- range seq (sub (len $tmp) 1) -}} + {{- $.Scratch.Add "bareul" (index $tmp (sub . 1)) -}} {{- end -}} - {{- end -}} - {{- end -}} - {{- end }} -
    • - {{- $header | plainify | safeHTML -}} - {{- else }} -
    • - {{- $header | plainify | safeHTML -}} - {{- end -}} - {{- end -}} - - {{- $firstHeaderLevel := $largest }} - {{- $lastHeaderLevel := len (seq (index (findRE "[1-6]" (index $headers (sub (len $headers) 1)) 1) 0)) }} -
    • - {{- range seq (sub $lastHeaderLevel $firstHeaderLevel) -}} - {{- if in ($.Scratch.Get "bareul") (add . $firstHeaderLevel) }} -
    - {{- else }} + {{- else -}}
{{- end -}} + {{- end -}} + {{- end -}} {{- end }} - - {{- end }} -
-
-
+
  • + {{- $header | plainify | safeHTML -}} + {{- else }} +
  • + {{- $header | plainify | safeHTML -}} + {{- end -}} + {{- end -}} + + {{- $firstHeaderLevel := $largest }} + {{- $lastHeaderLevel := len (seq (index (findRE "[1-6]" (index $headers (sub (len $headers) 1)) 1) 0)) }} +
  • + {{- range seq (sub $lastHeaderLevel $firstHeaderLevel) -}} + {{- if in ($.Scratch.Get "bareul") (add . $firstHeaderLevel) }} + + {{- else }} + + + {{- end -}} + {{- end }} + + {{- end }} + +
    {{- end }}