Skip to content

Commit eb04157

Browse files
committed
WIP: Add related contents
Signed-off-by: Khusika Dhamar Gusti <[email protected]>
1 parent 3058c3b commit eb04157

File tree

3 files changed

+163
-3
lines changed

3 files changed

+163
-3
lines changed

assets/css/_page/_single.scss

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,70 @@
11
@import "../_partial/_single/toc";
22

3+
/* Add styles for the new Related Posts panel, matching the TOC */
4+
.related {
5+
position: absolute;
6+
padding: .5rem .5rem .5rem 1rem;
7+
width: 240px;
8+
visibility: hidden;
9+
border-left: 2px solid $global-link-color; // Increase border width to match TOC
10+
11+
.related-title {
12+
margin-bottom: .5rem;
13+
font-size: 1.1rem;
14+
font-weight: bold;
15+
text-transform: uppercase;
16+
}
17+
18+
.related-content {
19+
max-height: calc(100vh - 205px);
20+
overflow: auto;
21+
22+
ul {
23+
list-style: none;
24+
padding: 0;
25+
margin: 0;
26+
}
27+
28+
li {
29+
position: relative;
30+
padding-left: 1rem;
31+
}
32+
33+
li::before {
34+
content: '|';
35+
position: absolute;
36+
left: 0;
37+
top: 0.1rem;
38+
color: $global-link-color;
39+
font-weight: 700; // Adjust font-weight to match TOC (from 900 to 700)
40+
}
41+
42+
a {
43+
display: block;
44+
padding: .2rem 0;
45+
border-bottom: 1px solid transparent;
46+
@include link(false, false);
47+
}
48+
}
49+
}
50+
51+
/* Style for the inline "details" version to match the inline TOC */
52+
.details.related {
53+
.details-summary {
54+
cursor: pointer;
55+
.details-icon {
56+
transform: rotate(0deg);
57+
transition: transform .3s;
58+
}
59+
&.open .details-icon {
60+
transform: rotate(90deg);
61+
}
62+
}
63+
.details-content.related-content {
64+
padding: .5rem 0;
65+
}
66+
}
67+
368
.single-card {
469
padding: 3rem;
570
margin: 1rem 0 0;

assets/js/theme.js

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,62 @@ class Theme {
393393
}
394394
}
395395

396+
initRelated() {
397+
const $relatedStatic = document.getElementById('related-static');
398+
if (!$relatedStatic) return;
399+
400+
if (this.util.isTocStatic() || $relatedStatic.getAttribute('data-kept') === 'true') {
401+
if (this._relatedOnScroll) this.scrollEventSet.delete(this._relatedOnScroll);
402+
return;
403+
}
404+
405+
const $relatedAuto = document.getElementById('related-auto');
406+
const $relatedContent = document.getElementById('related-content-static');
407+
408+
if ($relatedContent && $relatedAuto) {
409+
$relatedAuto.querySelector('.related-content').appendChild($relatedContent);
410+
} else {
411+
return;
412+
}
413+
414+
const $toc = document.getElementById('toc-auto');
415+
416+
if ($toc && getComputedStyle($toc).visibility !== 'hidden' && getComputedStyle($toc).display !== 'none') {
417+
// Sychronize position with the TOC
418+
const tocRect = $toc.getBoundingClientRect();
419+
$relatedAuto.style.top = `${window.scrollY + tocRect.top}px`;
420+
$relatedAuto.style.left = `20px`;
421+
$relatedAuto.style.visibility = 'visible';
422+
} else {
423+
$relatedAuto.style.visibility = 'hidden';
424+
return;
425+
}
426+
427+
const headerIsFixed = document.body.getAttribute('data-header-desktop') !== 'normal';
428+
const headerHeight = document.getElementById('header-desktop').offsetHeight;
429+
const TOP_SPACING = 20 + (headerIsFixed ? headerHeight : 0);
430+
const minRelatedTop = $relatedAuto.offsetTop;
431+
const minScrollTop = minRelatedTop - TOP_SPACING + (headerIsFixed ? 0 : headerHeight);
432+
433+
this._relatedOnScroll = this._relatedOnScroll || (() => {
434+
const footerTop = document.getElementById('post-footer').offsetTop;
435+
const maxRelatedTop = footerTop - $relatedAuto.getBoundingClientRect().height;
436+
const maxScrollTop = maxRelatedTop - TOP_SPACING + (headerIsFixed ? 0 : headerHeight);
437+
if (this.newScrollTop < minScrollTop) {
438+
$relatedAuto.style.position = 'absolute';
439+
$relatedAuto.style.top = `${minRelatedTop}px`;
440+
} else if (this.newScrollTop > maxScrollTop) {
441+
$relatedAuto.style.position = 'absolute';
442+
$relatedAuto.style.top = `${maxRelatedTop}px`;
443+
} else {
444+
$relatedAuto.style.position = 'fixed';
445+
$relatedAuto.style.top = `${TOP_SPACING}px`;
446+
}
447+
});
448+
this._relatedOnScroll();
449+
this.scrollEventSet.add(this._relatedOnScroll);
450+
}
451+
396452
initToc() {
397453
const $tocCore = document.getElementById('TableOfContents');
398454
if ($tocCore === null) return;
@@ -693,8 +749,12 @@ class Theme {
693749
this._resizeTimeout = null;
694750
for (let event of this.resizeEventSet) event();
695751
this.initToc();
696-
this.initMermaid();
697-
this.initSearch();
752+
this.initRelated(); // Ensure this call remains
753+
this.initComment();
754+
755+
this.onScroll();
756+
this.onResize();
757+
this.onClickMask();
698758
}, 100);
699759
}
700760
}, false);
@@ -731,6 +791,7 @@ class Theme {
731791

732792
window.setTimeout(() => {
733793
this.initToc();
794+
this.initRelated(); // Ensure this call remains
734795
this.initComment();
735796

736797
this.onScroll();

layouts/posts/single.html

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,24 @@
1010
{{- $toc = dict "enable" false -}}
1111
{{- end -}}
1212

13-
{{- /* Auto TOC */ -}}
13+
{{- /* Add related content parameters, similar to TOC */ -}}
14+
{{- $related := $params.related -}}
15+
{{- if eq $related true -}}
16+
{{- $related = .Site.Params.page.related | default dict -}}
17+
{{- else if eq $related false -}}
18+
{{- $related = dict "enable" false -}}
19+
{{- end -}}
20+
{{- $relatedPages := .Site.RegularPages.Related . | first (or ($related.count) 5) -}}
21+
22+
{{- /* Auto Related (Left Panel) - Only show if related pages exist */ -}}
23+
{{- if and (ne $related.enable false) (gt (len $relatedPages) 0) -}}
24+
<div class="related" id="related-auto">
25+
<h2 class="related-title">{{ T "related" | default "Related" }}</h2>
26+
<div class="related-content{{ if eq $related.auto false }} always-active{{ end }}" id="related-content-auto"></div>
27+
</div>
28+
{{- end -}}
29+
30+
{{- /* Auto TOC (Right Panel) */ -}}
1431
{{- if ne $toc.enable false -}}
1532
<div class="toc" id="toc-auto">
1633
<h2 class="toc-title">{{ T "contents" }}</h2>
@@ -81,6 +98,23 @@ <h2 class="single-subtitle">{{ . }}</h2>
8198

8299
<hr>
83100

101+
{{- /* Static Related (Inline) - Only show if related pages exist */ -}}
102+
{{- if and (ne $related.enable false) (gt (len $relatedPages) 0) -}}
103+
<div class="details related" id="related-static" data-kept="{{ if $related.keepStatic }}true{{ end }}">
104+
<div class="details-summary related-title">
105+
<span>{{ T "related" | default "Related" }}</span>
106+
<span><i class="details-icon fa-solid fa-angle-right"></i></span>
107+
</div>
108+
<div class="details-content related-content" id="related-content-static">
109+
<ul>
110+
{{- range $relatedPages -}}
111+
<li><a href="{{ .RelPermalink }}" title="{{ .Title }}">{{ .Title }}</a></li>
112+
{{- end -}}
113+
</ul>
114+
</div>
115+
</div>
116+
{{- end -}}
117+
84118
{{- /* Static TOC */ -}}
85119
{{- if ne $toc.enable false -}}
86120
<div class="details toc" id="toc-static" data-kept="{{ if $toc.keepStatic }}true{{ end }}">

0 commit comments

Comments
 (0)