From e8fc294c5d39bfcf6fee77058111f0d9a2262359 Mon Sep 17 00:00:00 2001 From: DonVoo Date: Sun, 12 Jul 2026 23:46:44 +0200 Subject: [PATCH] Add top transfer dropdown --- backend/00-router.go | 55 +++++++++++++++++++++++++++----------- frontend-js/dist/app.js | 27 +++++++++++++++++++ frontend-js/dist/style.css | 47 ++++++++++++++++++++++++++++++++ 3 files changed, 113 insertions(+), 16 deletions(-) diff --git a/backend/00-router.go b/backend/00-router.go index 15315e6..82fc8c2 100644 --- a/backend/00-router.go +++ b/backend/00-router.go @@ -57,15 +57,15 @@ func renderShell(w http.ResponseWriter, active, readingPane string) { fmt.Fprintf(w, ` Mail-Graveyard - + - +
Mail-Graveyard
@@ -98,7 +98,7 @@ func renderShell(w http.ResponseWriter, active, readingPane string) {
bereit
-`, active, renderInitialReadPane(readingPane)) +`, active, renderRibbonTransferMenu(""), renderInitialReadPane(readingPane)) } func accountsHandler(w http.ResponseWriter, r *http.Request) { @@ -312,15 +312,15 @@ func renderAccountsPage(w http.ResponseWriter, accounts []Account, edit Account, fmt.Fprintf(w, ` Konten-Verwaltung - Mail-Graveyard - + - +
Mail-Graveyard
@@ -337,7 +337,7 @@ func renderAccountsPage(w http.ResponseWriter, accounts []Account, edit Account, Einstellungen -
`) +
`, renderRibbonTransferMenu("")) if msg != "" { fmt.Fprintf(w, `
%s
`, html.EscapeString(msg)) } @@ -356,15 +356,15 @@ func renderArchivesPage(w http.ResponseWriter, archives []string, accounts []Acc fmt.Fprintf(w, ` Archiv-mbox Verwaltung - Mail-Graveyard - + - +
Mail-Graveyard
@@ -381,7 +381,7 @@ func renderArchivesPage(w http.ResponseWriter, archives []string, accounts []Acc Einstellungen -
`) +
`, renderRibbonTransferMenu("")) if msg != "" { fmt.Fprintf(w, `
%s
`, html.EscapeString(msg)) } @@ -423,15 +423,15 @@ func renderTransferPage(w http.ResponseWriter, mode transferMode, accounts []Acc fmt.Fprintf(w, ` %s - Mail-Graveyard - + - +
Mail-Graveyard
@@ -453,7 +453,7 @@ func renderTransferPage(w http.ResponseWriter, mode transferMode, accounts []Acc
bereit
`, - html.EscapeString(mode.Title), transferMenuItems(mode.Slug), + html.EscapeString(mode.Title), renderRibbonTransferMenu(mode.Slug), transferMenuItems(mode.Slug), html.EscapeString(mode.LeftTitle), renderTransferPicker(mode.LeftKind, accounts, archives), html.EscapeString(mode.RightTitle), renderTransferPicker(mode.RightKind, accounts, archives)) } @@ -475,6 +475,29 @@ func transferMenuItems(active string) string { return b.String() } +func renderRibbonTransferMenu(active string) string { + items := []transferMode{ + {Slug: "postfach-archiv", Title: "Postfach <--> Archiv-MBox"}, + {Slug: "archiv-postfach", Title: "Archiv-MBox <--> Postfach"}, + {Slug: "postfach-postfach", Title: "Postfach <--> Postfach"}, + } + buttonClass := "tab ribbon-menu-button" + if active != "" { + buttonClass += " active" + } + var b strings.Builder + fmt.Fprintf(&b, `
`, buttonClass) + for _, item := range items { + class := "ribbon-dropdown-item" + if item.Slug == active { + class += " active" + } + fmt.Fprintf(&b, `%s`, class, item.Slug, html.EscapeString(item.Title)) + } + b.WriteString(`
`) + return b.String() +} + func renderTransferPicker(kind string, accounts []Account, archives []string) string { var b strings.Builder b.WriteString(`
`) diff --git a/frontend-js/dist/app.js b/frontend-js/dist/app.js index a5008bf..5ceb818 100644 --- a/frontend-js/dist/app.js +++ b/frontend-js/dist/app.js @@ -93,6 +93,33 @@ window.addEventListener("DOMContentLoaded", () => bind(document.querySelector(".three-pane"))); })(); +(function () { + function closeAll() { + document.querySelectorAll(".ribbon-menu.open").forEach((menu) => { + menu.classList.remove("open"); + const button = menu.querySelector("[data-ribbon-menu-toggle]"); + if (button) button.setAttribute("aria-expanded", "false"); + }); + } + + document.addEventListener("click", (event) => { + const button = event.target.closest("[data-ribbon-menu-toggle]"); + if (button) { + const menu = button.closest(".ribbon-menu"); + const willOpen = !menu.classList.contains("open"); + closeAll(); + menu.classList.toggle("open", willOpen); + button.setAttribute("aria-expanded", willOpen ? "true" : "false"); + return; + } + if (!event.target.closest(".ribbon-menu")) closeAll(); + }); + + document.addEventListener("keydown", (event) => { + if (event.key === "Escape") closeAll(); + }); +})(); + (function () { function setOpen(open) { document.body.classList.toggle("backstage-open", open); diff --git a/frontend-js/dist/style.css b/frontend-js/dist/style.css index 18aa4d5..5250476 100644 --- a/frontend-js/dist/style.css +++ b/frontend-js/dist/style.css @@ -60,9 +60,56 @@ body.ol2013 { padding: 0 16px; height: 100%; color: #eaf3fb; text-decoration: none; border-bottom: 3px solid transparent; + background: transparent; + border-left: 0; + border-right: 0; + border-top: 0; + font: inherit; + cursor: pointer; } .tab:hover { background: var(--ol-blue-dark); color: #fff; } .tab.active { background: #fff; color: var(--ol-blue); border-bottom-color: #fff; } +.ribbon-menu { + position: relative; + height: 100%; +} +.ribbon-menu-button::after { + content: ""; + width: 0; + height: 0; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 5px solid currentColor; +} +.ribbon-dropdown { + position: absolute; + top: 44px; + left: 0; + min-width: 238px; + background: #fff; + color: var(--ol-text); + border: 1px solid var(--ol-border); + box-shadow: 0 7px 18px rgba(0, 0, 0, .18); + display: none; + z-index: 25; +} +.ribbon-menu.open .ribbon-dropdown { display: block; } +.ribbon-dropdown-item { + display: block; + padding: 9px 13px; + color: var(--ol-text); + text-decoration: none; + border-left: 3px solid transparent; +} +.ribbon-dropdown-item:hover { + background: #eef6fd; +} +.ribbon-dropdown-item.active { + color: var(--ol-blue-dark); + background: var(--ol-sel); + border-left-color: var(--ol-blue); + font-weight: 600; +} .mail-logo { position: relative; width: 17px;