Add option to highlight current entry

Fixes #2.
This commit is contained in:
Florine W. Dekker 2020-07-20 12:54:32 +02:00
parent 91e77ab3a5
commit 81fff6c7e9
Signed by: FWDekker
GPG Key ID: B1B567AF58D6EE0F
5 changed files with 53 additions and 34 deletions

BIN
package-lock.json generated

Binary file not shown.

View File

@ -1,6 +1,6 @@
{ {
"name": "@fwdekker/template", "name": "@fwdekker/template",
"version": "0.0.17", "version": "0.0.18",
"description": "The base template for pages on fwdekker.com.", "description": "The base template for pages on fwdekker.com.",
"author": "Felix W. Dekker (https://fwdekker.com)", "author": "Felix W. Dekker (https://fwdekker.com)",
"license": "MIT", "license": "MIT",
@ -25,8 +25,8 @@
"normalize.css": "^8.0.1" "normalize.css": "^8.0.1"
}, },
"devDependencies": { "devDependencies": {
"css-loader": "^3.5.3", "css-loader": "^3.6.0",
"grunt": "^1.1.0", "grunt": "^1.2.1",
"grunt-cli": "^1.3.2", "grunt-cli": "^1.3.2",
"grunt-contrib-clean": "^2.0.0", "grunt-contrib-clean": "^2.0.0",
"grunt-contrib-watch": "^1.1.0", "grunt-contrib-watch": "^1.1.0",
@ -34,6 +34,6 @@
"grunt-webpack": "^3.1.3", "grunt-webpack": "^3.1.3",
"style-loader": "^1.2.1", "style-loader": "^1.2.1",
"webpack": "^4.43.0", "webpack": "^4.43.0",
"webpack-cli": "^3.3.11" "webpack-cli": "^3.3.12"
} }
} }

View File

@ -1,7 +1,10 @@
/* Variables */ /* Variables */
:root { :root {
--fwdekker-theme-color: #0033cc; --fwdekker-theme-color: #0033cc;
--fwdekker-theme-color-dark: #00279d; --fwdekker-theme-color-dark: #0029a3;
--fwdekker-theme-color-very-dark: #001f7a;
--fwdekker-theme-color-light: #003df5;
--fwdekker-theme-color-very-light: #1f57ff;
} }

View File

@ -22,27 +22,6 @@
color: white; color: white;
} }
.nav ul {
margin: 0;
padding: 0;
list-style: none;
}
.nav li {
display: inline-block;
margin: 0;
padding: 0;
position: relative;
background-color: var(--fwdekker-theme-color);
}
.nav li:hover,
.nav li:focus-within {
cursor: pointer;
background-color: var(--fwdekker-theme-color-dark);
}
.nav .logo { .nav .logo {
width: calc(1em + var(--padding)); width: calc(1em + var(--padding));
@ -57,6 +36,33 @@
} }
.nav ul {
margin: 0;
padding: 0;
list-style: none;
}
.nav ul li {
display: inline-block;
margin: 0;
padding: 0;
position: relative;
background-color: var(--fwdekker-theme-color);
}
.nav ul li:hover,
.nav ul li:focus-within {
cursor: pointer;
background-color: var(--fwdekker-theme-color-very-dark);
}
.nav li.currentPage {
background-color: var(--fwdekker-theme-color-dark);
}
.nav ul li ul { .nav ul li ul {
display: none; display: none;
position: absolute; position: absolute;

View File

@ -36,9 +36,10 @@ export const doAfterLoad = function (fun) {
* *
* Fetches entries asynchronously from the website's API. * Fetches entries asynchronously from the website's API.
* *
* @param [highlightPath] {String} the path to highlight together with its parents
* @returns {HTMLElement} a base navigation element that will eventually be filled with contents * @returns {HTMLElement} a base navigation element that will eventually be filled with contents
*/ */
export const nav = function () { export const nav = function (highlightPath = "") {
const base = h("ul", const base = h("ul",
h("li", h("a", {href: "https://fwdekker.com/"}, h("li", h("a", {href: "https://fwdekker.com/"},
h("div.logo", h("img.logo", {src: "https://fwdekker.com/favicon.png"})), h("div.logo", h("img.logo", {src: "https://fwdekker.com/favicon.png"})),
@ -48,7 +49,7 @@ export const nav = function () {
fetch("https://fwdekker.com/api/nav/") fetch("https://fwdekker.com/api/nav/")
.then(it => it.json()) .then(it => it.json())
.then(json => json.entries.forEach(entry => base.appendChild(unpackEntry(entry)))) .then(json => json.entries.forEach(entry => base.appendChild(unpackEntry(entry, "/", highlightPath))))
.catch(e => { .catch(e => {
console.error("Failed to fetch navigation elements", e); console.error("Failed to fetch navigation elements", e);
return []; return [];
@ -61,18 +62,27 @@ export const nav = function () {
* Unpacks a navigation entry returned from the navigation API into an HTML element. * Unpacks a navigation entry returned from the navigation API into an HTML element.
* *
* @param entry {Object} the entry to unpack * @param entry {Object} the entry to unpack
* @param [depth] {Object} the current nesting level * @param [path] {number} the current path traversed, found by joining the names of the entries with `/`s; always starts
* and ends with a `/`
* @param [highlightPath] {String} the path to highlight together with its parents
* @returns {HTMLElement} the navigation list entry as HTML, described by its children * @returns {HTMLElement} the navigation list entry as HTML, described by its children
*/ */
const unpackEntry = function (entry, depth = 0) { const unpackEntry = function (entry, path = "/", highlightPath = "") {
if (entry.entries.length === 0) const shouldHighlight = highlightPath.startsWith(`${path + entry.name}/`);
return h("li", h("a", {href: entry.link, innerHTML: entry.name}));
const arrow = depth === 0 ? "▾" : "▸" if (entry.entries.length === 0)
return h("li",
h("a", {href: entry.link, innerHTML: entry.name}),
{className: shouldHighlight ? "currentPage" : ""}
);
const depth = path.split("/").length - 2; // -1 because count parts, then another -1 because of leading `/`
const arrow = depth === 0 ? "▾" : "▸";
return h("li", return h("li",
h("a", {href: entry.link, innerHTML: `${entry.name} ${arrow}`}), h("a", {href: entry.link, innerHTML: `${entry.name} ${arrow}`}),
h("ul", entry.entries.map(it => unpackEntry(it, depth + 1))) h("ul", entry.entries.map(it => unpackEntry(it, `${path + entry.name}/`, highlightPath))),
{className: shouldHighlight ? "currentPage" : ""}
); );
}; };