tuning the sidebar

This commit is contained in:
buenosairesam
2026-01-27 00:32:06 -03:00
parent fecb978a5f
commit e1f81889fc
3 changed files with 168 additions and 147 deletions

View File

@@ -41,7 +41,7 @@
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
padding: 1rem 0; padding: 1rem 0;
z-index: 1000; z-index: 99999;
} }
.sidebar-item { .sidebar-item {
width: 44px; width: 44px;
@@ -55,7 +55,7 @@
color: #a3a3a3; color: #a3a3a3;
transition: all 0.2s; transition: all 0.2s;
} }
.sidebar-item:hover { a.sidebar-item:hover {
background: #333; background: #333;
color: white; color: white;
} }
@@ -73,6 +73,19 @@
background: #333; background: #333;
margin: 0.5rem 0; margin: 0.5rem 0;
} }
.sidebar-icon {
width: 44px;
height: 44px;
display: flex;
align-items: center;
justify-content: center;
color: #555;
margin-bottom: 0.5rem;
}
.sidebar-icon svg {
width: 20px;
height: 20px;
}
.sidebar-item .tooltip { .sidebar-item .tooltip {
position: absolute; position: absolute;
left: 70px; left: 70px;
@@ -227,30 +240,29 @@
<span class="tooltip">Soleprint</span> <span class="tooltip">Soleprint</span>
</a> </a>
<a href="/artery" class="sidebar-item" title="Artery"> <div class="sidebar-divider"></div>
<div class="sidebar-icon" title="Artery">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 2v8M12 10L6 18M12 10l6 8"/> <path d="M12 2v8M12 10L6 18M12 10l6 8"/>
<circle cx="12" cy="10" r="2"/> <circle cx="12" cy="10" r="2"/>
</svg> </svg>
<span class="tooltip">Artery</span> </div>
</a>
<a href="/atlas" class="sidebar-item" title="Atlas"> <div class="sidebar-icon" title="Atlas">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="8"/> <circle cx="12" cy="12" r="8"/>
<path d="M12 4v16M4 12h16"/> <path d="M12 4v16M4 12h16"/>
</svg> </svg>
<span class="tooltip">Atlas</span> </div>
</a>
<a href="/station" class="sidebar-item" title="Station"> <div class="sidebar-icon" title="Station">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="4" y="6" width="16" height="12" rx="1"/> <rect x="4" y="6" width="16" height="12" rx="1"/>
<circle cx="9" cy="11" r="2"/> <circle cx="9" cy="11" r="2"/>
<circle cx="15" cy="11" r="2"/> <circle cx="15" cy="11" r="2"/>
</svg> </svg>
<span class="tooltip">Station</span> </div>
</a>
</nav> </nav>
{% endif %} {% endif %}

View File

@@ -1,73 +1,73 @@
/* Soleprint Sidebar - Injected Styles */ /* Soleprint Sidebar - Injected Styles */
/* Matches the original Jinja2 sidebar look */
:root {
--spr-sidebar-width: 60px;
--spr-sidebar-width-expanded: 280px;
--spr-sidebar-bg: #1a1a1a;
--spr-sidebar-text: #e5e5e5;
--spr-sidebar-text-muted: #a3a3a3;
--spr-sidebar-border: #333;
--spr-sidebar-accent: #d4a574;
--spr-sidebar-hover: #2a2a2a;
}
/* Sidebar Container */ /* Sidebar Container */
#spr-sidebar { #spr-sidebar {
position: fixed; position: fixed;
left: 0;
top: 0; top: 0;
width: var(--spr-sidebar-width); left: 0;
width: 60px;
height: 100vh; height: 100vh;
background: var(--spr-sidebar-bg); background: #1a1a1a;
border-right: 1px solid var(--spr-sidebar-border); border-right: 1px solid #333;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center;
padding: 1rem 0;
z-index: 99999; z-index: 99999;
transition: width 0.2s ease;
font-family: font-family:
system-ui, system-ui,
-apple-system, -apple-system,
sans-serif; sans-serif;
transition: width 0.2s ease;
} }
#spr-sidebar.expanded { #spr-sidebar.expanded {
width: var(--spr-sidebar-width-expanded); width: 200px;
align-items: flex-start;
padding: 1rem;
} }
/* Push page content */ /* Push page content */
body.spr-sidebar-active { body.spr-sidebar-active {
margin-left: var(--spr-sidebar-width) !important; margin-left: 60px !important;
transition: margin-left 0.2s ease; transition: margin-left 0.2s ease;
} }
body.spr-sidebar-active.spr-sidebar-expanded { body.spr-sidebar-active.spr-sidebar-expanded {
margin-left: var(--spr-sidebar-width-expanded) !important; margin-left: 200px !important;
} }
/* Sidebar Items */ /* Sidebar Items (clickable) */
.spr-sidebar-item { .spr-sidebar-item {
width: 44px;
height: 44px;
display: flex; display: flex;
align-items: center; align-items: center;
gap: 12px; justify-content: center;
padding: 12px 18px; border-radius: 8px;
color: var(--spr-sidebar-text-muted); margin-bottom: 0.5rem;
text-decoration: none; text-decoration: none;
transition: all 0.15s; color: #a3a3a3;
cursor: pointer; transition: all 0.2s;
border: none; position: relative;
background: none; flex-shrink: 0;
}
#spr-sidebar.expanded .spr-sidebar-item {
width: 100%; width: 100%;
text-align: left; justify-content: flex-start;
font-size: 14px; padding: 0 12px;
gap: 12px;
} }
.spr-sidebar-item:hover { .spr-sidebar-item:hover {
background: var(--spr-sidebar-hover); background: #333;
color: var(--spr-sidebar-text); color: white;
} }
.spr-sidebar-item.active { .spr-sidebar-item.active {
background: var(--spr-sidebar-accent); background: #d4a574;
color: #0a0a0a; color: #0a0a0a;
} }
@@ -77,8 +77,10 @@ body.spr-sidebar-active.spr-sidebar-expanded {
flex-shrink: 0; flex-shrink: 0;
} }
/* Label (hidden when collapsed) */
.spr-sidebar-item .label { .spr-sidebar-item .label {
display: none; display: none;
font-size: 0.9rem;
white-space: nowrap; white-space: nowrap;
} }
@@ -86,76 +88,94 @@ body.spr-sidebar-active.spr-sidebar-expanded {
display: inline; display: inline;
} }
/* Divider */ /* Tooltip (hidden when expanded) */
.spr-sidebar-divider { .spr-sidebar-item .tooltip {
height: 1px; position: absolute;
background: var(--spr-sidebar-border); left: 54px;
margin: 8px 16px; background: #333;
color: white;
padding: 0.5rem 0.75rem;
border-radius: 4px;
font-size: 0.85rem;
white-space: nowrap;
opacity: 0;
pointer-events: none;
transition: opacity 0.2s;
} }
/* Spacer */ .spr-sidebar-item:hover .tooltip {
opacity: 1;
}
#spr-sidebar.expanded .spr-sidebar-item .tooltip {
display: none;
}
/* Toggle button */
.spr-toggle {
border: none;
background: none;
cursor: pointer;
}
/* Divider */
.spr-sidebar-divider {
width: 32px;
height: 1px;
background: #333;
margin: 0.5rem 0;
}
/* Decorative icons (non-clickable) */
.spr-sidebar-icon {
width: 44px;
height: 44px;
display: flex;
align-items: center;
justify-content: center;
color: #555;
margin-bottom: 0.5rem;
}
.spr-sidebar-icon svg {
width: 20px;
height: 20px;
}
/* Spacer to push auth to bottom */
.spr-sidebar-spacer { .spr-sidebar-spacer {
flex: 1; flex: 1;
} }
/* User Section */ /* User/Auth Section */
.spr-sidebar-user { .spr-sidebar-user {
padding: 12px 16px; margin-top: auto;
border-top: 1px solid var(--spr-sidebar-border); display: flex;
font-size: 12px; flex-direction: column;
color: var(--spr-sidebar-text-muted); align-items: center;
}
.spr-sidebar-user .email {
display: none;
margin-top: 4px;
color: var(--spr-sidebar-text);
}
#spr-sidebar.expanded .spr-sidebar-user .email {
display: block;
} }
/* Login Button */ /* Login Button */
.spr-login-btn { .spr-login-btn {
width: 44px;
height: 44px;
display: flex; display: flex;
align-items: center; align-items: center;
gap: 8px;
padding: 8px 12px;
background: #4285f4;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 13px;
width: 100%;
justify-content: center; justify-content: center;
border-radius: 8px;
background: none;
border: none;
cursor: pointer;
color: #a3a3a3;
transition: all 0.2s;
} }
.spr-login-btn:hover { .spr-login-btn:hover {
background: #3367d6; background: #333;
color: white;
} }
.spr-login-btn svg { .spr-login-btn svg {
width: 18px; width: 24px;
height: 18px; height: 24px;
}
/* Header with room name */
.spr-sidebar-header {
padding: 16px;
border-bottom: 1px solid var(--spr-sidebar-border);
}
.spr-sidebar-header .room-name {
display: none;
font-size: 12px;
text-transform: uppercase;
letter-spacing: 1px;
color: var(--spr-sidebar-accent);
margin-top: 8px;
}
#spr-sidebar.expanded .spr-sidebar-header .room-name {
display: block;
} }

View File

@@ -1,5 +1,5 @@
// Soleprint Sidebar - Self-Injecting Script // Soleprint Sidebar - Self-Injecting Script
// This script creates and manages the soleprint sidebar when injected into a managed app // Matches the original Jinja2 sidebar look
(function () { (function () {
"use strict"; "use strict";
@@ -8,12 +8,14 @@
let config = null; let config = null;
let user = null; let user = null;
let expanded = localStorage.getItem("spr_sidebar_expanded") === "true"; let expanded = localStorage.getItem("spr_sidebar_expanded") === "true";
// Icons as SVG strings // Icons as SVG strings
const icons = { const icons = {
toggle: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> toggle: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M4 6h16M4 12h16M4 18h16"/> <rect x="3" y="3" width="18" height="18" rx="2"/>
<path d="M9 3v18M3 9h6"/>
</svg>`, </svg>`,
home: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> home: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M3 12l9-9 9 9M5 10v10a1 1 0 001 1h3m10-11v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1"/> <path d="M3 12l9-9 9 9M5 10v10a1 1 0 001 1h3m10-11v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1"/>
@@ -64,14 +66,6 @@
// Create sidebar // Create sidebar
createSidebar(); createSidebar();
// Setup keyboard shortcut
document.addEventListener("keydown", (e) => {
if (e.ctrlKey && e.shiftKey && e.key === "S") {
e.preventDefault();
toggleSidebar();
}
});
console.log("[Soleprint] Sidebar initialized for room:", config.room); console.log("[Soleprint] Sidebar initialized for room:", config.room);
} catch (error) { } catch (error) {
console.error("[Soleprint] Failed to initialize sidebar:", error); console.error("[Soleprint] Failed to initialize sidebar:", error);
@@ -101,95 +95,90 @@
document.body.classList.add("spr-sidebar-expanded"); document.body.classList.add("spr-sidebar-expanded");
} }
const sidebar = document.createElement("div"); const sidebar = document.createElement("nav");
sidebar.id = "spr-sidebar"; sidebar.id = "spr-sidebar";
if (expanded) sidebar.classList.add("expanded"); if (expanded) sidebar.classList.add("expanded");
sidebar.innerHTML = ` sidebar.innerHTML = `
<div class="spr-sidebar-header"> <button class="spr-sidebar-item spr-toggle" title="Toggle sidebar">
<button class="spr-sidebar-item" onclick="sprSidebar.toggle()" title="Toggle sidebar (Ctrl+Shift+S)"> ${icons.toggle}
${icons.toggle} <span class="label">Menu</span>
<span class="label">Menu</span> <span class="tooltip">Toggle</span>
</button> </button>
<div class="room-name">${config.room}</div>
</div>
<a href="/" class="spr-sidebar-item" title="Home"> <a href="/" class="spr-sidebar-item" title="${config.room}">
${icons.home} ${icons.home}
<span class="label">Home</span> <span class="label">${config.room}</span>
<span class="tooltip">${config.room}</span>
</a> </a>
<div class="spr-sidebar-divider"></div> <div class="spr-sidebar-divider"></div>
<a href="${SPR_BASE}/" class="spr-sidebar-item" title="Soleprint"> <a href="${SPR_BASE}/" class="spr-sidebar-item active" title="Soleprint">
${icons.soleprint} ${icons.soleprint}
<span class="label">Soleprint</span> <span class="label">Soleprint</span>
<span class="tooltip">Soleprint</span>
</a> </a>
<a href="${config.tools.artery}" class="spr-sidebar-item" title="Artery"> <div class="spr-sidebar-divider"></div>
<div class="spr-sidebar-icon" title="Artery">
${icons.artery} ${icons.artery}
<span class="label">Artery</span> </div>
</a>
<a href="${config.tools.atlas}" class="spr-sidebar-item" title="Atlas"> <div class="spr-sidebar-icon" title="Atlas">
${icons.atlas} ${icons.atlas}
<span class="label">Atlas</span> </div>
</a>
<a href="${config.tools.station}" class="spr-sidebar-item" title="Station"> <div class="spr-sidebar-icon" title="Station">
${icons.station} ${icons.station}
<span class="label">Station</span> </div>
</a>
<div class="spr-sidebar-spacer"></div> <div class="spr-sidebar-spacer"></div>
${config.auth_enabled ? renderAuthSection() : ""} ${config.auth_enabled ? renderAuthSection() : ""}
`; `;
// Add toggle click handler
sidebar
.querySelector(".spr-toggle")
.addEventListener("click", toggleSidebar);
document.body.appendChild(sidebar); document.body.appendChild(sidebar);
} }
function toggleSidebar() {
const sidebar = document.getElementById("spr-sidebar");
expanded = !expanded;
sidebar.classList.toggle("expanded", expanded);
document.body.classList.toggle("spr-sidebar-expanded", expanded);
localStorage.setItem("spr_sidebar_expanded", expanded);
}
function renderAuthSection() { function renderAuthSection() {
if (user) { if (user) {
return ` return `
<div class="spr-sidebar-user"> <div class="spr-sidebar-user">
<div class="spr-sidebar-item" title="${user.email}"> <a href="${config.auth.logout_url}" class="spr-sidebar-item" title="Logout (${user.email})">
${icons.user}
<span class="label">${user.email}</span>
</div>
<a href="${config.auth.logout_url}" class="spr-sidebar-item" title="Logout">
${icons.logout} ${icons.logout}
<span class="label">Logout</span> <span class="label">Logout</span>
<span class="tooltip">Logout</span>
</a> </a>
</div> </div>
`; `;
} else { } else {
return ` return `
<div class="spr-sidebar-user"> <div class="spr-sidebar-user">
<a href="${config.auth.login_url}" class="spr-sidebar-item spr-login-btn" title="Login with Google"> <a href="${config.auth.login_url}" class="spr-sidebar-item" title="Login with Google">
${icons.google} ${icons.google}
<span class="label">Login with Google</span> <span class="label">Login</span>
<span class="tooltip">Login</span>
</a> </a>
</div> </div>
`; `;
} }
} }
function toggleSidebar() {
const sidebar = document.getElementById("spr-sidebar");
expanded = !expanded;
sidebar.classList.toggle("expanded", expanded);
document.body.classList.toggle("spr-sidebar-expanded", expanded);
localStorage.setItem("spr_sidebar_expanded", expanded);
}
// Expose to global scope for onclick handlers
window.sprSidebar = {
toggle: toggleSidebar,
};
// Initialize when DOM is ready // Initialize when DOM is ready
if (document.readyState === "loading") { if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", init); document.addEventListener("DOMContentLoaded", init);