Skip to content

Commit 4fbfde3

Browse files
committed
feat: add button to toggle sidebar. Collapse sidebar under lg breakpoint
Additional Changes: - fix: don't trigger animations when toggling between breakpoints
1 parent 59ce26d commit 4fbfde3

File tree

5 files changed

+166
-68
lines changed

5 files changed

+166
-68
lines changed

TODO.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
Add hide button for sidebarinfo. Keep sidebar hidden by default under lg breakpoints. - [ ]
1+
Add hide button for sidebarinfo. Keep sidebar hidden by default under lg breakpoints. - [x]
22
Fix bootstrap collapse (it isn't smooth when hiding) - [ ]
33
Add dynamic font size to Table of Contents to prevent overflow - [ ]
44
On section pages the date seems to close to the title on the card-bodys. Only on the github deployment though... - [ ]
5+
grow left border under lg breakpoints

assets/js/main.js

Lines changed: 81 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,44 @@
11
const currentPage = window.location.pathname;
2+
const BREAKPOINT_LG = 991.98;
23
let animation = sessionStorage.getItem("animation") === "true";
4+
let showSideBar = localStorage.getItem("showSideBar") === "true";
5+
let sidebar = document.querySelector(".my-sidebar");
6+
let toggler = document.getElementById("sidebar-toggler");
7+
toggler.addEventListener("click", toggle);
8+
window.addEventListener("resize", hideAnimations());
39

4-
function hide() {
5-
let sidebar = document.querySelector(".my-side-bar");
6-
// switching to home/resume page (toggle off the sidebar with animation)
7-
if (animation) {
8-
sidebar.classList.add("show");
9-
void document.body.offsetHeight;
10+
switch (currentPage) {
11+
case "/":
12+
case "/resume/":
13+
hideToggler();
14+
if (animation) {
15+
sidebar.classList.add("show");
16+
toggler.classList.add("show");
17+
void document.body.offsetHeight;
1018

19+
document.body.classList.remove("preload");
20+
hide();
21+
} else {
22+
document.body.classList.remove("preload");
23+
}
24+
break;
25+
default:
26+
if (showSideBar && window.innerWidth > BREAKPOINT_LG) {
27+
if (animation) {
28+
sidebar.classList.add("show");
29+
toggler.classList.add("show");
30+
void document.body.offsetHeight;
31+
} else {
32+
document.body.classList.remove("preload");
33+
show();
34+
}
35+
}
1136
document.body.classList.remove("preload");
12-
sidebar.classList.remove("show");
13-
sessionStorage.setItem("animation", false);
14-
} else {
15-
document.body.classList.remove("preload");
16-
}
17-
}
18-
19-
function show() {
20-
let sidebar = document.querySelector(".my-side-bar");
21-
if (animation) {
22-
sidebar.classList.add("show");
23-
void document.body.offsetHeight;
24-
document.body.classList.remove("preload");
25-
} else {
26-
document.body.classList.remove("preload");
27-
sidebar.classList.add("show");
28-
sessionStorage.setItem("animation", true);
29-
}
37+
break;
3038
}
3139

32-
window.onload = function () {
33-
switch (currentPage) {
34-
case "/":
35-
case "/resume/":
36-
hide();
37-
break;
38-
default:
39-
show();
40-
break;
41-
}
42-
};
43-
44-
let previousActive = null;
40+
// Table of Content active code
41+
let activeElement = null;
4542
const observer = new IntersectionObserver((entries) => {
4643
for (entry of entries) {
4744
// NOTE: intersection ratios are only 1 or 0
@@ -54,18 +51,15 @@ const observer = new IntersectionObserver((entries) => {
5451
const element = links.get(key);
5552
if (!found && val) {
5653
found = true;
57-
previousActive = key;
54+
activeElement = key;
5855
element.classList.add("active");
5956
history.replaceState(null, null, `#${key}`);
6057
} else {
6158
element.classList.remove("active");
6259
}
6360
});
6461

65-
// Activate the previousActive
66-
if (!found) {
67-
links.get(previousActive).classList.add("active");
68-
}
62+
links.get(activeElement).classList.add("active");
6963
});
7064

7165
let links = new Map();
@@ -76,3 +70,48 @@ for (el of document.querySelectorAll("#TableOfContents a[href]")) {
7670
actives.set(id, false);
7771
observer.observe(document.getElementById(id));
7872
}
73+
74+
function toggle() {
75+
// use localStorage so user preference persists between sessions
76+
if (sidebar.classList.contains("show")) {
77+
hide();
78+
localStorage.setItem("showSideBar", false);
79+
} else {
80+
show();
81+
localStorage.setItem("showSideBar", true);
82+
}
83+
}
84+
85+
function hide() {
86+
sidebar.classList.remove("show");
87+
toggler.classList.remove("show");
88+
sessionStorage.setItem("animation", false);
89+
}
90+
91+
function show() {
92+
sidebar.classList.add("show");
93+
toggler.classList.add("show");
94+
sessionStorage.setItem("animation", true);
95+
}
96+
97+
function hideToggler() {
98+
toggler.style.display = "none";
99+
}
100+
101+
function hideAnimations() {
102+
let previousWidth = document.body.clientWidth;
103+
return () => {
104+
let currentWidth = document.body.clientWidth;
105+
106+
let newDiff = currentWidth - BREAKPOINT_LG;
107+
let previousDiff = previousWidth - BREAKPOINT_LG;
108+
109+
// In between breakpoints. Disable animations
110+
if (previousDiff > 0 != newDiff > 0) {
111+
document.body.classList.add("noanimation");
112+
void document.body.offsetHeight;
113+
document.body.classList.remove("noanimation");
114+
}
115+
previousWidth = currentWidth;
116+
};
117+
}

assets/sass/main.scss

Lines changed: 77 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,11 @@ body {
9999
&.preload {
100100
visibility: hidden;
101101
* {
102-
-webkit-transition: none !important;
103-
-moz-transition: none !important;
104-
-ms-transition: none !important;
105-
-o-transition: none !important;
102+
transition: none !important;
103+
}
104+
}
105+
&.noanimation {
106+
* {
106107
transition: none !important;
107108
}
108109
}
@@ -113,7 +114,8 @@ body {
113114
$font-header-size: 1.5rem;
114115
// TODO: examine better this height relative to root font size
115116
$header-size: $font-header-size * 2.5;
116-
$side-bar-size: 300px;
117+
$toggler-size: 50px;
118+
$sidebar-size: 300px + $toggler-size;
117119

118120
.my-header {
119121
background-color: $my-black;
@@ -135,7 +137,7 @@ $side-bar-size: 300px;
135137
@include make-col-ready();
136138
@include make-col(2);
137139

138-
min-width: $side-bar-size;
140+
min-width: $sidebar-size;
139141
// font-size: clamp(1rem, 1.5vw, $font-header-size);
140142

141143
.my-port {
@@ -220,15 +222,17 @@ $side-bar-size: 300px;
220222

221223
// Define mixin for placing elements after header
222224
@mixin after-header() {
223-
// top: $header-size;
224225
height: subtract(100vh, $header-size);
226+
// @include media-breakpoint-down(lg) {
227+
// height: subtract(100vh, add($header-size, $toggler-size));
228+
// }
225229
}
226230

227231
.my-email {
228232
font-size: clamp(0.8rem, 0.75vw, 1rem);
229233
}
230234

231-
.my-side-bar {
235+
.my-sidebar {
232236
@include make-col-ready();
233237
@include after-header();
234238

@@ -249,20 +253,69 @@ $side-bar-size: 300px;
249253
transition-duration: 0.3s;
250254
transition-timing-function: linear;
251255
&.show {
252-
@include make-col(2);
253-
padding: 1.25rem;
254256
opacity: 1;
257+
padding: 1.25rem;
258+
}
259+
@include media-breakpoint-up(lg) {
260+
&.show {
261+
@include make-col(2);
262+
padding-right: Max(1.25rem, $toggler-size);
263+
// padding: 1.25rem;
264+
// opacity: 1;
265+
266+
// NOTE: do math (use the `max` css function)
267+
// instead of min-width to correctly animate from 0 to width
268+
width: Max($sidebar-size, 16.66666667%);
269+
}
270+
}
271+
@include media-breakpoint-down(lg) {
272+
@include make-col(12);
273+
max-height: 0;
274+
&.show {
275+
// NOTE: Using max-height so it animates from 0 to 1000px. The value 1000 was
276+
// chosen empirically.
277+
max-height: 1000px;
278+
}
279+
}
280+
}
255281

256-
// NOTE: do math (use the `max` css function)
257-
// instead of min-width to correctly animate from 0 to width
258-
width: Max($side-bar-size, 16.66666667%);
282+
#sidebar-toggler {
283+
position: fixed;
284+
top: add($header-size, 20px);
285+
left: 2px; // account for main-layout left border
286+
width: $toggler-size;
259287

260-
// On devices lower than lg, take full width
261-
@include media-breakpoint-down(lg) {
262-
@include make-col(12);
263-
height: auto;
264-
// overflow-y: visible;
265-
flex-grow: 1;
288+
transition-property: all;
289+
transition-duration: 0.3s;
290+
transition-timing-function: linear;
291+
292+
border-top-left-radius: 0;
293+
border-bottom-left-radius: 0;
294+
295+
@include media-breakpoint-up(lg) {
296+
&::before {
297+
content: "\f061"; // Unicode for the right arrow icon
298+
font-family: "Font Awesome 5 Free"; // Ensure the correct Font Awesome font
299+
font-weight: 900; // Necessary for Font Awesome icons
300+
}
301+
&.show {
302+
left: Max($sidebar-size, 16.66666667%);
303+
transform: translateX(-100%) scaleX(-1);
304+
}
305+
}
306+
307+
@include media-breakpoint-down(lg) {
308+
position: sticky;
309+
z-index: 1015;
310+
height: $toggler-size;
311+
top: $header-size;
312+
border-radius: 0;
313+
width: 100%;
314+
&::before {
315+
content: "Show Info";
316+
}
317+
&.show::before {
318+
content: "Hide Info";
266319
}
267320
}
268321
}
@@ -295,9 +348,12 @@ $side-bar-size: 300px;
295348
align-items: flex-start;
296349
// height: 100%;
297350
overflow-y: auto;
351+
padding: 1.25rem;
352+
padding-left: Max(1.25rem, $toggler-size);
353+
padding-top: 0;
298354

299355
@include media-breakpoint-down(lg) {
300-
height: auto;
356+
// height: auto;
301357
@include make-col(12);
302358
overflow-y: visible;
303359
}
@@ -315,7 +371,7 @@ $side-bar-size: 300px;
315371
z-index: 1010;
316372

317373
@include media-breakpoint-down(lg) {
318-
top: $header-size;
374+
top: add($header-size, $toggler-size);
319375
}
320376
}
321377

@@ -367,5 +423,4 @@ $side-bar-size: 300px;
367423
}
368424

369425
.my-block {
370-
371426
}

layouts/_default/baseof.html

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@
1111
{{ partial "header.html" . }}
1212
</header>
1313
<div class="container-fluid">
14-
<div class="row">
15-
<aside class="my-side-bar pt-4">
14+
<div class="row flex-lg-row flex-column">
15+
<!-- <div class="row"> -->
16+
<aside class="my-sidebar">
1617
{{ partial "sidebar.html" . }}
1718
</aside>
19+
<button id="sidebar-toggler" class="btn my-btn"></button>
1820
<div class="my-main-layout">
1921
<main class="w-100 mb-auto">
2022
{{ block "main" . }}{{ end }}

layouts/partials/sidebar.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ <h2>Get In Touch:</h2>
5353
class="my-email d-flex align-items-center justify-content-center"
5454
href="mailto:[email protected]"
5555
>
56-
<i class="p-1 fas fa-envelope"></i> [email protected]
56+
<i class="p-1 fas fa-envelope"></i>
57+
5758
</a>
5859
<br />
5960

0 commit comments

Comments
 (0)