frontend: Darstellung horizontal/vertikal/kompakt + graue Any-of-Linien
Der bisherige „vertikal"-Toggle wird zur dreistufigen Auswahl „horizontal / vertikal / kompakt", die zugleich das Seitenlayout wählt: - horizontal: Diagramm oben, Editor unten (je volle Breite), Agenda rechts im Editor aufklappbar. - vertikal: Editor links, Diagramm rechts; „all of" tritt rechts aus. - kompakt: wie vertikal, aber „all of" läuft nach unten (spart Breite); Gate nur noch über den Linienstil codiert. Zusätzlich wird das Petrol im Diagramm aufgegeben: any-of-Linien (Sammelleiste und Abzweige) sowie der Rahmen der Alternative-Knoten sind in allen Modi durchgehend gestrichelt bzw. grau (#6B7A8C). all-of bleibt durchgezogen in Tinte. Petrol nur noch für UI-Akzente und das Logo. Doku nachgezogen: SPEC §9 (Linienführung, drei Modi), DECISIONS D15, frontend/CLAUDE.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
9143743b43
commit
20b9d89f88
@@ -83,3 +83,22 @@ Notation nicht; es speichert den Text als Ganzes und bedient Integrationen
|
|||||||
über explizite Metadaten. Wird Backend-Parsen später doch erforderlich,
|
über explizite Metadaten. Wird Backend-Parsen später doch erforderlich,
|
||||||
gilt: docs/SPEC.md ist normativ, beide Parser testen gegen dieselben
|
gilt: docs/SPEC.md ist normativ, beide Parser testen gegen dieselben
|
||||||
Fixtures (SPEC §10) — es darf keine zweite, abweichende Grammatik entstehen.
|
Fixtures (SPEC §10) — es darf keine zweite, abweichende Grammatik entstehen.
|
||||||
|
|
||||||
|
## D15 — Kompakter Modus + graue Any-of-Linien in allen Modi
|
||||||
|
Der vertikale Modus (D9) lässt „all of“ rechts austreten — formal sauber,
|
||||||
|
aber breit. Der zusätzliche Modus **kompakt** führt beide Gates nach unten
|
||||||
|
(minimale Breite) und unterscheidet sie nur noch über den Linienstil:
|
||||||
|
durchgezogen = und, gestrichelt = oder. Auswahl dreistufig
|
||||||
|
„horizontal/vertikal/kompakt“ statt Toggle, da es nun drei sich
|
||||||
|
ausschließende Darstellungen sind.
|
||||||
|
|
||||||
|
Zugleich wird das **Petrol im Diagramm ganz aufgegeben**: die any-of-Linien
|
||||||
|
(Sammelleiste *und* Abzweige) und auch der **Rahmen der Alternative-Knoten**
|
||||||
|
sind in **allen** Modi **gestrichelt bzw. gerahmt in Grau** (`#6B7A8C`). Die
|
||||||
|
frühere durchgezogene Petrol-Sammelleiste und der petrolfarbene Knotenrahmen
|
||||||
|
entfallen. Begründung: Das Gate ist bereits durch den Linienstil (gestrichelt)
|
||||||
|
und die Anordnung codiert; die zusätzliche Signalfarbe wirkte laut und ließ die
|
||||||
|
durchgezogene Hauptlinie optisch mit „all of“ konkurrieren. Grau tritt zurück,
|
||||||
|
die gestrichelte Führung bleibt eindeutig. D12/BRAND — „durchgezogen = und,
|
||||||
|
gestrichelt = oder“ — gilt für das **Markenzeichen** unverändert (Logo behält
|
||||||
|
Petrol); im **Diagramm** trägt allein der Linienstil die Gate-Codierung.
|
||||||
|
|||||||
+23
-8
@@ -93,21 +93,36 @@ Codiert als Checkbox nach dem Zeichen (Erweiterung der Markdown-Task-Syntax):
|
|||||||
|
|
||||||
## 9. Darstellung
|
## 9. Darstellung
|
||||||
|
|
||||||
### Normalmodus
|
Drei Modi, umschaltbar über „horizontal / vertikal / kompakt“. Der Modus wählt
|
||||||
- **all of:** Kinder nebeneinander, klassischer Organigramm-Fächer,
|
zugleich die Seitenanordnung: **horizontal** stellt Diagramm über den Editor
|
||||||
durchgezogene Linien (Tinte `#41556E`).
|
(volle Breite), **vertikal** und **kompakt** stellen Editor und Diagramm
|
||||||
- **any of:** Alternativen untereinander; durchgezogene vertikale Linie links
|
nebeneinander (schmales Diagramm rechts).
|
||||||
unterhalb des Parents, **gestrichelte** Abzweige zu den Alternativen
|
|
||||||
(Petrol `#0F766E`). Alternative-Knoten mit petrolfarbenem Rahmen.
|
|
||||||
|
|
||||||
### Transponierter Modus (Toggle „schmal (vertikal)“)
|
**Linienführung (in allen Modi gleich):** all-of-Linien durchgezogen in Tinte
|
||||||
|
(`#41556E`); any-of-Linien — Haupt-/Sammelleiste **und** Abzweige — durchgehend
|
||||||
|
**gestrichelt in Grau** (`#6B7A8C`). Auch der **Rahmen der Alternative-Knoten**
|
||||||
|
ist grau (`#6B7A8C`) — kein Petrol mehr im Diagramm. Der Modus ändert nur die
|
||||||
|
**Anordnung**, nicht die Linienfarbe.
|
||||||
|
|
||||||
|
### Horizontal (Normalmodus)
|
||||||
|
- **all of:** Kinder nebeneinander, klassischer Organigramm-Fächer.
|
||||||
|
- **any of:** Alternativen untereinander; gestrichelte graue Sammelleiste links
|
||||||
|
unterhalb des Parents, gestrichelte graue Abzweige zu den Alternativen.
|
||||||
|
|
||||||
|
### Vertikal (transponiert)
|
||||||
- **all of:** Linie tritt **rechts auf halber Höhe** aus dem Parent aus
|
- **all of:** Linie tritt **rechts auf halber Höhe** aus dem Parent aus
|
||||||
(entspricht Richtung LR), vertikale Sammelleiste, durchgezogene Abzweige;
|
(entspricht Richtung LR), vertikale Sammelleiste, durchgezogene Abzweige;
|
||||||
Kinder rechts eingerückt untereinander.
|
Kinder rechts eingerückt untereinander.
|
||||||
- **any of:** unverändert — Austritt **unten links**, gestrichelte Abzweige.
|
- **any of:** Austritt **unten links**, gestrichelte graue Abzweige.
|
||||||
- Merkregel: Austrittsseite codiert das Gate (rechts = und, unten = oder),
|
- Merkregel: Austrittsseite codiert das Gate (rechts = und, unten = oder),
|
||||||
Linienstil bestätigt es.
|
Linienstil bestätigt es.
|
||||||
|
|
||||||
|
### Kompakt (transponiert, platzsparend)
|
||||||
|
- **Beide Gates** laufen **unten links** aus dem Parent heraus, Kinder
|
||||||
|
untereinander — kein Rechts-Fächer, dadurch minimale Breite.
|
||||||
|
- Das Gate wird hier allein über den **Linienstil** codiert (siehe D15):
|
||||||
|
und = durchgezogen (Tinte), oder = gestrichelt (Grau).
|
||||||
|
|
||||||
### Geometrie-Invarianten
|
### Geometrie-Invarianten
|
||||||
- Knoten haben feste Zeilenhöhe (`line-height: 1.3`), damit Abzweige
|
- Knoten haben feste Zeilenhöhe (`line-height: 1.3`), damit Abzweige
|
||||||
deterministisch auf Knotenmitte liegen (Offset 23 px = 5 px Listenabstand
|
deterministisch auf Knotenmitte liegen (Offset 23 px = 5 px Listenabstand
|
||||||
|
|||||||
+6
-1
@@ -14,7 +14,12 @@ Diagramm rechts, Toggles für transponierte Ansicht und verworfene Elemente).
|
|||||||
## Stolperfallen
|
## Stolperfallen
|
||||||
- Abzweig-Linien zielen auf die **Knotenmitte** (fester 23-px-Offset,
|
- Abzweig-Linien zielen auf die **Knotenmitte** (fester 23-px-Offset,
|
||||||
`line-height: 1.3`), nicht auf die Mitte des Teilbaums — bei Layout-
|
`line-height: 1.3`), nicht auf die Mitte des Teilbaums — bei Layout-
|
||||||
Änderungen beide Modi (normal + „schmal (vertikal)") prüfen.
|
Änderungen alle drei Modi (horizontal/vertikal/kompakt) prüfen.
|
||||||
|
Vertikal + kompakt teilen die transponierte Basis-CSS; nur vertikal
|
||||||
|
bekommt den Rechts-Ausgang für „all of“, kompakt führt auch „all of“
|
||||||
|
nach unten. Any-of ist in allen Modi grau: Linien gestrichelt grau und
|
||||||
|
Alternative-Rahmen grau (Basis-CSS `ul.or`). Kein Petrol im Diagramm mehr;
|
||||||
|
`var(--or)` nur noch für UI-Akzente/Logo (SPEC §9, D15).
|
||||||
- Extraktionsreihenfolge im Parser nicht umstellen: Kommentar → Zeichen/
|
- Extraktionsreihenfolge im Parser nicht umstellen: Kommentar → Zeichen/
|
||||||
Status → URL → Größe → Tags (sonst kollidiert `@` in URLs).
|
Status → URL → Größe → Tags (sonst kollidiert `@` in URLs).
|
||||||
- „verworfen" ist per Default ausgeblendet; Filterlogik steckt in
|
- „verworfen" ist per Default ausgeblendet; Filterlogik steckt in
|
||||||
|
|||||||
+50
-24
@@ -109,6 +109,20 @@
|
|||||||
}
|
}
|
||||||
.switch input:checked + i{background:var(--or)}
|
.switch input:checked + i{background:var(--or)}
|
||||||
.switch input:checked + i::before{left:15px}
|
.switch input:checked + i::before{left:15px}
|
||||||
|
.seg{
|
||||||
|
display:inline-flex;align-items:stretch;
|
||||||
|
border:1px solid rgba(36,52,71,.2);border-radius:999px;overflow:hidden;
|
||||||
|
}
|
||||||
|
.seg label{display:flex;cursor:pointer}
|
||||||
|
.seg input{position:absolute;opacity:0;width:0;height:0}
|
||||||
|
.seg span{
|
||||||
|
padding:4px 12px;
|
||||||
|
font-family:'IBM Plex Sans',sans-serif;font-size:.75rem;color:var(--muted);
|
||||||
|
transition:background .15s,color .15s;
|
||||||
|
}
|
||||||
|
.seg label + label span{border-left:1px solid rgba(36,52,71,.14)}
|
||||||
|
.seg input:checked + span{background:var(--or);color:#fff}
|
||||||
|
.seg input:focus-visible + span{outline:2px solid var(--or);outline-offset:-2px}
|
||||||
textarea{
|
textarea{
|
||||||
display:block;width:100%;min-height:380px;
|
display:block;width:100%;min-height:380px;
|
||||||
border:0;outline:none;resize:vertical;
|
border:0;outline:none;resize:vertical;
|
||||||
@@ -213,7 +227,7 @@
|
|||||||
ul.and>li:last-child::before{border-right:2px solid var(--line);border-radius:0 6px 0 0}
|
ul.and>li:last-child::before{border-right:2px solid var(--line);border-radius:0 6px 0 0}
|
||||||
ul.and>li:first-child::after{border-radius:6px 0 0 0}
|
ul.and>li:first-child::after{border-radius:6px 0 0 0}
|
||||||
|
|
||||||
/* --- ANY OF: durchgezogene Linie links, gestrichelte Abzweige --- */
|
/* --- ANY OF: durchgehend gestrichelte graue Linien (Haupt- + Abzweige) --- */
|
||||||
li.has-or{align-items:flex-start}
|
li.has-or{align-items:flex-start}
|
||||||
ul.or{
|
ul.or{
|
||||||
display:flex;flex-direction:column;
|
display:flex;flex-direction:column;
|
||||||
@@ -222,19 +236,19 @@
|
|||||||
padding-top:14px;
|
padding-top:14px;
|
||||||
}
|
}
|
||||||
ul.or::before{
|
ul.or::before{
|
||||||
content:'';position:absolute;top:0;left:9px;height:14px;border-left:2px solid var(--or);
|
content:'';position:absolute;top:0;left:9px;height:14px;border-left:2px dashed var(--muted);
|
||||||
}
|
}
|
||||||
ul.or>li{position:relative;align-items:flex-start;padding:5px 0 5px 30px}
|
ul.or>li{position:relative;align-items:flex-start;padding:5px 0 5px 30px}
|
||||||
/* Abzweig auf Höhe der Knoten-Mitte (5px li-Padding + halbe Knotenhöhe), nicht Mitte des Teilbaums */
|
/* Abzweig auf Höhe der Knoten-Mitte (5px li-Padding + halbe Knotenhöhe), nicht Mitte des Teilbaums */
|
||||||
ul.or>li::before{
|
ul.or>li::before{
|
||||||
content:'';position:absolute;left:9px;top:23px;width:21px;border-top:2px dashed var(--or);
|
content:'';position:absolute;left:9px;top:23px;width:21px;border-top:2px dashed var(--muted);
|
||||||
}
|
}
|
||||||
ul.or>li::after{
|
ul.or>li::after{
|
||||||
content:'';position:absolute;left:9px;top:0;height:100%;border-left:2px solid var(--or);
|
content:'';position:absolute;left:9px;top:0;height:100%;border-left:2px dashed var(--muted);
|
||||||
}
|
}
|
||||||
ul.or>li:last-child::after{height:23px}
|
ul.or>li:last-child::after{height:23px}
|
||||||
ul.or .node{
|
ul.or .node{
|
||||||
border-color:var(--or);
|
border-color:var(--muted);
|
||||||
box-shadow:none;
|
box-shadow:none;
|
||||||
font-weight:400;
|
font-weight:400;
|
||||||
}
|
}
|
||||||
@@ -265,24 +279,26 @@
|
|||||||
.chip.st-prod {background:#DBEAF8;border-color:#85ACD7}
|
.chip.st-prod {background:#DBEAF8;border-color:#85ACD7}
|
||||||
.chip.st-verworfen{background:#F1F2F4;border-color:#B3BAC2;border-style:dashed;color:var(--muted);text-decoration:line-through}
|
.chip.st-verworfen{background:#F1F2F4;border-color:#B3BAC2;border-style:dashed;color:var(--muted);text-decoration:line-through}
|
||||||
|
|
||||||
/* ---------- Vertikal-Modus (transponiert) ---------- */
|
/* ---------- Transponierte Modi (vertikal + kompakt) ---------- */
|
||||||
.tree.vertical{margin:0}
|
/* Gemeinsame Basis: Kinder untereinander, Sammelleiste links,
|
||||||
.tree.vertical li{align-items:flex-start}
|
Abzweig auf Knotenmitte (23-px-Offset). */
|
||||||
.tree.vertical ul.and{flex-direction:column;align-items:flex-start;padding-top:14px}
|
.tree.vertical, .tree.kompakt{margin:0}
|
||||||
.tree.vertical ul.and::before{left:9px;height:14px}
|
.tree.vertical li, .tree.kompakt li{align-items:flex-start}
|
||||||
.tree.vertical ul.and>li{padding:5px 0 5px 30px}
|
.tree.vertical ul.and, .tree.kompakt ul.and{flex-direction:column;align-items:flex-start;padding-top:14px}
|
||||||
.tree.vertical ul.and>li::before{
|
.tree.vertical ul.and::before, .tree.kompakt ul.and::before{left:9px;height:14px}
|
||||||
|
.tree.vertical ul.and>li, .tree.kompakt ul.and>li{padding:5px 0 5px 30px}
|
||||||
|
.tree.vertical ul.and>li::before, .tree.kompakt ul.and>li::before{
|
||||||
left:9px;right:auto;top:23px;width:21px;height:0;
|
left:9px;right:auto;top:23px;width:21px;height:0;
|
||||||
border:0;border-top:2px solid var(--line);border-radius:0;
|
border:0;border-top:2px solid var(--line);border-radius:0;
|
||||||
}
|
}
|
||||||
.tree.vertical ul.and>li::after{
|
.tree.vertical ul.and>li::after, .tree.kompakt ul.and>li::after{
|
||||||
left:9px;right:auto;top:0;width:0;height:100%;
|
left:9px;right:auto;top:0;width:0;height:100%;
|
||||||
border:0;border-left:2px solid var(--line);border-radius:0;
|
border:0;border-left:2px solid var(--line);border-radius:0;
|
||||||
}
|
}
|
||||||
.tree.vertical ul.and>li:last-child::after{height:23px}
|
.tree.vertical ul.and>li:last-child::after, .tree.kompakt ul.and>li:last-child::after{height:23px}
|
||||||
|
|
||||||
/* All-of transponiert: Linie läuft rechts aus dem Überknoten heraus (wie Richtung LR),
|
/* Nur vertikal: All-of tritt rechts aus dem Überknoten heraus (wie Richtung LR),
|
||||||
Any-of bleibt unten-links — dadurch klar unterscheidbare Austrittsseiten */
|
Any-of bleibt unten-links — klar unterscheidbare Austrittsseiten, aber breit. */
|
||||||
.tree.vertical li.has-and{flex-direction:row;align-items:flex-start}
|
.tree.vertical li.has-and{flex-direction:row;align-items:flex-start}
|
||||||
.tree.vertical li.has-and>ul.and{padding-top:0}
|
.tree.vertical li.has-and>ul.and{padding-top:0}
|
||||||
.tree.vertical li.has-and>ul.and::before{
|
.tree.vertical li.has-and>ul.and::before{
|
||||||
@@ -291,6 +307,11 @@
|
|||||||
}
|
}
|
||||||
.tree.vertical li.has-and>ul.and>li:first-child::after{top:17px;height:calc(100% - 17px)}
|
.tree.vertical li.has-and>ul.and>li:first-child::after{top:17px;height:calc(100% - 17px)}
|
||||||
.tree.vertical li.has-and>ul.and>li:only-child::after{top:17px;height:6px}
|
.tree.vertical li.has-and>ul.and>li:only-child::after{top:17px;height:6px}
|
||||||
|
|
||||||
|
/* Kompakt: auch All-of läuft nach unten (spart Breite) — kein Rechts-Fächer.
|
||||||
|
Die graue, gestrichelte Any-of-Führung kommt aus der Basis und gilt hier
|
||||||
|
wie in allen Modi. Gate-Codierung: und = durchgezogen dunkel (Tinte),
|
||||||
|
oder = gestrichelt grau. */
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -307,7 +328,7 @@
|
|||||||
</svg>
|
</svg>
|
||||||
<span>Werk<span style="color:var(--or)">baum</span></span>
|
<span>Werk<span style="color:var(--or)">baum</span></span>
|
||||||
</h1>
|
</h1>
|
||||||
<p>Struktur als Text bearbeiten — das Diagramm entsteht live. Umschalter „vertikal“ ordnet Editor und Diagramm nebeneinander an.</p>
|
<p>Struktur als Text bearbeiten — das Diagramm entsteht live. Darstellung „horizontal / vertikal / kompakt“ wählt Anordnung und Linienführung.</p>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div class="app" id="app">
|
<div class="app" id="app">
|
||||||
@@ -348,9 +369,11 @@
|
|||||||
<label class="switch">
|
<label class="switch">
|
||||||
<input type="checkbox" id="showc"><i></i>verworfene
|
<input type="checkbox" id="showc"><i></i>verworfene
|
||||||
</label>
|
</label>
|
||||||
<label class="switch">
|
<div class="seg" role="radiogroup" aria-label="Darstellung">
|
||||||
<input type="checkbox" id="vert"><i></i>vertikal
|
<label><input type="radio" name="layout" value="horizontal" checked><span>horizontal</span></label>
|
||||||
</label>
|
<label><input type="radio" name="layout" value="vertikal"><span>vertikal</span></label>
|
||||||
|
<label><input type="radio" name="layout" value="kompakt"><span>kompakt</span></label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="diagram"><ul class="tree" id="out"></ul></div>
|
<div class="diagram"><ul class="tree" id="out"></ul></div>
|
||||||
<div class="warnings" id="warn"></div>
|
<div class="warnings" id="warn"></div>
|
||||||
@@ -520,10 +543,13 @@ src.addEventListener('keydown', e => {
|
|||||||
src.addEventListener('input', render);
|
src.addEventListener('input', render);
|
||||||
|
|
||||||
const app = document.getElementById('app');
|
const app = document.getElementById('app');
|
||||||
const vert = document.getElementById('vert');
|
function applyLayout(mode){
|
||||||
vert.addEventListener('change', () => {
|
out.classList.toggle('vertical', mode === 'vertikal');
|
||||||
out.classList.toggle('vertical', vert.checked);
|
out.classList.toggle('kompakt', mode === 'kompakt');
|
||||||
app.classList.toggle('side', vert.checked);
|
app.classList.toggle('side', mode !== 'horizontal');
|
||||||
|
}
|
||||||
|
document.querySelectorAll('input[name="layout"]').forEach(radio => {
|
||||||
|
radio.addEventListener('change', () => { if(radio.checked) applyLayout(radio.value); });
|
||||||
});
|
});
|
||||||
|
|
||||||
const showc = document.getElementById('showc');
|
const showc = document.getElementById('showc');
|
||||||
|
|||||||
Reference in New Issue
Block a user