tangled
alpha
login
or
join now
erika.florist
/
maudit
6
fork
atom
Rust library to generate static websites
6
fork
atom
overview
issues
pulls
1
pipelines
refactor: bundle scripts
Princesseuh
5 months ago
355a89a3
398a27d9
+133
-105
4 changed files
expand all
collapse all
unified
split
website
assets
docs-sidebar.ts
mobile-menu.ts
src
layout
header.rs
layout.rs
+100
website/assets/docs-sidebar.ts
···
1
1
+
document.addEventListener("DOMContentLoaded", function () {
2
2
+
const leftSidebarToggleElement = document.getElementById(
3
3
+
"left-sidebar-toggle"
4
4
+
);
5
5
+
const rightSidebarToggleElement = document.getElementById(
6
6
+
"right-sidebar-toggle"
7
7
+
);
8
8
+
const leftSidebarElement = document.getElementById("mobile-left-sidebar");
9
9
+
const rightSidebarElement = document.getElementById("mobile-right-sidebar");
10
10
+
11
11
+
// Early return if required elements are not found
12
12
+
if (
13
13
+
!leftSidebarToggleElement ||
14
14
+
!rightSidebarToggleElement ||
15
15
+
!leftSidebarElement ||
16
16
+
!rightSidebarElement
17
17
+
) {
18
18
+
throw new Error("Sidebar elements not found in the DOM");
19
19
+
}
20
20
+
21
21
+
// Now we can safely assign to non-nullable variables
22
22
+
const leftSidebarToggle = leftSidebarToggleElement;
23
23
+
const rightSidebarToggle = rightSidebarToggleElement;
24
24
+
const leftSidebar = leftSidebarElement;
25
25
+
const rightSidebar = rightSidebarElement;
26
26
+
27
27
+
let leftOpen = false;
28
28
+
let rightOpen = false;
29
29
+
30
30
+
function toggleLeftSidebar() {
31
31
+
leftOpen = !leftOpen;
32
32
+
33
33
+
leftSidebar.classList.toggle("-translate-x-full", !leftOpen);
34
34
+
leftSidebar.classList.toggle("translate-x-0", leftOpen);
35
35
+
leftSidebar.classList.toggle("opacity-0", !leftOpen);
36
36
+
leftSidebar.classList.toggle("opacity-100", leftOpen);
37
37
+
leftSidebar.classList.toggle("pointer-events-none", !leftOpen);
38
38
+
39
39
+
if (leftOpen) {
40
40
+
document.body.style.overflow = "hidden";
41
41
+
} else if (!rightOpen) {
42
42
+
document.body.style.overflow = "";
43
43
+
}
44
44
+
}
45
45
+
46
46
+
function toggleRightSidebar() {
47
47
+
rightOpen = !rightOpen;
48
48
+
49
49
+
rightSidebar.classList.toggle("translate-x-full", !rightOpen);
50
50
+
rightSidebar.classList.toggle("translate-x-0", rightOpen);
51
51
+
rightSidebar.classList.toggle("opacity-0", !rightOpen);
52
52
+
rightSidebar.classList.toggle("opacity-100", rightOpen);
53
53
+
rightSidebar.classList.toggle("pointer-events-none", !rightOpen);
54
54
+
55
55
+
if (rightOpen) {
56
56
+
document.body.style.overflow = "hidden";
57
57
+
} else if (!leftOpen) {
58
58
+
document.body.style.overflow = "";
59
59
+
}
60
60
+
}
61
61
+
62
62
+
// Close sidebars when clicking outside
63
63
+
function closeSidebars(event: MouseEvent) {
64
64
+
const target = event.target;
65
65
+
if (
66
66
+
leftOpen &&
67
67
+
target &&
68
68
+
!leftSidebar.contains(target as Node) &&
69
69
+
!leftSidebarToggle.contains(target as Node)
70
70
+
) {
71
71
+
toggleLeftSidebar();
72
72
+
}
73
73
+
if (
74
74
+
rightOpen &&
75
75
+
target &&
76
76
+
!rightSidebar.contains(target as Node) &&
77
77
+
!rightSidebarToggle.contains(target as Node)
78
78
+
) {
79
79
+
toggleRightSidebar();
80
80
+
}
81
81
+
}
82
82
+
83
83
+
leftSidebarToggle.addEventListener("click", toggleLeftSidebar);
84
84
+
rightSidebarToggle.addEventListener("click", toggleRightSidebar);
85
85
+
document.addEventListener("click", closeSidebars);
86
86
+
87
87
+
// Close right sidebar when clicking on table of contents links
88
88
+
rightSidebar.addEventListener("click", function (event) {
89
89
+
const target = event.target as HTMLElement;
90
90
+
if (
91
91
+
target &&
92
92
+
target.tagName === "A" &&
93
93
+
target.getAttribute("href")?.startsWith("#")
94
94
+
) {
95
95
+
if (rightOpen) {
96
96
+
toggleRightSidebar();
97
97
+
}
98
98
+
}
99
99
+
});
100
100
+
});
+28
website/assets/mobile-menu.ts
···
1
1
+
document.addEventListener("DOMContentLoaded", function () {
2
2
+
const menuButton = document.getElementById("mobile-menu-button");
3
3
+
const panel = document.getElementById("mobile-menu-panel");
4
4
+
const hamburgerIcon = document.getElementById("hamburger-icon");
5
5
+
const closeIcon = document.getElementById("close-icon");
6
6
+
let isOpen = false;
7
7
+
8
8
+
function toggleMenu() {
9
9
+
if (!panel) return;
10
10
+
11
11
+
isOpen = !isOpen;
12
12
+
13
13
+
panel.classList.toggle("-translate-x-4", !isOpen);
14
14
+
panel.classList.toggle("opacity-0", !isOpen);
15
15
+
panel.classList.toggle("pointer-events-none", !isOpen);
16
16
+
17
17
+
if (hamburgerIcon) {
18
18
+
hamburgerIcon.classList.toggle("hidden", isOpen);
19
19
+
}
20
20
+
if (closeIcon) {
21
21
+
closeIcon.classList.toggle("hidden", !isOpen);
22
22
+
}
23
23
+
24
24
+
document.body.style.overflow = isOpen ? "hidden" : "";
25
25
+
}
26
26
+
27
27
+
menuButton?.addEventListener("click", toggleMenu);
28
28
+
});
+2
-77
website/src/layout.rs
···
75
75
headings: &[MarkdownHeading],
76
76
seo: Option<SeoMeta>,
77
77
) -> impl Into<RenderResult> {
78
78
+
ctx.assets.include_script("assets/docs-sidebar.ts");
79
79
+
78
80
layout(
79
81
html! {
80
82
// Second header for docs navigation (mobile only)
···
115
117
aside."py-8".hidden."sm:block" {
116
118
(right_sidebar(headings))
117
119
}
118
118
-
}
119
119
-
120
120
-
script {
121
121
-
(PreEscaped(r#"
122
122
-
document.addEventListener('DOMContentLoaded', function() {
123
123
-
const leftSidebarToggle = document.getElementById('left-sidebar-toggle');
124
124
-
const rightSidebarToggle = document.getElementById('right-sidebar-toggle');
125
125
-
const leftSidebar = document.getElementById('mobile-left-sidebar');
126
126
-
const rightSidebar = document.getElementById('mobile-right-sidebar');
127
127
-
128
128
-
let leftOpen = false;
129
129
-
let rightOpen = false;
130
130
-
131
131
-
function toggleLeftSidebar() {
132
132
-
leftOpen = !leftOpen;
133
133
-
134
134
-
leftSidebar.classList.toggle('-translate-x-full', !leftOpen);
135
135
-
leftSidebar.classList.toggle('translate-x-0', leftOpen);
136
136
-
leftSidebar.classList.toggle('opacity-0', !leftOpen);
137
137
-
leftSidebar.classList.toggle('opacity-100', leftOpen);
138
138
-
leftSidebar.classList.toggle('pointer-events-none', !leftOpen);
139
139
-
140
140
-
if (leftOpen) {
141
141
-
document.body.style.overflow = 'hidden';
142
142
-
} else if (!rightOpen) {
143
143
-
document.body.style.overflow = '';
144
144
-
}
145
145
-
}
146
146
-
147
147
-
function toggleRightSidebar() {
148
148
-
rightOpen = !rightOpen;
149
149
-
150
150
-
rightSidebar.classList.toggle('translate-x-full', !rightOpen);
151
151
-
rightSidebar.classList.toggle('translate-x-0', rightOpen);
152
152
-
rightSidebar.classList.toggle('opacity-0', !rightOpen);
153
153
-
rightSidebar.classList.toggle('opacity-100', rightOpen);
154
154
-
rightSidebar.classList.toggle('pointer-events-none', !rightOpen);
155
155
-
156
156
-
if (rightOpen) {
157
157
-
document.body.style.overflow = 'hidden';
158
158
-
} else if (!leftOpen) {
159
159
-
document.body.style.overflow = '';
160
160
-
}
161
161
-
}
162
162
-
163
163
-
// Close sidebars when clicking outside
164
164
-
function closeSidebars(event) {
165
165
-
if (leftOpen && !leftSidebar.contains(event.target) && !leftSidebarToggle.contains(event.target)) {
166
166
-
toggleLeftSidebar();
167
167
-
}
168
168
-
if (rightOpen && !rightSidebar.contains(event.target) && !rightSidebarToggle.contains(event.target)) {
169
169
-
toggleRightSidebar();
170
170
-
}
171
171
-
}
172
172
-
173
173
-
leftSidebarToggle.addEventListener('click', toggleLeftSidebar);
174
174
-
rightSidebarToggle.addEventListener('click', toggleRightSidebar);
175
175
-
document.addEventListener('click', closeSidebars);
176
176
-
177
177
-
// Close right sidebar when clicking on table of contents links
178
178
-
rightSidebar.addEventListener('click', function(event) {
179
179
-
if (event.target.tagName === 'A' && event.target.getAttribute('href').startsWith('#')) {
180
180
-
if (rightOpen) {
181
181
-
toggleRightSidebar();
182
182
-
}
183
183
-
}
184
184
-
});
185
185
-
186
186
-
// Close sidebars on escape key
187
187
-
document.addEventListener('keydown', function(event) {
188
188
-
if (event.key === 'Escape') {
189
189
-
if (leftOpen) toggleLeftSidebar();
190
190
-
if (rightOpen) toggleRightSidebar();
191
191
-
}
192
192
-
});
193
193
-
});
194
194
-
"#))
195
120
}
196
121
},
197
122
true,
+3
-28
website/src/layout/header.rs
···
3
3
use maud::PreEscaped;
4
4
use maudit::route::PageContext;
5
5
6
6
-
pub fn header(_: &mut PageContext, bottom_border: bool) -> Markup {
6
6
+
pub fn header(ctx: &mut PageContext, bottom_border: bool) -> Markup {
7
7
+
ctx.assets.include_script("assets/mobile-menu.ts");
8
8
+
7
9
let border = if bottom_border { "border-b" } else { "" };
8
10
let nav_links = vec![
9
11
("/docs/", "Documentation"),
···
76
78
}
77
79
}
78
80
}
79
79
-
}
80
80
-
81
81
-
script {
82
82
-
(PreEscaped(r#"
83
83
-
document.addEventListener('DOMContentLoaded', function() {
84
84
-
const menuButton = document.getElementById('mobile-menu-button');
85
85
-
const panel = document.getElementById('mobile-menu-panel');
86
86
-
const hamburgerIcon = document.getElementById('hamburger-icon');
87
87
-
const closeIcon = document.getElementById('close-icon');
88
88
-
let isOpen = false;
89
89
-
90
90
-
function toggleMenu() {
91
91
-
isOpen = !isOpen;
92
92
-
93
93
-
panel.classList.toggle('-translate-x-4', !isOpen);
94
94
-
panel.classList.toggle('opacity-0', !isOpen);
95
95
-
panel.classList.toggle('pointer-events-none', !isOpen);
96
96
-
97
97
-
hamburgerIcon.classList.toggle('hidden', isOpen);
98
98
-
closeIcon.classList.toggle('hidden', !isOpen);
99
99
-
100
100
-
document.body.style.overflow = isOpen ? 'hidden' : '';
101
101
-
}
102
102
-
103
103
-
menuButton.addEventListener('click', toggleMenu);
104
104
-
});
105
105
-
"#))
106
81
}
107
82
}
108
83
}