Skip to content

feat(composer): Blöcke anfassen und einstellen - #190

Merged
BechsteinDigital merged 1 commit into
mainfrom
feat/composer-editing
Aug 7, 2026
Merged

BechsteinDigital merged 1 commit into
mainfrom
feat/composer-editing

Conversation

@BechsteinDigital

Copy link
Copy Markdown
Owner

1. Why is this change necessary?

Der Canvas zeigte seit #189 die echten Blöcke — aber man kam nicht an sie heran. Jetzt wählt ein
Klick einen Block aus, das Panel daneben ist aus seinen controls generiert, und jede Änderung
geht als Autosave zurück.

2. What does this change do, exactly?

Der Editier-Marker ist ein durchgereichtes Attribut, kein Hüllelement. Ein Wrapper um jeden
Block wäre der bequemere Weg und der falsche: Ein Theme setzt Abstände typischerweise über
.cal-region > * + *, und ein Element dazwischen bricht genau das. display: contents rettet es
nicht — ein Element ohne Box hat auch keine Margins. Vue reicht Nicht-Prop-Attribute an die
Komponenten-Wurzel durch, also markieren wir den Block selbst und lassen den Baum in Ruhe.

Der Klick-Konflikt (§7.6) liegt auf den Kindern, nicht auf dem Block. Die Wurzel nimmt den
Klick, die Innereien nehmen keinen — ein Button im Block feuert also nicht, der Block wird
ausgewählt. Läge pointer-events: none auf dem Block selbst, ginge der Klick an die Region, und
dann wüsste niemand mehr, welcher Block gemeint war. Der „Interaktiv testen"-Umschalter ändert
nur das, nicht die Auswahl: Wer ein Akkordeon aufklappt, um hineinzusehen, soll dabei nicht
verlieren, was er gerade bearbeitet.

Das Panel ist generiert (§7.7). Ein handgebautes Panel je Block wäre eine zweite Beschreibung
derselben Einstellungen neben BlockControls — und die zweite ist immer die, die veraltet.

Die Erscheinungs-Controls wählen aus --cal-* und aus nichts sonst. Ihre eigenen options
werden bewusst ignoriert: Das wäre der Weg, auf dem ein freier Farbwert doch noch hereinkäme, und
mit ihm wäre die Zusicherung der Token-Achse in einer Registrierung aufgehoben.

Die Token-Rollen kommen aus dem CSS, das im Canvas gilt — nicht aus einer gepflegten Liste.
Eine Liste liefe auseinander, sobald jemand ein Token hinzufügt: Das Panel böte Rollen an, die es
nicht gibt, oder verschwiege welche, die es gibt.

Zwei kleinere, aber gleichartige Entscheidungen: Ein Control-Typ ohne Feld wird benannt, nicht
weggelassen (weggelassen sähe er aus wie eine Einstellung, die es nicht gibt). Zurücksetzen
entfernt die Bindung
, statt den Default einzufrieren — ein entferntes Control folgt dem Block,
wenn dessen Autor den Default ändert.

3. Describe each step to reproduce the issue or behaviour.

Neun Tests für den Weg, den ein Redakteur wirklich geht, plus 26 für die reinen Teile. Alle sechs
tragenden Aussagen sabotiert — alle sechs beißen.

Gate Ergebnis
.NET 2008 + 29 Analyzer
Surface Runtime 109
Composer Admin 56
Admin Shell 521
Docs Site lint + build

4. Please link to the relevant issues (if any).

Setzt §7.6 (Klick-Konflikt) und §7.7 (generiertes Panel, Guardrails) um. Baut auf #189 auf.


Zwei Befunde, dabei behoben

Die Speicher-Route gab 204 ohne neuen Stempel zurück. Damit ließe sich genau einmal
speichern: Nach dem ersten Schreiben ist der eigene Stempel veraltet, und der nächste Autosave
liefe in einen Konflikt mit sich selbst — die verwirrendste Art zu scheitern, weil niemand sonst
etwas angefasst hat. Jetzt 200 mit changedAtUtc. Ein Test fährt genau diesen zweiten Speicher-
vorgang.

Der Canvas hatte die Basis-Token gar nicht. Auf einer Fläche lädt die Runtime tokens.scss
selbst; im Admin tut das niemand, und ein Block, der var(--cal-color-fg) liest, fiel auf nichts
zurück — eine Vorschau, die falsch aussieht, ohne dass etwas kaputt wirkt. @callora/surface
exportiert sie jetzt als Text, aus derselben Datei, die die Fläche lädt. Als Text und nicht als
Datei, weil der Konsument sie scopen muss und ein ?inline-Import über die Paketgrenze ihm sass
und einen Dateizugriff außerhalb seines Projekts aufzwänge (Vite verweigert ihn — genau so ist es
aufgefallen).

Noch nicht drin

  • Sektionslayouts aus dem Theme (§7.1/§7.7). theme.json kennt heute Templates und Settings,
    aber keine Layouts mit ihren Regionen. Ohne sie gibt es keine Zielorte, in die man etwas ziehen
    könnte — deshalb steht das vor Drag & Drop, nicht daneben.
  • Drag & Drop und die Block-Palette.
  • Der abgeleitete Nutzungsindex („welche Layouts benutzen Block X", §7.2).

Der Canvas zeigte die echten Blöcke, aber man kam nicht an sie heran. Jetzt wählt
ein Klick einen Block aus, das Panel daneben ist aus seinen `controls` generiert,
und jede Änderung geht als Autosave zurück.

**Der Editier-Marker ist ein durchgereichtes Attribut, kein Hüllelement.** Ein
Wrapper um jeden Block wäre der bequemere Weg und der falsche: Ein Theme setzt
Abstände typischerweise über `.cal-region > * + *`, und ein Element dazwischen
bricht genau das — `display: contents` erst recht, denn ein Element ohne Box hat
auch keine Margins. Vue reicht Nicht-Prop-Attribute an die Komponenten-Wurzel
durch, also markieren wir den Block selbst und lassen den Baum in Ruhe.

**Der Klick-Konflikt (§7.6) liegt auf den Kindern, nicht auf dem Block.** Die
Wurzel nimmt den Klick, die Innereien nehmen keinen — ein Button im Block feuert
also nicht, der Block wird ausgewählt. Läge `pointer-events: none` auf dem Block
selbst, ginge der Klick an die Region, und dann wüsste niemand mehr, welcher
Block gemeint war.

**Das Panel ist generiert (§7.7).** Ein handgebautes Panel je Block wäre eine
zweite Beschreibung derselben Einstellungen neben `BlockControls`, und die zweite
ist immer die, die veraltet. Die Erscheinungs-Controls wählen aus `--cal-*` und
aus nichts sonst; ihre eigenen `options` werden bewusst ignoriert, denn das wäre
der Weg, auf dem ein freier Farbwert doch noch hereinkäme.

**Die Token-Rollen kommen aus dem CSS, das im Canvas gilt**, nicht aus einer
gepflegten Liste. Eine Liste liefe auseinander, sobald jemand ein Token
hinzufügt: Das Panel böte dann Rollen an, die es nicht gibt, oder verschwiege
welche, die es gibt.

**Ein Control-Typ ohne Feld wird benannt, nicht weggelassen.** Weggelassen sähe
er aus wie eine Einstellung, die es nicht gibt — und niemand käme auf die Idee,
sie zu vermissen.

**Zurücksetzen entfernt die Bindung, statt den Default einzufrieren.** Ein
entferntes Control folgt dem Block, wenn dessen Autor den Default ändert; ein
eingefrorener Wert tut das nicht.

Dabei zwei Befunde behoben:

- **Die Speicher-Route gab 204 ohne neuen Stempel zurück.** Damit ließe sich
  genau einmal speichern: Nach dem ersten Schreiben ist der eigene Stempel
  veraltet, und der nächste Autosave liefe in einen Konflikt mit sich selbst —
  die verwirrendste Art zu scheitern, weil niemand sonst etwas angefasst hat.
  Jetzt 200 mit `changedAtUtc`.
- **Der Canvas hatte die Basis-Token gar nicht.** Auf einer Fläche lädt die
  Runtime `tokens.scss` selbst; im Admin tut das niemand, und ein Block, der
  `var(--cal-color-fg)` liest, fiel auf nichts zurück. `@callora/surface`
  exportiert sie jetzt als Text — aus derselben Datei, die die Fläche lädt, also
  ohne zweite Liste, und ohne dem Konsumenten sass und einen Dateizugriff
  außerhalb seines Projekts aufzuzwingen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QvepSeijoZeRaBsyiGqoka
@BechsteinDigital
BechsteinDigital merged commit 37e58bb into main Aug 7, 2026
8 of 9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant