Skip to content

Commit 154b2aa

Browse files
committed
ui: css-ify navigation bar frontend
Rely on an almost-pure CSS implementation for the navigation bar. The old implementation was quite ugly, as it relied on the javascript cloning a bunch of HTML nodes to create the mobile-only dropdown. Instead, just do this duplication when generating the HTML (the cloning of nodes was not cloning event handlers, so depending on the order in which JS files were loaded, registering event handler to navbar items was impossible. Or rather, they would only work on the desktop version). This also eliminates the use of some jQuery, which is always nice. The cost here are some animations, but really, we don't need those. While we're at it, remove some unused css definitions. This entire part of the code pre-dates pointercrate, and stems from when I was messing around with doing my own Bootstrap-style css framework when I was in high school, to learn webdev. Good times. Signed-off-by: stadust <43299462+stadust@users.noreply.github.com>
1 parent 3a198f7 commit 154b2aa

File tree

3 files changed

+43
-130
lines changed

3 files changed

+43
-130
lines changed

pointercrate-core-pages/src/navigation.rs

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -40,22 +40,32 @@ impl NavigationBar {
4040
}
4141
}
4242

43-
impl Render for &TopLevelNavigationBarItem {
43+
struct NavGroup<T>(T);
44+
45+
impl<T: Render> Render for NavGroup<T> {
4446
fn render(&self) -> Markup {
4547
html! {
4648
div.nav-group {
47-
a.nav-item.hover.white href = (self.item.link) {
48-
(self.item.content)
49-
@if !self.sub_levels.is_empty() {
50-
i.fas.fa-sort-down style = "height: 50%; padding-left: 5px" {}
51-
}
52-
}
49+
(self.0)
50+
}
51+
}
52+
}
53+
}
54+
55+
impl Render for TopLevelNavigationBarItem {
56+
fn render(&self) -> Markup {
57+
html! {
58+
a.nav-item.hover.white href = (self.item.link) {
59+
(self.item.content)
5360
@if !self.sub_levels.is_empty() {
54-
ul.nav-hover-dropdown {
55-
@for sub_item in &self.sub_levels {
56-
li {
57-
a.white.hover href = (sub_item.link) { (sub_item.content)}
58-
}
61+
i.fas.fa-sort-down style = "height: 50%; padding-left: 5px" {}
62+
}
63+
}
64+
@if !self.sub_levels.is_empty() {
65+
ul.nav-hover-dropdown {
66+
@for sub_item in &self.sub_levels {
67+
li {
68+
a.white.hover href = (sub_item.link) { (sub_item.content)}
5969
}
6070
}
6171
}
@@ -69,22 +79,27 @@ impl Render for NavigationBar {
6979
html! {
7080
header {
7181
nav.center.collapse.underlined.see-through {
72-
div.nav-icon style = "margin-right: auto" {
82+
div.nav-icon.nav-nohide style = "margin-right: auto" {
7383
a href = "/" aria-label = "Go to homepage" {
7484
img src = (self.logo_path) style="height:15px" alt="Logo";
7585
}
7686
}
7787
@for item in &self.items {
78-
(item)
88+
(NavGroup(item))
7989
}
80-
div.nav-item.collapse-button {
90+
div.nav-item.collapse-button.nav-nohide {
8191
div.hamburger.hover {
8292
input type="checkbox"{}
8393
span{}
8494
span{}
8595
span{}
8696
}
8797
}
98+
div.nav-drop-down {
99+
@for item in &self.items {
100+
(item)
101+
}
102+
}
88103
}
89104
div {} // artificial spacing
90105
}

pointercrate-core-pages/static/css/nav.css

Lines changed: 7 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -67,31 +67,15 @@ header nav .nav-drop-down {
6767

6868
background: inherit;
6969
width: 100%;
70-
7170
display: none;
7271

73-
flex-direction: column;
74-
7572
z-index: 1000;
7673

7774
box-shadow: 0px 7px 10px 1px rgba(0, 0, 0, 0.2);
7875
}
7976

80-
header nav .nav-drop-down .seperator {
81-
border-right: None;
82-
border-bottom: 1px solid #999;
83-
84-
height: 0px;
85-
width: calc(100% - 20px);
86-
87-
align-self: center;
88-
89-
margin: 0px 10px 10px 10px;
90-
padding: 10px 0px 0px 0px;
91-
}
92-
9377
/*
94-
* Things for on hover sub-menus
78+
* Things for on hover sub-menus.
9579
*/
9680
header nav .nav-hover-dropdown {
9781
margin: 0;
@@ -124,8 +108,7 @@ header nav .nav-drop-down .nav-hover-dropdown a {
124108

125109
/* --------- smartphone ----------- */
126110
@media (max-width: 1071px) {
127-
.collapse > :not(.nav-drop-down).nav-item:not(.nav-nohide),
128-
.collapse > :not(.nav-drop-down) .nav-item:not(.nav-nohide) {
111+
.collapse > :not(.nav-drop-down).nav-group:not(.nav-nohide) {
129112
display: none;
130113
}
131114

@@ -143,6 +126,10 @@ header nav .nav-drop-down .nav-hover-dropdown a {
143126
margin: 0;
144127
}
145128

129+
.nav-drop-down.extended {
130+
display: block;
131+
}
132+
146133
.collapse-button {
147134
display: flex;
148135
height: 27px !important;
@@ -155,22 +142,11 @@ header nav .nav-drop-down .nav-hover-dropdown a {
155142
}
156143

157144
@media (min-width: 1072px) {
145+
158146
.nav-drop-down {
159147
display: none;
160148
}
161149

162-
header nav .seperator {
163-
border-right: 1px solid #999;
164-
165-
width: 0px;
166-
height: 80%;
167-
168-
align-self: center;
169-
170-
margin-right: 10px;
171-
padding: 0px 0px 0px 10px;
172-
}
173-
174150
.collapse-button {
175151
display: none !important;
176152
}
Lines changed: 6 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,94 +1,16 @@
11
"use strict";
22

3-
const TEMPLATES = {
4-
DROP_DOWN: "<div class='nav-drop-down'></div>",
5-
BUTTON:
6-
'<div class ="nav-item collapse-button nav-nohide"><div class="hamburger hover"><input type="checkbox" /><span></span><span></span><span></span></div></div>',
7-
};
8-
9-
const NOHIDE_CLASSES = [".collapse-button", ".nav-icon"];
10-
113
class NavigationBar {
124
constructor(navigation) {
13-
this.extended = false;
14-
this.nav = $(navigation);
15-
16-
let dropDown = document.createElement("div");
17-
dropDown.classList.add("nav-drop-down");
18-
19-
for (let navGroup of navigation.getElementsByClassName("nav-group")) {
20-
for (let navItem of navGroup.childNodes) {
21-
if (!navItem.classList.contains("nav-nohide")) {
22-
let clone = navItem.cloneNode(true);
23-
24-
for (let hovered of clone.getElementsByClassName(
25-
"nav-hover-dropdown"
26-
))
27-
hovered.classList.remove("nav-hover-dropdown");
5+
let dropDown = navigation.getElementsByClassName("nav-drop-down")[0];
286

29-
dropDown.appendChild(clone);
30-
}
31-
}
32-
}
33-
navigation.appendChild(dropDown);
34-
35-
this.dropDown = $(dropDown);
36-
this.button = this.ensureButton();
37-
this.registerHandlers();
38-
}
39-
40-
toggleDisplay(instant) {
41-
this.extended = !this.extended;
42-
43-
if (this.extended) {
44-
this.dropDown.stop().slideDown({
45-
duration: instant ? 0 : 400,
46-
easing: "easeInOutQuad",
47-
});
48-
} else {
49-
this.dropDown.stop().slideUp({
50-
duration: instant ? 0 : 400,
51-
easing: "easeInOutQuad",
52-
});
53-
}
54-
}
55-
56-
ensureButton() {
57-
var button = this.nav.find(".collapse-button");
58-
59-
if (button.length === 0) {
60-
button = $(TEMPLATES.BUTTON);
61-
this.nav.append(button);
62-
}
63-
64-
return button;
65-
}
66-
67-
registerHandlers() {
68-
$(window).resize(() => {
69-
if (this.extended) {
70-
if ($(window).width() >= 1024) {
71-
this.dropDown.css("display", "none");
72-
} else if (this.dropDown.css("display") === "none") {
73-
this.dropDown.css("display", "flex");
74-
}
75-
}
76-
});
77-
78-
this.button.click(() => this.toggleDisplay());
7+
navigation.getElementsByClassName("collapse-button")[0]
8+
.addEventListener("click", (e) => dropDown.classList.toggle("extended"));
9+
7910
}
8011
}
8112

82-
NavigationBar.allNavigationBars = [];
83-
8413
$(document).ready(function () {
85-
for (let i = 0; i < NOHIDE_CLASSES.length; ++i) {
86-
$(NOHIDE_CLASSES[i]).each((index, element) =>
87-
$(element).addClass("nav-nohide")
88-
);
89-
}
90-
91-
$("header nav.collapse").each((index, element) => {
92-
NavigationBar.allNavigationBars.push(new NavigationBar(element));
93-
});
14+
for(let navbar of document.querySelectorAll("header nav.collapse"))
15+
new NavigationBar(navbar);
9416
});

0 commit comments

Comments
 (0)