byte_theme:card: prop-driven Standard-Card mit Bubble-Frame-Outline (no-CTA-Variante) wieder eingeführt
byte_theme:card wird als prop-driven Wrapper um byte_theme:bubble-card-frame mit variant: profile-2-2-no-cta neu eingeführt — exakt das Schema, das node.blog.card bereits füttert. Card-Familie wächst von zwei auf drei SDCs.
Kontext
Das byte_theme hatte bis vor kurzem eine Card-Familie aus mehreren SDCs: card, card-bubble-text, card-bubble-icon, card-bubble-profile. Eine vorangegangene Refactor-Welle hatte die Familie auf zwei Komponenten reduziert: card-bubble-profile (mit CTA-Notch) und card-bubble-profile-no-button (ohne CTA, gerade Bottom-Edge). Beide sind slot-basiert — Inhalt wird in Drupal Canvas via {% block content %} zusammengestellt.
Das Canvas-Content-Template canvas.content_template.node.blog.card referenziert aber weiterhin sdc.byte_theme.card mit strukturierten Props (heading_text, level, url, media: {src, alt, width, height}, text, orientation, style, background) — die Drupal-Default-Render-Form für Blog-Posts in der „Card"-View-Mode. Da byte_theme:card als SDC entfernt wurde, scheitert das Rendern jeder Blog-Card-Liste mit Twig\Error\LoaderError: Template "byte_theme:card" is not defined. Die Insights-Section auf der Home-Page zeigte stattdessen drei Stack-Trace-Boxen.
Der User hat im Live-Debug zwei Constraints fixiert: (1) byte_theme:card ist die „normale Card ohne Aussparung unten", (2) sie soll den SOLCOM-Brand-Frame tragen („Fancyborder" — gemeint ist die gradient-Stroke-Outline aus bubble-card-frame profile-2-2-no-cta).
Entscheidung
byte_theme:card als prop-driven Wrapper um byte_theme:bubble-card-frame mit variant: profile-2-2-no-cta wieder einführen. Konkret:
- Neue SDC
components/card/mit Schema (heading_text,level: 1-6,url,media: {src, alt, width, height},text,orientation: vertical|horizontal,style: framed|plain,background: default). Die Prop-Form spiegelt exakt wider, wasnode.blog.cardheute schon füttert — keine Schema-Änderung am Content-Template nötig. - Visual-Frame kommt aus dem etablierten
.bubble-card/.bubble-card--profile-no-ctaLayer. Twig-Inner:<div class="bubble-card__frame" aria-hidden="true">{% include 'byte_theme:bubble-card-frame' with { variant: 'profile-2-2-no-cta' } only %}</div>— gleiches Pattern wiecard-bubble-profile-no-button.twig. - Element-Switch: Bei
url-Prop rendert die Card als<a class="solcom-card bubble-card …">(full-card-click-target). Ohneurlals<article>. Mirrors diebyte_theme:buttonhref→<a>/ no-href→<button>-Konvention aus ADR-0004. - Stable semantic class
.solcom-cardals prop-driven Layout-Layer. Tailwind-Atom-Klassen leben unter@applyinsrc/main.css@layer components. - Kein
card-bubble-text/card-bubble-iconRe-Animate. Die Card-Familie wächst auf drei SDCs mit klar getrennten Use-Cases. - Render-Contract-Tests in
tests/src/Kernel/CardComponentTest.php: Test 1 pinnt<a class="solcom-card">mit Heading auf dem requested Level + Body-Text; Test 2 pinnt das Bubble-Frame-Inline-SVG (bubble-card__frame svg) als Anti-Drift-Sicherung.
Rejected alternatives
Expand each rejected option to see the rationale.
node.blog.card Content-Template auf byte_theme:card-bubble-profile-no-button umbiegen rejected
Bricht das Schema, weil card-bubble-profile-no-button slot-basiert ist und keinen heading_text/media-Prop kennt. Die Migration auf Slot-basierte Props wäre eine eigene Refactor-Welle, die den Scope der Bug-Fix-Aufgabe sprengt.
Plain-CSS-Border statt Bubble-Frame rejected
Liefert keine SOLCOM-Identity. User-Feedback hat das sofort als „nicht die richtige Card" erkannt. Der gradient-Stroke ist Brand-charakteristisch und gehört auf alle drei SDCs der Card-Familie.
card-bubble-profile-no-button zur prop-driven Komponente umbauen (Slot raus, Props rein) rejected
Bricht alle bestehenden Aufrufer. Die beiden Use-Cases (Slot vs. Prop-driven) existieren parallel sinnvoll — die Site-Builder-Erfahrung im Drupal-Canvas-Picker ist klarer mit drei dedizierten Komponenten.
byte_theme:card als Variant-Prop auf byte_theme:card-bubble-profile-no-button (mode: slot|prop-driven) rejected
Bringt Conditional-Schema-Komplexität (heading_text nur sinnvoll wenn mode: prop-driven), siehe ADR-0004 für die analoge Verwerfung. Drei dedizierte SDCs schlagen eine SDC mit Mode-Switch.
Card-Familie auf zwei reduzieren lassen und das Content-Template abschalten/migrieren rejected
Würde die Insights-Section abreißen oder kostet eine Field-Mapping-Refactor-Welle. Beides nicht im Scope. Re-Introduktion einer dritten Card-SDC ist die kleinste Schiene zum Fix.
Consequences
- Card-Familie wächst von zwei auf drei SDCs. Neue Wahrheit:
card-bubble-profile(mit CTA-Notch, slot-basiert),card-bubble-profile-no-button(ohne Notch, slot-basiert),card(ohne Notch, prop-driven für View-Mode-Listen). - Inkonsistenz-Spannung mit dem Memory-Eintrag „Card-SDCs sollten Canvas-Wrapper sein". Diese ADR durchbricht die Regel bewusst für den Use-Case „Drupal-View-Mode-Listen-Render". Beide Pattern existieren parallel, bewusst getrennt nach Render-Quelle (View-Mode vs. Page-Builder).
- Visual-Frame-Mechanik ist DRY. Da
byte_theme:cardundbyte_theme:card-bubble-profile-no-buttondenselbenbubble-card-frame profile-2-2-no-ctaincluden, lebt der Brand-Outline an genau einer Stelle. Brand-Color-Anpassung am Gradient-Stroke trifft beide Cards automatisch. card-bubble-profile-no-buttonundcardsind visuell identisch im Default-State — der Unterschied liegt im API-Modus (Slot vs. Prop). Schema-descriptionan beiden SDCs verweist explizit auf den Sibling und den Use-Case.- Notch-Geometrie ist hartcodiert auf no-CTA. Wenn jemand später eine prop-driven Card mit Notch braucht, müsste das Schema um eine
with_cta-Bool erweitert werden. Aktuell out of scope. - Cherry-Pick-Reibung gegen Upstream-Byte-Theme. Die Datei
components/card/existiert im Upstream. Der SOLCOM-Refactor ersetzt den Inhalt komplett durch das Bubble-Frame-Wrapping. Upstream-Updates ancard.twigmüssen manuell gemappt werden. Die Reibung ist analog zu ADR-0004 (button.twigreplace) und akzeptiert. - Pflicht-Verfahren nach SDC-Hinzufügung:
ComponentSourceManager::generateComponents('sdc')muss laufen. Anschließend muss das Content-Template perentity::save()re-materialisiert werden. Siehe ADR-0008 Consequences und ADR-0007 für die generelle Mechanik. - A11y-Implikation des Full-Card-Click-Pattern:
<a>wraps den vollständigen Card-Inhalt inkl.<h3>. Screenreader sehen die ganze Card als ein Link. Das ist meistens das Gewünschte für Blog-Card-Listen, kann aber für Inhalts-Sources mit langem Text die Acc-Name-Latenz erhöhen. - Test 2 (Bubble-Frame-SVG-Assertion) ist Anti-Drift-Sicherung. Wer die Frame-Wrapping aus Versehen rauskürzt, bricht den Test mit klarem Fehler.