frontend: "verworfene"-Toggle als kompakter Icon-Button

Der breite Schalter mit Text wird ein schmaler Druck-Button (29px statt
Schalter+Label): Symbol = gestrichelte Box mit Durchstreichung (spiegelt
den verworfenen Knoten), aria-pressed als Ein/Aus-Zustand (gedrueckt =
petrol gefuellt), Erklaerung per Tooltip (discardedTooltip). Ersetzt die
Checkbox #showc; Zustand jetzt ueber aria-pressed (discardedShown/
setDiscarded), unveraendert in Filter, Speichern und Wiederherstellen.

Verifiziert (headless): Button toggelt aria-pressed + Petrol-Fuellung,
blendet verworfene Knoten ein/aus, Zustand ueberlebt Reload. Gilt auf
allen Bildschirmen (spart auch mobil Platz).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
mhoennig
2026-07-21 14:40:29 +02:00
co-authored by Claude Opus 4.8
parent 924ca5aaee
commit cb440af362
+12 -9
View File
@@ -251,6 +251,8 @@
.dlbtn{gap:3px} .dlbtn{gap:3px}
.dl-label{font-family:'IBM Plex Mono',monospace;font-size:.62rem;font-weight:600;letter-spacing:.02em} .dl-label{font-family:'IBM Plex Mono',monospace;font-size:.62rem;font-weight:600;letter-spacing:.02em}
.legendbtn{display:none} /* nur auf kleinem Bildschirm sichtbar */ .legendbtn{display:none} /* nur auf kleinem Bildschirm sichtbar */
.togglebtn[aria-pressed="true"]{background:var(--or);color:#fff;border-color:var(--or)}
.togglebtn[aria-pressed="true"]:hover{color:#fff}
textarea{ textarea{
display:block;width:100%;min-height:0; display:block;width:100%;min-height:0;
border:0;outline:none;resize:none; border:0;outline:none;resize:none;
@@ -600,9 +602,9 @@
<div class="panel right"> <div class="panel right">
<div class="panel-head"> <div class="panel-head">
<span data-i18n="diagramTitle">Diagramm</span> <span data-i18n="diagramTitle">Diagramm</span>
<label class="switch" data-i18n-title="discardedTooltip" title="Verworfene Knoten samt Teilbaum ein-/ausblenden"> <button type="button" class="copybtn togglebtn" id="showc" aria-pressed="false" data-i18n-title="discardedTooltip" data-i18n-aria="discardedTooltip" title="Verworfene Knoten samt Teilbaum ein-/ausblenden" aria-label="Verworfene Knoten samt Teilbaum ein-/ausblenden">
<input type="checkbox" id="showc"><i></i><span data-i18n="discarded">verworfene</span> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="6" width="18" height="12" rx="2" stroke-dasharray="3 2.5"/><path d="M7 12h10"/></svg>
</label> </button>
<div class="seg" role="radiogroup" aria-label="Darstellung"> <div class="seg" role="radiogroup" aria-label="Darstellung">
<label data-i18n-title="modeHorizontal" title="Horizontal Organigramm, Diagramm über dem Editor"> <label data-i18n-title="modeHorizontal" title="Horizontal Organigramm, Diagramm über dem Editor">
<input type="radio" name="layout" value="horizontal" checked data-i18n-aria="modeHorizontal" aria-label="Horizontal Organigramm"> <input type="radio" name="layout" value="horizontal" checked data-i18n-aria="modeHorizontal" aria-label="Horizontal Organigramm">
@@ -726,7 +728,7 @@ function needsBreakdown(n){
} }
function visibleChildren(n){ function visibleChildren(n){
if(showc.checked) return n.children; if(discardedShown()) return n.children;
return n.children.filter(k => !k.status || k.status.key !== 'verworfen'); return n.children.filter(k => !k.status || k.status.key !== 'verworfen');
} }
@@ -772,7 +774,7 @@ function renderChildren(node, warnings){
function render(){ function render(){
let {roots} = parse(src.value); let {roots} = parse(src.value);
const warnings = []; const warnings = [];
if(!showc.checked){ if(!discardedShown()){
roots = roots.filter(r => !r.status || r.status.key !== 'verworfen'); roots = roots.filter(r => !r.status || r.status.key !== 'verworfen');
} }
@@ -1085,8 +1087,9 @@ diagramEl.addEventListener('wheel', e => {
}, {passive:false}); }, {passive:false});
const showc = document.getElementById('showc'); const showc = document.getElementById('showc');
showc.addEventListener('change', render); function discardedShown(){ return showc.getAttribute('aria-pressed') === 'true'; }
showc.addEventListener('change', saveUI); function setDiscarded(on){ showc.setAttribute('aria-pressed', on ? 'true' : 'false'); }
showc.addEventListener('click', () => { setDiscarded(!discardedShown()); render(); saveUI(); });
/* ---------- In die Zwischenablage kopieren ---------- */ /* ---------- In die Zwischenablage kopieren ---------- */
async function writeClipboard(text){ async function writeClipboard(text){
@@ -1511,7 +1514,7 @@ function saveUI(){
const modeEl = document.querySelector('input[name="layout"]:checked'); const modeEl = document.querySelector('input[name="layout"]:checked');
localStorage.setItem(LS_UI, JSON.stringify({ localStorage.setItem(LS_UI, JSON.stringify({
mode: modeEl ? modeEl.value : 'horizontal', mode: modeEl ? modeEl.value : 'horizontal',
discarded: showc.checked, discarded: discardedShown(),
split: splitState, split: splitState,
col: app.style.getPropertyValue('--col') || null, col: app.style.getPropertyValue('--col') || null,
drow: app.style.getPropertyValue('--drow') || null, drow: app.style.getPropertyValue('--drow') || null,
@@ -1531,7 +1534,7 @@ function restoreState(){
const modeEl = document.querySelector('input[name="layout"][value="' + mode + '"]'); const modeEl = document.querySelector('input[name="layout"][value="' + mode + '"]');
if(modeEl) modeEl.checked = true; if(modeEl) modeEl.checked = true;
if(ui){ if(ui){
if(typeof ui.discarded === 'boolean') showc.checked = ui.discarded; if(typeof ui.discarded === 'boolean') setDiscarded(ui.discarded);
if(typeof ui.zoom === 'number') zoom = ui.zoom; if(typeof ui.zoom === 'number') zoom = ui.zoom;
if(ui.split) splitState = ui.split; if(ui.split) splitState = ui.split;
if(ui.fullscreen){ if(ui.fullscreen){