fix: move dashboard actions into compact menu
All checks were successful
Build & Push Docker Image to Gitea Registry / build-and-push (push) Successful in 12s

This commit is contained in:
Kroonk
2026-05-22 00:02:51 +02:00
parent ae775c4dcf
commit df0a5d5035
7 changed files with 168 additions and 39 deletions

View File

@@ -12,7 +12,7 @@
<link rel="icon" type="image/png" sizes="48x48" href="/icons/favicon-48-v4.png"> <link rel="icon" type="image/png" sizes="48x48" href="/icons/favicon-48-v4.png">
<link rel="icon" type="image/png" sizes="192x192" href="/icons/favicon-192-v4.png"> <link rel="icon" type="image/png" sizes="192x192" href="/icons/favicon-192-v4.png">
<link rel="apple-touch-icon" href="/icons/apple-touch-icon-v4.png"> <link rel="apple-touch-icon" href="/icons/apple-touch-icon-v4.png">
<link rel="stylesheet" href="/style.css?v=29"> <link rel="stylesheet" href="/style.css?v=30">
</head> </head>
<body> <body>
<header class="shell hero admin-hero"> <header class="shell hero admin-hero">

37
app.js
View File

@@ -35,6 +35,8 @@ const logoutButton = document.querySelector('#dashboardLogoutButton');
const favoritesLink = document.querySelector('#favoritesLink'); const favoritesLink = document.querySelector('#favoritesLink');
const adminPanelLink = document.querySelector('#adminPanelLink'); const adminPanelLink = document.querySelector('#adminPanelLink');
const userBadge = document.querySelector('#dashboardUserBadge'); const userBadge = document.querySelector('#dashboardUserBadge');
const dashboardMenuButton = document.querySelector('#dashboardMenuButton');
const dashboardMenuPanel = document.querySelector('#dashboardMenuPanel');
function normalize(value) { function normalize(value) {
return String(value || '').toLowerCase().trim(); return String(value || '').toLowerCase().trim();
@@ -491,6 +493,23 @@ viewOptions.forEach((option) => {
searchInput.addEventListener('input', updateVisibility); searchInput.addEventListener('input', updateVisibility);
function closeDashboardMenu() {
if (!dashboardMenuButton || !dashboardMenuPanel) return;
dashboardMenuButton.setAttribute('aria-expanded', 'false');
dashboardMenuButton.classList.remove('is-open');
dashboardMenuPanel.classList.remove('is-open');
dashboardMenuPanel.hidden = true;
}
function toggleDashboardMenu() {
if (!dashboardMenuButton || !dashboardMenuPanel) return;
const isOpen = dashboardMenuButton.getAttribute('aria-expanded') === 'true';
dashboardMenuButton.setAttribute('aria-expanded', String(!isOpen));
dashboardMenuButton.classList.toggle('is-open', !isOpen);
dashboardMenuPanel.classList.toggle('is-open', !isOpen);
dashboardMenuPanel.hidden = isOpen;
}
function updateAuthNav() { function updateAuthNav() {
const authenticated = MischLabsAuth.isAuthenticated(); const authenticated = MischLabsAuth.isAuthenticated();
const claims = MischLabsAuth.claims(); const claims = MischLabsAuth.claims();
@@ -507,6 +526,24 @@ function updateAuthNav() {
} }
} }
dashboardMenuButton?.addEventListener('click', (event) => {
event.stopPropagation();
toggleDashboardMenu();
});
document.addEventListener('click', (event) => {
if (!dashboardMenuPanel || dashboardMenuPanel.hidden) return;
if (!event.target.closest('.dashboard-menu')) {
closeDashboardMenu();
}
});
document.addEventListener('keydown', (event) => {
if (event.key === 'Escape') {
closeDashboardMenu();
}
});
loginButton?.addEventListener('click', () => MischLabsAuth.login()); loginButton?.addEventListener('click', () => MischLabsAuth.login());
logoutButton?.addEventListener('click', () => MischLabsAuth.logout()); logoutButton?.addEventListener('click', () => MischLabsAuth.logout());

View File

@@ -12,7 +12,7 @@
<link rel="icon" type="image/png" sizes="48x48" href="/icons/favicon-48-v4.png"> <link rel="icon" type="image/png" sizes="48x48" href="/icons/favicon-48-v4.png">
<link rel="icon" type="image/png" sizes="192x192" href="/icons/favicon-192-v4.png"> <link rel="icon" type="image/png" sizes="192x192" href="/icons/favicon-192-v4.png">
<link rel="apple-touch-icon" href="/icons/apple-touch-icon-v4.png"> <link rel="apple-touch-icon" href="/icons/apple-touch-icon-v4.png">
<link rel="stylesheet" href="/style.css?v=29"> <link rel="stylesheet" href="/style.css?v=30">
</head> </head>
<body> <body>
<header class="shell hero admin-hero"> <header class="shell hero admin-hero">

View File

@@ -15,7 +15,7 @@
<link rel="icon" type="image/png" sizes="48x48" href="/icons/favicon-48-v4.png"> <link rel="icon" type="image/png" sizes="48x48" href="/icons/favicon-48-v4.png">
<link rel="icon" type="image/png" sizes="192x192" href="/icons/favicon-192-v4.png"> <link rel="icon" type="image/png" sizes="192x192" href="/icons/favicon-192-v4.png">
<link rel="apple-touch-icon" href="/icons/apple-touch-icon-v4.png"> <link rel="apple-touch-icon" href="/icons/apple-touch-icon-v4.png">
<link rel="stylesheet" href="style.css?v=29"> <link rel="stylesheet" href="style.css?v=30">
</head> </head>
<body> <body>
<header class="shell hero"> <header class="shell hero">
@@ -43,13 +43,20 @@
</div> </div>
</div> </div>
<nav class="dashboard-actions" aria-label="Dashboard Aktionen"> <div class="dashboard-menu">
<span class="user-badge" id="dashboardUserBadge" hidden></span> <button class="dashboard-menu-button" id="dashboardMenuButton" type="button" aria-label="Menue oeffnen" aria-expanded="false" aria-controls="dashboardMenuPanel">
<a class="ghost-button mini" id="adminPanelLink" href="/admin.html" hidden>Admin Panel</a> <span></span>
<a class="ghost-button mini" id="favoritesLink" href="/favorites.html" hidden>Favoriten</a> <span></span>
<button class="ghost-button mini" id="dashboardLoginButton" type="button">SSO Login</button> <span></span>
<button class="ghost-button mini" id="dashboardLogoutButton" type="button" hidden>Abmelden</button> </button>
</nav> <nav class="dashboard-menu-panel" id="dashboardMenuPanel" aria-label="Dashboard Aktionen" hidden>
<span class="dashboard-menu-user" id="dashboardUserBadge" hidden></span>
<a class="dashboard-menu-item" id="adminPanelLink" href="/admin.html" hidden>Admin Panel</a>
<a class="dashboard-menu-item" id="favoritesLink" href="/favorites.html" hidden>Favoriten verwalten</a>
<button class="dashboard-menu-item" id="dashboardLoginButton" type="button">SSO Login</button>
<button class="dashboard-menu-item is-danger" id="dashboardLogoutButton" type="button" hidden>Abmelden</button>
</nav>
</div>
</header> </header>
<main class="shell"> <main class="shell">
@@ -135,6 +142,6 @@
</div> </div>
<script src="/auth.js?v=2" defer></script> <script src="/auth.js?v=2" defer></script>
<script src="/app.js?v=35" defer></script> <script src="/app.js?v=36" defer></script>
</body> </body>
</html> </html>

View File

@@ -11,7 +11,7 @@
<link rel="icon" type="image/png" sizes="48x48" href="/icons/favicon-48-v4.png"> <link rel="icon" type="image/png" sizes="48x48" href="/icons/favicon-48-v4.png">
<link rel="icon" type="image/png" sizes="192x192" href="/icons/favicon-192-v4.png"> <link rel="icon" type="image/png" sizes="192x192" href="/icons/favicon-192-v4.png">
<link rel="apple-touch-icon" href="/icons/apple-touch-icon-v4.png"> <link rel="apple-touch-icon" href="/icons/apple-touch-icon-v4.png">
<link rel="stylesheet" href="/style.css?v=29"> <link rel="stylesheet" href="/style.css?v=30">
</head> </head>
<body> <body>
<main class="shell hero"> <main class="shell hero">

133
style.css
View File

@@ -60,9 +60,9 @@ input {
.hero { .hero {
display: grid; display: grid;
grid-template-columns: minmax(0, 1fr) auto; grid-template-columns: minmax(0, 1fr) auto auto;
gap: 24px; gap: 16px;
align-items: end; align-items: start;
padding: 32px 0 22px; padding: 32px 0 22px;
} }
@@ -119,27 +119,106 @@ h1 {
display: grid; display: grid;
grid-template-columns: repeat(3, minmax(82px, 1fr)); grid-template-columns: repeat(3, minmax(82px, 1fr));
gap: 10px; gap: 10px;
margin-top: 12px;
} }
.dashboard-actions { .dashboard-menu {
grid-column: 1 / -1; position: relative;
display: flex; z-index: 30;
justify-content: flex-end; margin-top: 12px;
align-items: center;
gap: 8px;
margin-top: -10px;
} }
.user-badge { .dashboard-menu-button {
min-height: 34px; width: 42px;
display: inline-flex; height: 42px;
align-items: center; display: inline-grid;
padding: 0 12px; place-content: center;
color: #c4f1ff; gap: 5px;
background: rgba(17, 22, 36, 0.72); color: #d8e7ff;
background: rgba(17, 22, 36, 0.82);
border: 1px solid var(--border); border: 1px solid var(--border);
border-radius: var(--radius); border-radius: var(--radius);
font-size: 0.82rem; cursor: pointer;
transition: border-color 0.2s ease, background 0.2s ease, transform 0.2s ease;
}
.dashboard-menu-button span {
width: 17px;
height: 2px;
display: block;
background: currentColor;
border-radius: 999px;
}
.dashboard-menu-button:hover,
.dashboard-menu-button.is-open {
background: rgba(103, 232, 249, 0.12);
border-color: rgba(103, 232, 249, 0.38);
}
.dashboard-menu-button:active {
transform: translateY(1px);
}
.dashboard-menu-panel {
position: absolute;
top: calc(100% + 10px);
right: 0;
width: min(260px, calc(100vw - 32px));
display: grid;
gap: 6px;
padding: 10px;
background: rgba(9, 13, 26, 0.96);
border: 1px solid rgba(148, 163, 184, 0.22);
border-radius: 10px;
box-shadow: 0 22px 55px rgba(0, 0, 0, 0.42);
backdrop-filter: blur(18px);
}
.dashboard-menu-panel[hidden] {
display: none;
}
.dashboard-menu-user {
display: block;
padding: 9px 10px;
color: #c4f1ff;
border-bottom: 1px solid rgba(148, 163, 184, 0.14);
font-size: 0.78rem;
font-weight: 700;
}
.dashboard-menu-user[hidden] {
display: none;
}
.dashboard-menu-item {
min-height: 36px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 10px;
color: var(--text);
background: transparent;
border: 1px solid transparent;
border-radius: 8px;
font: inherit;
font-size: 0.84rem;
text-decoration: none;
cursor: pointer;
}
.dashboard-menu-item:hover {
background: rgba(148, 163, 184, 0.1);
border-color: rgba(148, 163, 184, 0.16);
}
.dashboard-menu-item[hidden] {
display: none;
}
.dashboard-menu-item.is-danger {
color: #fecdd3;
} }
.metric { .metric {
@@ -931,10 +1010,20 @@ main {
@media (max-width: 900px) { @media (max-width: 900px) {
.hero { .hero {
grid-template-columns: 1fr; grid-template-columns: minmax(0, 1fr) auto;
align-items: start; align-items: start;
} }
.brand {
grid-column: 1 / 2;
}
.dashboard-menu {
grid-column: 2 / 3;
grid-row: 1;
justify-self: end;
}
.admin-actions { .admin-actions {
justify-content: flex-start; justify-content: flex-start;
} }
@@ -960,14 +1049,10 @@ main {
} }
.hero-meta { .hero-meta {
grid-column: 1 / -1;
width: 100%; width: 100%;
} }
.dashboard-actions {
justify-content: flex-start;
margin-top: 0;
}
.control-bar { .control-bar {
grid-template-columns: 1fr; grid-template-columns: 1fr;
} }

6
sw.js
View File

@@ -1,12 +1,12 @@
const CACHE_NAME = 'mischlabs-pwa-v19'; const CACHE_NAME = 'mischlabs-pwa-v20';
const APP_SHELL = [ const APP_SHELL = [
'/', '/',
'/index.html', '/index.html',
'/favorites.html', '/favorites.html',
'/offline.html', '/offline.html',
'/style.css?v=29', '/style.css?v=30',
'/auth.js?v=2', '/auth.js?v=2',
'/app.js?v=35', '/app.js?v=36',
'/favorites.js?v=1', '/favorites.js?v=1',
'/services.json?v=1', '/services.json?v=1',
'/manifest.webmanifest?v=4', '/manifest.webmanifest?v=4',