Skip to content

Commit 4861842

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

File tree

4 files changed

+203
-4
lines changed

4 files changed

+203
-4
lines changed

assets/css/_page/_single.scss

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
@import "../_partial/_single/toc";
2+
@import "../_partial/_single/related";
23

34
.single-card {
45
padding: 3rem;
@@ -348,4 +349,4 @@
348349

349350
.lg-toolbar .lg-icon::after {
350351
color: #999;
351-
}
352+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
.related {
2+
position: absolute;
3+
padding: .5rem .5rem .5rem 1rem;
4+
width: clamp(180px, 15vw, 280px);
5+
border-left: 3px solid $global-link-color;
6+
7+
[theme=dark] & {
8+
border-left-color: $global-link-color-dark;
9+
}
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;
40+
text-shadow: 0.5px 0 $global-link-color;
41+
42+
[theme=dark] & {
43+
color: $global-link-color-dark;
44+
text-shadow: 0.5px 0 $global-link-color-dark;
45+
}
46+
}
47+
48+
a {
49+
display: block;
50+
padding: .2rem 0;
51+
border-bottom: 1px solid transparent;
52+
@include link(false, false);
53+
}
54+
}
55+
}
56+
57+
.page-aside-left {
58+
// Hide by default on all screens
59+
display: none;
60+
}
61+
62+
// This new media query controls the layout for screens 1200px and wider.
63+
@media (min-width: 1200px) {
64+
.page-aside-left {
65+
// Show the panel on wide screens
66+
display: block;
67+
position: absolute;
68+
// Symmetrically position the panel to the left of the main content.
69+
// This calculation is robust and uses the globally available CSS variable.
70+
left: calc((100vw - var(--single-max-width)) / 2 - 280px - 1rem);
71+
width: 280px;
72+
}
73+
}
74+
75+
/* Style for the inline "details" version to match the inline TOC */
76+
.details.related {
77+
.details-summary {
78+
cursor: pointer;
79+
.details-icon {
80+
transform: rotate(0deg);
81+
transition: transform .3s;
82+
}
83+
&.open .details-icon {
84+
transform: rotate(90deg);
85+
}
86+
}
87+
.details-content.related-content {
88+
padding: .5rem 0;
89+
}
90+
}
91+
92+
//TEMP: Add this rule to permanently hide the static related block container.
93+
#related-static {
94+
display: none !important;
95+
}

assets/js/theme.js

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

396+
initRelated() {
397+
// Clean up any listeners from the previous page to prevent conflicts.
398+
if (this._relatedOnScroll) {
399+
this.scrollEventSet.delete(this._relatedOnScroll);
400+
this.resizeEventSet.delete(this._relatedOnScroll);
401+
}
402+
403+
const $relatedAuto = document.getElementById('related-auto');
404+
if (!$relatedAuto) return;
405+
406+
const $relatedContentStatic = document.getElementById('related-content-static');
407+
if ($relatedContentStatic) {
408+
const $relatedContentAuto = $relatedAuto.querySelector('.related-content');
409+
if ($relatedContentAuto) {
410+
$relatedContentAuto.appendChild($relatedContentStatic);
411+
}
412+
}
413+
414+
const $toc = document.getElementById('toc-auto');
415+
if (!$toc) return;
416+
417+
// Create a new scroll handler function for the current page.
418+
this._relatedOnScroll = () => {
419+
// If the panel's container is hidden by CSS, do nothing.
420+
if (getComputedStyle($relatedAuto.parentElement).display === 'none') {
421+
return;
422+
}
423+
424+
const headerIsFixed = document.body.getAttribute('data-header-desktop') !== 'normal';
425+
const headerHeight = document.getElementById('header-desktop').offsetHeight;
426+
const TOP_SPACING = 20 + (headerIsFixed ? headerHeight : 0);
427+
428+
const minRelatedTop = $toc.offsetTop;
429+
const minScrollTop = minRelatedTop - TOP_SPACING;
430+
431+
const footerTop = document.getElementById('post-footer').offsetTop;
432+
const maxRelatedTop = footerTop - $relatedAuto.getBoundingClientRect().height;
433+
const maxScrollTop = maxRelatedTop - TOP_SPACING;
434+
435+
if ($relatedAuto.style.position !== 'fixed') {
436+
$relatedAuto.style.position = 'absolute';
437+
$relatedAuto.style.top = `${minRelatedTop}px`;
438+
}
439+
440+
if (this.newScrollTop < minScrollTop) {
441+
$relatedAuto.style.position = 'absolute';
442+
$relatedAuto.style.top = `${minRelatedTop}px`;
443+
} else if (this.newScrollTop > maxScrollTop) {
444+
$relatedAuto.style.position = 'absolute';
445+
$relatedAuto.style.top = `${maxRelatedTop}px`;
446+
} else {
447+
$relatedAuto.style.position = 'fixed';
448+
$relatedAuto.style.top = `${TOP_SPACING}px`;
449+
}
450+
};
451+
452+
// Run once on load and add the new handler to the event listeners.
453+
this._relatedOnScroll();
454+
this.scrollEventSet.add(this._relatedOnScroll);
455+
this.resizeEventSet.add(this._relatedOnScroll);
456+
}
457+
396458
initToc() {
397459
const $tocCore = document.getElementById('TableOfContents');
398460
if ($tocCore === null) return;
@@ -693,8 +755,12 @@ class Theme {
693755
this._resizeTimeout = null;
694756
for (let event of this.resizeEventSet) event();
695757
this.initToc();
696-
this.initMermaid();
697-
this.initSearch();
758+
this.initRelated(); // Ensure this call remains
759+
this.initComment();
760+
761+
this.onScroll();
762+
this.onResize();
763+
this.onClickMask();
698764
}, 100);
699765
}
700766
}, false);
@@ -731,6 +797,7 @@ class Theme {
731797

732798
window.setTimeout(() => {
733799
this.initToc();
800+
this.initRelated(); // Ensure this call remains
734801
this.initComment();
735802

736803
this.onScroll();

layouts/posts/single.html

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,26 @@
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="page-aside-left">
25+
<div class="related" id="related-auto">
26+
<h2 class="related-title">{{ T "related" | default "Related" }}</h2>
27+
<div class="related-content{{ if eq $related.auto false }} always-active{{ end }}" id="related-content-auto"></div>
28+
</div>
29+
</div>
30+
{{- end -}}
31+
32+
{{- /* Auto TOC (Right Panel) */ -}}
1433
{{- if ne $toc.enable false -}}
1534
<div class="toc" id="toc-auto">
1635
<h2 class="toc-title">{{ T "contents" }}</h2>
@@ -81,6 +100,23 @@ <h2 class="single-subtitle">{{ . }}</h2>
81100

82101
<hr>
83102

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

0 commit comments

Comments
 (0)