feat: add dynamic sidebar for scenes

Introduce a new sidebar in the UI for enhanced navigation through
scenes. This feature includes CSS modifications for styling, updates in
JavaScript to dynamically load sidebar content based on scene
categories, and template adjustments to include the sidebar option. By
leveraging the Collapse component from Bootstrap alongside existing
infrastructure, this addition enriches user interaction by providing a
convenient and visually appealing method to explore different scenes
within the application. The sidebar's design and functionality are
thoughtfully integrated to ensure a cohesive and user-friendly
experience.

The decision to implement a sidebar stemmed from the need to improve
navigational efficiency and user engagement with the content. This
change is part of a broader effort to enhance the UI/UX of the
application, aiming to make the exploration of scenes more intuitive and
accessible.
This commit is contained in:
Kumi 2024-03-15 19:27:19 +01:00
parent e3cff5b9b7
commit 0999d2f16e
Signed by: kumi
GPG key ID: ECBCC9082395383F
4 changed files with 75 additions and 5 deletions

View file

@ -3,3 +3,12 @@
position: fixed;
width: 100%;
}
#sceneSidebar {
z-index: 99999;
position: fixed;
width: 250px;
height: 100%;
background-color: #f8f9fa;
opacity: 0.7;
}

View file

@ -1,5 +1,5 @@
import { getScene, getCategory } from "./api";
import { Dropdown } from "bootstrap";
import { Dropdown, Collapse } from "bootstrap";
import "../scss/frontend.scss";
import "../css/scene.css";
@ -20,13 +20,18 @@ class QuackscapeScene extends HTMLElement {
this.x = this.getAttribute("x") | 0;
this.y = this.getAttribute("y") | 0;
this.z = this.getAttribute("z") | 0;
this.navbar = this.getAttribute("nonavbar") == undefined;
this.navbar = this.getAttribute("navbar") != undefined;
this.sidebar = this.getAttribute("sidebar") != undefined;
loadScene(this.scene, this.x, this.y, this.z, this, this.embedded);
if (this.navbar) {
loadNavbar(this.scene, this);
}
if (this.sidebar) {
loadSidebar(this.scene, this);
}
}
}
@ -36,6 +41,62 @@ document.addEventListener("contextmenu", function (event) {
customElements.define("quackscape-scene", QuackscapeScene);
// Function to add a sidebar to the destination object
async function loadSidebar(scene_id, destination) {
getScene(scene_id).then((scene) => {
getCategory(scene.obj.category).then((category) => {
var sidebar = document.createElement("div");
sidebar.setAttribute("class", "collapse show");
sidebar.setAttribute("id", "sceneSidebar");
var p = document.createElement("div");
p.setAttribute("class", "p-4");
var h5 = document.createElement("h5");
h5.setAttribute("class", "font-weight-bold");
h5.textContent = "Scenes";
var ul = document.createElement("ul");
ul.setAttribute("class", "nav flex-column");
category.obj.scenes.forEach((scene) => {
var li = document.createElement("li");
li.setAttribute("class", "nav-item");
var a = document.createElement("a");
a.setAttribute("href", "#");
a.setAttribute("class", "nav-link");
a.textContent = scene.title;
a.addEventListener("click", function () {
loadScene(scene.id, -1, -1, -1, destination);
});
li.appendChild(a);
ul.appendChild(li);
});
p.appendChild(h5);
p.appendChild(ul);
var button = document.createElement("button");
button.setAttribute("class", "btn btn-primary");
button.setAttribute("type", "button");
button.setAttribute("data-bs-toggle", "collapse");
button.setAttribute("data-bs-target", "#sceneSidebar");
button.setAttribute("aria-expanded", false);
button.setAttribute("aria-controls", "sceneSidebar");
button.textContent = "<";
//p.appendChild(button); // TODO: Make it prettier before enabling.
sidebar.appendChild(p);
destination.prepend(sidebar);
});
});
}
// Function to add a navbar to the destination object
async function loadNavbar(scene_id, destination) {

View file

@ -20,6 +20,7 @@
x="{{ scene.default_x }}"
y="{{ scene.default_y }}"
z="{{ scene.default_z }}"
sidebar
></quackscape-scene>
</body>
</html>

View file

@ -30,7 +30,6 @@
y="{{ scene.default_y }}"
z="{{ scene.default_z }}"
embedded
nonavbar
></quackscape-scene>
</div>