Skip to content

Feature: Element Inspector i Builder

Problemstilling

Når man bygger en chatbot i builderen, er det vanskelig å forstå den rendrede DOM-strukturen til elementene. Man vet at man har en "Message 1", men ikke hvilke CSS-klasser og wrappere den får i CE-output. Dette gjør det spesielt vanskelig å:

  • Skrive CSS i CSS-operatoren som treffer riktig element
  • Vite hva man kan targete med ShowHide/Change-operatorer
  • Debugge layout-problemer
  • Forstå nesting-hierarkiet (wrap → block → inner element → span)

Konsept

En "Inspect"-modus i builderen som viser elementhierarkiet i preview-iframen med fargekodede, dashed outlines.

Brukerflyt

  1. Brukeren trykker på et inspect-ikon (forstørrelsesglass) i preview-panelet
  2. En liste over alle identifiserbare elementer dukker opp — palette-style (lik TargetOpSelector / ShowHide)
  3. Elementer er gruppert: Blocks (t1, b1, g1...), Flow-komponenter (m1, c1, i1...), evt. Custom HTML (h1...)
  4. Brukeren klikker et element i listen
  5. Elementets hierarki vises — f.eks.:
    ☑ t1-wrap          (ytterst, blå dashed)
    ☑ text-block t1    (oransje dashed)
    ☑ t1-inner-wrap    (grønn dashed)
  6. Alle nivåer er avhuket by default → alle outlines vises
  7. Brukeren kan fjerne haker for å vise bare nivåene de er interessert i
  8. Fargene er faste per dybde-nivå (ytterst → innerst), ikke per element-type

Eksisterende mønstre å bygge på

DOM-struktur i CE (Creative-Engine)

Blokker følger dette mønsteret:

html
<div class="t1-wrap">                    ← Wrap (ytre container)
  <div class="text-block t1">            ← Type-block + ID
    <div class="t1-inner-wrap">           ← Inner wrap
      <p>Innhold her</p>                  ← Faktisk innhold
    </div>
  </div>
</div>

Forkortelser for blokker:

Blokk-typeForkortelseWrap-klasseBlock-klasse
Textt1t1-wraptext-block t1
Buttonb1b1-wrapbutton-block b1
Graphicg1g1-wrapgraphic-block g1
Formf1f1-wrapform-block f1
Videov1v1-wrapvideo-block v1
Slidersl1sl1-wrapslider-block sl1
Conversationco1co1-wrapconversation-block co1
HTMLh1html-block-wraphtml-block html1

Flow-komponenter (inne i conversation-block):

html
<div class="message-wrap message-wrap-{uniq}">       ← Ytre wrapper
  <div class="message-avatar message-avatar-{uniq}">  ← Avatar (valgfri)
  <div class="message-bubble message-bubble-{uniq} m1 msg-type-text">  ← Bubble + ID
    <div class="message-content">                      ← Innhold
      Tekst her
    </div>
  </div>
</div>

Forkortelser for flow-komponenter:

TypeForkortelseKlasser
Message (Text)m1.message-bubble .m1
Choicec1.choice .c1
Inputin1.input .in1
Linkl1.link .l1
Imagei1.image .i1
Shopsh1.shop .sh1
Consentco1.consent .co1

Eksisterende UI-mønstre i builderen

  1. TargetOpSelector palette — Dropdown med grupperte forkortelser (s1, a2, t1...) i tabellform. Brukt i ShowHide og Change-operatorer. Kan gjenbrukes eller utvides.

  2. ghostSelectionContainerborder: 1px dashed $grey-70 for multi-select i flow. Viser at dashed borders allerede er et mønster.

  3. focusComponentbox-shadow: 0px 0px 0px 6px rgba(color, 0.25), inset 0px 0px 0px 2px color for fokusert operator. Fargekoding allerede i bruk.

  4. Branding outlineoutline: 2px dashed ${branding.color} — dynamisk farget dashed outline, akkurat det vi trenger.

  5. Analytics highlightfilter: opacity(0.4) for å dimme ikke-relevante elementer.

Kommunikasjon builder ↔ preview

Preview kjører i en same-origin iframe (/preview-frame.html). Kommunikasjon skjer via:

javascript
// Builder → Preview
frame.contentDocument.dispatchEvent(new CustomEvent('creative-data-update', { detail }))

Kan utvides med ny event-type for inspeksjon:

javascript
frame.contentDocument.dispatchEvent(new CustomEvent('inspector-highlight', {
  detail: { selector: '.t1-wrap', color: '#4A90D9', enabled: true }
}))

CE DevTools

Det finnes allerede et DevTools-system i Creative-Engine (/src/dev-tools/). Feature-flagget devTools aktiverer det. Inspektøren kan enten bygge på dette eller være uavhengig.


Implementeringsplan

Approach A: Ren builder-side (enklest)

Inspektøren lever kun i builder-koden. Manipulerer preview-iframe DOM direkte via frame.contentDocument.querySelector().

Fordeler:

  • Ingen endringer i Creative-Engine
  • Enklere å prototype
  • Alt i én kodebase

Ulemper:

  • Tett kobling til CE sin DOM-struktur (men det er allerede tilfellet med TargetOpSelector)
  • Må querySelecte inn i iframe

Implementering:

  1. InspectorPanel.vue — Ny komponent i BuilderVisuals/Preview/

    • Knapp (forstørrelsesglass) i preview-toolbar
    • Toggler inspector-modus
    • Viser element-liste når aktiv
  2. Element-liste — Henter tilgjengelige elementer fra creativeBlocks (allerede tilgjengelig i PreviewPanel)

    • Blocks: Parse creativeBlocks keys → forkortelser (t1, b1, g1...)
    • Flow-komponenter: Parse flow logic → forkortelser (m1, c1, i1...)
    • Grupper etter type, vis som pills/chips
  3. Hierarki-visning — Når et element er valgt:

    • Query iframe DOM: frame.contentDocument.querySelector('.t1-wrap')
    • Traversér children: .t1-wrap.text-block.t1.t1-inner-wrap → barn
    • Vis som trestruktur med checkboxer
    • Hver node viser: klasse-navn + farge-indikator
  4. Outline-rendering — Inject CSS i iframe:

    javascript
    const style = frame.contentDocument.createElement('style')
    style.id = 'inspector-styles'
    style.textContent = `
      .inspector-outline-0 { outline: 2px dashed #4A90D9 !important; outline-offset: 2px; }
      .inspector-outline-1 { outline: 2px dashed #E8913A !important; outline-offset: 0px; }
      .inspector-outline-2 { outline: 2px dashed #50B83C !important; outline-offset: -2px; }
      .inspector-outline-3 { outline: 2px dashed #9C6ADE !important; outline-offset: -4px; }
    `
    frame.contentDocument.head.appendChild(style)

    Legg til/fjern klasser basert på checkbox-state.

  5. Fargeskjema (dybdebasert, fast rekkefølge):

    • Nivå 0 (ytterst/wrap): #4A90D9 (blå)
    • Nivå 1 (block): #E8913A (oransje)
    • Nivå 2 (inner-wrap): #50B83C (grønn)
    • Nivå 3 (innhold): #9C6ADE (lilla)
    • Nivå 4+: #DE6A9C (rosa)

Approach B: CE DevTools-utvidelse (mest robust)

Legger til en "Inspector"-tab i det eksisterende DevTools-systemet i Creative-Engine.

Fordeler:

  • Bygger på eksisterende system
  • CE vet om sin egen DOM — ingen fragile selectors
  • Kan gjenbrukes utenfor builder (standalone debugging)

Ulemper:

  • Krever endringer i Creative-Engine repo
  • DevTools er feature-flagget — må sikre at inspector er tilgjengelig i builder-preview uten flaget
  • Mer koordinering mellom repoer

Approach C: Hybrid (anbefalt)

Builder håndterer UI (liste, checkboxer, fargekart). CE eksponerer en enkel API via CustomEvent for å highlighte elementer.

Builder-side:

  • InspectorPanel med liste og checkboxer
  • Sender events: inspector-highlight, inspector-clear

CE-side (minimal):

  • Lytter på inspector-highlight event
  • Legger til/fjerner outline-klasser på matchende elementer
  • Eksponerer inspector-elements event med liste over alle rendered elements + deres hierarki
javascript
// CE lytter:
document.addEventListener('inspector-query', () => {
  const elements = buildElementTree() // traverser DOM, finn alle blocks/flow-komponenter
  document.dispatchEvent(new CustomEvent('inspector-elements', { detail: elements }))
})

// CE mottar highlight-instruksjoner:
document.addEventListener('inspector-highlight', (e) => {
  const { selector, depth, enabled } = e.detail
  const el = document.querySelector(selector)
  el?.classList.toggle(`inspector-outline-${depth}`, enabled)
})

Utfordringer og vurderinger

Custom HTML-blokker

  • Innholdet er bruker-definert v-html — kan ha vilkårlig nesting
  • Forslag: Vis bare html-block-wrap og html-block som nivåer. Ikke prøv å parse innholdet.
  • Evt. vis en "Custom content" placeholder for barn-elementer

Elementer som ikke finnes ennå

  • Flow-komponenter rendres sekvensielt — en m3 finnes ikke i DOM før flowen har nådd den
  • Forslag: Vis bare elementer som faktisk er i DOM akkurat nå. Oppdater listen ved re-render.
  • Alternativt: Vis alle blocks (de finnes alltid), men merk flow-komponenter som "ikke rendret ennå" med dimmet stil

Scroll-synk

  • Når man velger et element i inspector-listen, bør preview scrolle til det
  • element.scrollIntoView({ behavior: 'smooth', block: 'center' })

Ytelse

  • Outline via CSS-klasser (ikke inline styles) — bedre ytelse
  • Inject én <style> tag, toggle klasser — ikke re-inject styles
  • Vis forkortelse + type: t1 (Text), b1 (Button), m1 (Message), c1 (Choice)
  • Ikke hele DOM-path, bare meaningful klasser: t1-wrap, text-block t1, t1-inner-wrap
  • Fjern Vue-genererte klasser og unike suffixer

Minimal MVP

Enkleste versjon som gir verdi:

  1. Inspect-knapp i preview-toolbar
  2. Flat liste med blocks (t1, b1, g1...) — data allerede tilgjengelig fra creativeBlocks
  3. Klikk på element → vis wrap/block/inner-wrap med fargekodede outlines i preview
  4. Checkboxer for å toggle nivåer

Estimert scope: Kun builder-side endringer (Approach A). Én ny komponent + litt logikk i PreviewPanel.

Filer som berøres

Nye:

  • BuilderVisuals/Preview/InspectorPanel.vue — Hovedkomponent
  • BuilderVisuals/Preview/inspector.scss — Styling (evt. integrert)

Endres:

  • BuilderVisuals/Preview/PreviewPanel.vue — Legg til inspector-toggle + InspectorPanel
  • Evt. BuilderVisuals/Blocks/utils.ts — Gjenbruk classNameFromBlockName()

Utvidelser (post-MVP)

  • Flow-komponenter i listen (m1, c1...) — krever at preview har kjørt flowen
  • Klikk-i-preview for å velge element (event interception i iframe)
  • Kopier-klassenavn-knapp (for bruk i CSS-operator)
  • Tooltip med element-info ved hover over outlines
  • "Vis alle" / "skjul alle" toggle

Internal documentation