Exclusivobeta

Agent Vision <mv-agent-vision>

Mira tu página como la ve un agente de IA (o un lector de pantalla): envuelve cualquier región y la divide con una línea de escaneo arrastrable. A la izquierda, la vista humana; a la derecha, la "vista del agente", donde cada nodo del árbol de accesibilidad se convierte en una caja de wireframe alineada al píxel, etiquetada como una línea del árbol (button "Add to cart", heading 2 "Shipping", text field "Promo code"), y todo lo demás se funde en una cuadrícula tranquila. Los fallos que hacen que un sitio sea ilegible para los agentes (botones solo con icono y sin nombre, divs clicables, imágenes sin alt, campos con solo placeholder, saltos de encabezados, enlaces "Learn more" indistinguibles, puntos de color mudos) se señalan, se puntúan sobre 100 y se enumeran con su corrección; al hacer clic en un problema, la vista del agente lo barre y lo hace pulsar. Vuelve a escanear automáticamente con cada mutación, cambio de tamaño y desplazamiento.

CategoríaUtilidades
TipoWeb Component (<mv-agent-vision>)
Estadobeta
KitIA que puedes verificar
Keywordsexclusive, accessibility, a11y, ai-agent, agent, screen-reader, accessibility-tree, audit, lint, geo, seo, wipe, splitter, before-after, devtools, semantic-html

When to use

  • A team wants to show how AI agents and screen readers perceive a page during review or a demo
  • Developers audit a region for unnamed buttons, missing alt text and heading skips with a score
  • A before and after view helps explain accessibility or agent-readiness fixes to stakeholders

Avoid when

  • It would ship on a public production page for end users; keep it in dev, docs or review builds
  • A full compliance audit is required; it flags common issues but does not replace a real audit

Instalación

node scripts/add.mjs agent-vision --out ./src/marvelous

Agente de IA con el servidor MCP de Marvelous UI: install_components({ slugs: ["agent-vision"], target_dir: "<absolute path>/src/marvelous", framework: "react" }).

Archivos copiados (dependencias incluidas): tokens/tokens.css, core/base.css, core/dom.js, core/element.js, core/motion.js, core/observe.js, core/pointer.js, components/agent-vision/agent-vision.js, components/agent-vision/agent-vision.css.

Uso

Inicio rápido, el marcado mínimo que funciona:

<mv-agent-vision>
  <form>
    <h2>Newsletter</h2>
    <input type="email" placeholder="Email"> <button>Subscribe</button>
    <button type="button"><svg viewBox="0 0 24 24" width="16" height="16"><path d="M6 6l12 12M18 6 6 18" stroke="currentColor" stroke-width="2"/></svg></button>
  </form>
</mv-agent-vision>

Marcado de referencia: parte de él y personalízalo con atributos, data-* y variables CSS:

<div id="av-demo" style="width:min(100%,76rem);margin-inline:auto">
  <style>
    #av-demo .av-bar { display:flex; align-items:center; justify-content:space-between; gap:.75rem 1rem; flex-wrap:wrap; margin:0 0 1rem }
    #av-demo .av-bar p { margin:0; color:var(--mv-fg-muted); font-size:.8125rem; max-width:46rem }
    #av-demo .av-bar strong { color:var(--mv-fg) }
    #av-demo .av-page { container-type:inline-size; padding:1rem 1.25rem 1.25rem; border:1px solid var(--mv-border); border-radius:var(--mv-radius-xl); background:var(--mv-surface) }
    #av-demo .av-grid { display:grid; gap:1.25rem; margin-top:.875rem }
    @container (min-width:36rem) { #av-demo .av-grid { grid-template-columns:minmax(0,1fr) minmax(0,1.05fr); gap:1.75rem } }
    #av-demo .av-media { display:grid; gap:.625rem; align-content:start }
    #av-demo .av-hero-wrap { position:relative }
    #av-demo .av-hero { width:100%; aspect-ratio:4/3; object-fit:cover; border-radius:var(--mv-radius-lg) }
    #av-demo .av-tools { position:absolute; top:.625rem; right:.625rem; display:flex; gap:.375rem }
    #av-demo .av-tools .mv-button { background:var(--mv-surface-raised) }
    #av-demo .av-tools svg { width:1rem; height:1rem }
    #av-demo .av-thumbs { display:grid; grid-template-columns:repeat(3,1fr); gap:.5rem }
    #av-demo .av-thumbs img { width:100%; aspect-ratio:1; object-fit:cover; border-radius:var(--mv-radius-md) }
    #av-demo .av-thumbs img:nth-child(2) { object-position:20% 80%; transform:scaleX(-1) }
    #av-demo .av-thumbs img:nth-child(3) { object-position:85% 30% }
    #av-demo .av-info { display:grid; gap:.75rem; align-content:start }
    #av-demo .av-brand { margin:0; color:var(--mv-fg-muted); font-size:.75rem; font-weight:600; letter-spacing:.06em; text-transform:uppercase }
    #av-demo .av-info h2 { margin:-.375rem 0 0; font-size:1.5rem; line-height:1.15; letter-spacing:-.02em }
    #av-demo .av-reviews { color:var(--mv-fg-muted); font-size:.8125rem; text-decoration:none; justify-self:start }
    #av-demo .av-reviews:hover { color:var(--mv-fg); text-decoration:underline }
    #av-demo .av-reviews span { color:var(--mv-warning); letter-spacing:.08em; margin-right:.25rem }
    #av-demo .av-price { display:flex; align-items:center; gap:.625rem; margin:0; font-size:1.375rem; font-weight:700; font-variant-numeric:tabular-nums }
    #av-demo .av-dot { width:.625rem; height:.625rem; border-radius:50%; background:var(--mv-success); box-shadow:0 0 0 3px color-mix(in oklab,var(--mv-success) 22%,transparent) }
    #av-demo .av-stock { color:var(--mv-fg-muted); font-size:.8125rem; font-weight:500 }
    #av-demo .av-buy { display:grid; grid-template-columns:7rem 1fr; gap:.625rem; align-items:end }
    #av-demo .av-buy > .mv-button { width:100% }
    #av-demo .av-h { margin:.25rem 0 -.25rem; font-size:.9375rem }
    #av-demo .av-perks { display:grid; gap:.375rem; margin:0; padding:0; list-style:none; font-size:.8125rem; color:var(--mv-fg-muted) }
    #av-demo .av-perks li { display:flex; justify-content:space-between; gap:.75rem; padding:.5rem .75rem; border-radius:var(--mv-radius-md); background:var(--mv-bg-muted) }
    #av-demo .av-perks a { color:var(--mv-fg); font-weight:500; white-space:nowrap }
    #av-demo .av-promo { display:grid; gap:.375rem }
    #av-demo .av-promo-row { display:flex; gap:.5rem }
    #av-demo .av-hint { margin:.75rem 0 0; color:var(--mv-fg-muted); font-size:.75rem; text-align:center }
  </style>

  <div class="av-bar">
    <p><strong>Agent view</strong>. Drag the scan line: on the right, the page as an AI agent or a screen reader perceives it. Click an issue to jump to it.</p>
    <button class="mv-button" data-variant="outline" type="button" id="av-fix">Fix the page</button>
  </div>

  <mv-agent-vision id="av-vision" split="48">
    <article class="av-page" aria-labelledby="av-title">
      <nav class="mv-breadcrumb" aria-label="Breadcrumb">
        <ol>
          <li><a href="#home">Home</a></li>
          <li><a href="#trail">Trail</a></li>
          <li><span aria-current="page">Aster 3</span></li>
        </ol>
      </nav>

      <div class="av-grid">
        <div class="av-media">
          <div class="av-hero-wrap">
            <img class="av-hero" src="data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 480 360%27%3E%3Cdefs%3E%3ClinearGradient id=%27bg%27 x1=%270%27 y1=%270%27 x2=%270%27 y2=%271%27%3E%3Cstop offset=%270%27 stop-color=%27oklch(0.95 0.015 150)%27/%3E%3Cstop offset=%271%27 stop-color=%27oklch(0.88 0.03 150)%27/%3E%3C/linearGradient%3E%3CradialGradient id=%27fl%27%3E%3Cstop offset=%270%27 stop-color=%27black%27 stop-opacity=%27.25%27/%3E%3Cstop offset=%271%27 stop-color=%27black%27 stop-opacity=%270%27/%3E%3C/radialGradient%3E%3C/defs%3E%3Crect width=%27480%27 height=%27360%27 fill=%27url(%23bg)%27/%3E%3Cellipse cx=%27246%27 cy=%27286%27 rx=%27186%27 ry=%2716%27 fill=%27url(%23fl)%27/%3E%3Cpath d=%27M70 246 Q70 276 104 280 L386 280 Q424 278 428 246 Z%27 fill=%27oklch(0.3 0.03 160)%27/%3E%3Cpath d=%27M104 280v9M140 280v9M176 280v9M212 280v9M248 280v9M284 280v9M320 280v9M356 280v9M392 280v8%27 stroke=%27oklch(0.3 0.03 160)%27 stroke-width=%2712%27/%3E%3Cpath d=%27M74 236 L426 236 Q430 254 416 262 L98 262 Q76 258 74 236Z%27 fill=%27oklch(0.96 0.01 90)%27/%3E%3Cpath d=%27M82 238 Q76 196 118 174 L192 136 Q212 98 252 94 L290 96 Q302 138 340 158 L392 182 Q428 200 426 238 Z%27 fill=%27oklch(0.66 0.16 40)%27/%3E%3Cpath d=%27M290 96 Q302 138 340 158 L392 182 Q428 200 426 238 L360 238 Q350 180 300 150 Z%27 fill=%27black%27 fill-opacity=%27.1%27/%3E%3Cpath d=%27M212 126 L262 148 M204 142 L254 164 M196 158 L246 180%27 stroke=%27oklch(0.96 0.01 90)%27 stroke-width=%277%27 stroke-linecap=%27round%27/%3E%3Cpath d=%27M104 218 Q230 200 416 220%27 stroke=%27oklch(0.3 0.03 160)%27 stroke-opacity=%27.45%27 stroke-width=%276%27 fill=%27none%27/%3E%3Cpath d=%27M120 200 Q160 186 176 150%27 stroke=%27white%27 stroke-opacity=%27.35%27 stroke-width=%275%27 fill=%27none%27 stroke-linecap=%27round%27/%3E%3Ccircle cx=%27378%27 cy=%27206%27 r=%279%27 fill=%27oklch(0.96 0.01 90)%27 fill-opacity=%27.8%27/%3E%3C/svg%3E" alt="Aster 3 trail running shoe, side view" width="480" height="360">
            <div class="av-tools">
              <button class="mv-button" data-variant="outline" data-size="icon" data-shape="round" type="button" id="av-fav">
                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 14c1.5-1.5 3-3.2 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.8 0-3 .5-4.5 2-1.5-1.5-2.7-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4 3 5.5l7 7z"/></svg>
              </button>
              <button class="mv-button" data-variant="outline" data-size="icon" data-shape="round" type="button" id="av-share">
                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><path d="m8.6 13.5 6.8 4M15.4 6.5l-6.8 4"/></svg>
              </button>
            </div>
          </div>
          <div class="av-thumbs">
            <img src="data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 480 360%27%3E%3Cdefs%3E%3ClinearGradient id=%27bg%27 x1=%270%27 y1=%270%27 x2=%270%27 y2=%271%27%3E%3Cstop offset=%270%27 stop-color=%27oklch(0.95 0.015 150)%27/%3E%3Cstop offset=%271%27 stop-color=%27oklch(0.88 0.03 150)%27/%3E%3C/linearGradient%3E%3CradialGradient id=%27fl%27%3E%3Cstop offset=%270%27 stop-color=%27black%27 stop-opacity=%27.25%27/%3E%3Cstop offset=%271%27 stop-color=%27black%27 stop-opacity=%270%27/%3E%3C/radialGradient%3E%3C/defs%3E%3Crect width=%27480%27 height=%27360%27 fill=%27url(%23bg)%27/%3E%3Cellipse cx=%27246%27 cy=%27286%27 rx=%27186%27 ry=%2716%27 fill=%27url(%23fl)%27/%3E%3Cpath d=%27M70 246 Q70 276 104 280 L386 280 Q424 278 428 246 Z%27 fill=%27oklch(0.3 0.03 160)%27/%3E%3Cpath d=%27M104 280v9M140 280v9M176 280v9M212 280v9M248 280v9M284 280v9M320 280v9M356 280v9M392 280v8%27 stroke=%27oklch(0.3 0.03 160)%27 stroke-width=%2712%27/%3E%3Cpath d=%27M74 236 L426 236 Q430 254 416 262 L98 262 Q76 258 74 236Z%27 fill=%27oklch(0.96 0.01 90)%27/%3E%3Cpath d=%27M82 238 Q76 196 118 174 L192 136 Q212 98 252 94 L290 96 Q302 138 340 158 L392 182 Q428 200 426 238 Z%27 fill=%27oklch(0.66 0.16 40)%27/%3E%3Cpath d=%27M290 96 Q302 138 340 158 L392 182 Q428 200 426 238 L360 238 Q350 180 300 150 Z%27 fill=%27black%27 fill-opacity=%27.1%27/%3E%3Cpath d=%27M212 126 L262 148 M204 142 L254 164 M196 158 L246 180%27 stroke=%27oklch(0.96 0.01 90)%27 stroke-width=%277%27 stroke-linecap=%27round%27/%3E%3Cpath d=%27M104 218 Q230 200 416 220%27 stroke=%27oklch(0.3 0.03 160)%27 stroke-opacity=%27.45%27 stroke-width=%276%27 fill=%27none%27/%3E%3Cpath d=%27M120 200 Q160 186 176 150%27 stroke=%27white%27 stroke-opacity=%27.35%27 stroke-width=%275%27 fill=%27none%27 stroke-linecap=%27round%27/%3E%3Ccircle cx=%27378%27 cy=%27206%27 r=%279%27 fill=%27oklch(0.96 0.01 90)%27 fill-opacity=%27.8%27/%3E%3C/svg%3E" alt="Aster 3, full profile" width="160" height="160">
            <img src="data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 480 360%27%3E%3Cdefs%3E%3ClinearGradient id=%27bg%27 x1=%270%27 y1=%270%27 x2=%270%27 y2=%271%27%3E%3Cstop offset=%270%27 stop-color=%27oklch(0.95 0.015 150)%27/%3E%3Cstop offset=%271%27 stop-color=%27oklch(0.88 0.03 150)%27/%3E%3C/linearGradient%3E%3CradialGradient id=%27fl%27%3E%3Cstop offset=%270%27 stop-color=%27black%27 stop-opacity=%27.25%27/%3E%3Cstop offset=%271%27 stop-color=%27black%27 stop-opacity=%270%27/%3E%3C/radialGradient%3E%3C/defs%3E%3Crect width=%27480%27 height=%27360%27 fill=%27url(%23bg)%27/%3E%3Cellipse cx=%27246%27 cy=%27286%27 rx=%27186%27 ry=%2716%27 fill=%27url(%23fl)%27/%3E%3Cpath d=%27M70 246 Q70 276 104 280 L386 280 Q424 278 428 246 Z%27 fill=%27oklch(0.3 0.03 160)%27/%3E%3Cpath d=%27M104 280v9M140 280v9M176 280v9M212 280v9M248 280v9M284 280v9M320 280v9M356 280v9M392 280v8%27 stroke=%27oklch(0.3 0.03 160)%27 stroke-width=%2712%27/%3E%3Cpath d=%27M74 236 L426 236 Q430 254 416 262 L98 262 Q76 258 74 236Z%27 fill=%27oklch(0.96 0.01 90)%27/%3E%3Cpath d=%27M82 238 Q76 196 118 174 L192 136 Q212 98 252 94 L290 96 Q302 138 340 158 L392 182 Q428 200 426 238 Z%27 fill=%27oklch(0.66 0.16 40)%27/%3E%3Cpath d=%27M290 96 Q302 138 340 158 L392 182 Q428 200 426 238 L360 238 Q350 180 300 150 Z%27 fill=%27black%27 fill-opacity=%27.1%27/%3E%3Cpath d=%27M212 126 L262 148 M204 142 L254 164 M196 158 L246 180%27 stroke=%27oklch(0.96 0.01 90)%27 stroke-width=%277%27 stroke-linecap=%27round%27/%3E%3Cpath d=%27M104 218 Q230 200 416 220%27 stroke=%27oklch(0.3 0.03 160)%27 stroke-opacity=%27.45%27 stroke-width=%276%27 fill=%27none%27/%3E%3Cpath d=%27M120 200 Q160 186 176 150%27 stroke=%27white%27 stroke-opacity=%27.35%27 stroke-width=%275%27 fill=%27none%27 stroke-linecap=%27round%27/%3E%3Ccircle cx=%27378%27 cy=%27206%27 r=%279%27 fill=%27oklch(0.96 0.01 90)%27 fill-opacity=%27.8%27/%3E%3C/svg%3E" width="160" height="160" id="av-thumb">
            <img src="data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 480 360%27%3E%3Cdefs%3E%3ClinearGradient id=%27bg%27 x1=%270%27 y1=%270%27 x2=%270%27 y2=%271%27%3E%3Cstop offset=%270%27 stop-color=%27oklch(0.95 0.015 150)%27/%3E%3Cstop offset=%271%27 stop-color=%27oklch(0.88 0.03 150)%27/%3E%3C/linearGradient%3E%3CradialGradient id=%27fl%27%3E%3Cstop offset=%270%27 stop-color=%27black%27 stop-opacity=%27.25%27/%3E%3Cstop offset=%271%27 stop-color=%27black%27 stop-opacity=%270%27/%3E%3C/radialGradient%3E%3C/defs%3E%3Crect width=%27480%27 height=%27360%27 fill=%27url(%23bg)%27/%3E%3Cellipse cx=%27246%27 cy=%27286%27 rx=%27186%27 ry=%2716%27 fill=%27url(%23fl)%27/%3E%3Cpath d=%27M70 246 Q70 276 104 280 L386 280 Q424 278 428 246 Z%27 fill=%27oklch(0.3 0.03 160)%27/%3E%3Cpath d=%27M104 280v9M140 280v9M176 280v9M212 280v9M248 280v9M284 280v9M320 280v9M356 280v9M392 280v8%27 stroke=%27oklch(0.3 0.03 160)%27 stroke-width=%2712%27/%3E%3Cpath d=%27M74 236 L426 236 Q430 254 416 262 L98 262 Q76 258 74 236Z%27 fill=%27oklch(0.96 0.01 90)%27/%3E%3Cpath d=%27M82 238 Q76 196 118 174 L192 136 Q212 98 252 94 L290 96 Q302 138 340 158 L392 182 Q428 200 426 238 Z%27 fill=%27oklch(0.66 0.16 40)%27/%3E%3Cpath d=%27M290 96 Q302 138 340 158 L392 182 Q428 200 426 238 L360 238 Q350 180 300 150 Z%27 fill=%27black%27 fill-opacity=%27.1%27/%3E%3Cpath d=%27M212 126 L262 148 M204 142 L254 164 M196 158 L246 180%27 stroke=%27oklch(0.96 0.01 90)%27 stroke-width=%277%27 stroke-linecap=%27round%27/%3E%3Cpath d=%27M104 218 Q230 200 416 220%27 stroke=%27oklch(0.3 0.03 160)%27 stroke-opacity=%27.45%27 stroke-width=%276%27 fill=%27none%27/%3E%3Cpath d=%27M120 200 Q160 186 176 150%27 stroke=%27white%27 stroke-opacity=%27.35%27 stroke-width=%275%27 fill=%27none%27 stroke-linecap=%27round%27/%3E%3Ccircle cx=%27378%27 cy=%27206%27 r=%279%27 fill=%27oklch(0.96 0.01 90)%27 fill-opacity=%27.8%27/%3E%3C/svg%3E" alt="Quick-lace detail" width="160" height="160">
          </div>
        </div>

        <div class="av-info">
          <p class="av-brand">Nomad Supply Co. · Trail</p>
          <h2 id="av-title">Aster 3 Trail Running Shoe</h2>
          <a class="av-reviews" href="#avis"><span aria-hidden="true">★★★★☆</span>Read reviews (128)</a>
          <p class="av-price">$139.00 <span class="av-dot" title="In stock" id="av-dot"></span></p>

          <div class="av-buy">
            <div class="mv-field">
              <label class="mv-label" for="av-size">Size (US)</label>
              <select class="mv-select" id="av-size">
                <option>8</option><option>9</option><option selected>10</option><option>10.5</option><option>11</option>
              </select>
            </div>
            <div class="mv-button" data-size="lg" id="av-cart" onclick="this.textContent = 'Added ✓'">Add to cart</div>
          </div>

          <h4 class="av-h" id="av-heading">Shipping &amp; returns</h4>
          <ul class="av-perks">
            <li><span>Free shipping on orders over $75</span><a href="#shipping">Learn more</a></li>
            <li><span>Free returns within 30 days</span><a href="#returns">Learn more</a></li>
            <li><span>2-year workshop warranty</span><a href="#warranty">Learn more</a></li>
          </ul>

          <form class="av-promo" aria-label="Promo code" onsubmit="event.preventDefault()">
            <div class="av-promo-row">
              <input class="mv-input" id="av-code" placeholder="Promo code" autocomplete="off">
              <button class="mv-button" data-variant="secondary" type="submit">Apply</button>
            </div>
          </form>
        </div>
      </div>
    </article>
  </mv-agent-vision>
  <p class="av-hint">Arrow keys or <kbd class="mv-kbd">Home</kbd> / <kbd class="mv-kbd">End</kbd> on the handle · “Fix the page” applies the fixes live and re-runs the scan</p>

  <script type="module">
    const vision = document.getElementById("av-vision");
    const fix = document.getElementById("av-fix");
    const $ = (id) => document.getElementById(id);
    await customElements.whenDefined("mv-agent-vision");

    // Semantic twins of the broken elements, swapped in and out.
    const fakeCart = $("av-cart");
    const realCart = Object.assign(document.createElement("button"), { type: "button", className: "mv-button", textContent: "Add to cart" });
    realCart.dataset.size = "lg";
    const badHeading = $("av-heading");
    const goodHeading = Object.assign(document.createElement("h3"), { className: "av-h", textContent: badHeading.textContent });
    const label = Object.assign(document.createElement("label"), { className: "mv-label", htmlFor: "av-code", textContent: "Promo code" });
    const stock = Object.assign(document.createElement("span"), { className: "av-stock", textContent: "In stock" });
    const links = [...document.querySelectorAll("#av-demo .av-perks a")];
    const precise = ["Learn more about shipping", "Learn more about returns", "Learn more about the warranty"];

    const apply = (fixed) => {
      const toggle = (el, name, value) => (fixed ? el.setAttribute(name, value) : el.removeAttribute(name));
      toggle($("av-fav"), "aria-label", "Add to wishlist");
      toggle($("av-share"), "aria-label", "Share");
      toggle($("av-thumb"), "alt", "Lugged outsole, bottom view");
      (fixed ? fakeCart : realCart).replaceWith(fixed ? realCart : fakeCart);
      (fixed ? badHeading : goodHeading).replaceWith(fixed ? goodHeading : badHeading);
      const dot = $("av-dot");
      if (fixed) { dot.removeAttribute("title"); dot.setAttribute("aria-hidden", "true"); dot.after(stock); }
      else { dot.title = "In stock"; dot.removeAttribute("aria-hidden"); stock.remove(); }
      links.forEach((a, i) => toggle(a, "aria-label", precise[i]));
      if (fixed) document.querySelector("#av-demo .av-promo").prepend(label); else label.remove();
      fix.dataset.fixed = String(fixed);
      fix.textContent = fixed ? "Bring the flaws back" : "Fix the page";
    };
    fix.addEventListener("click", () => apply(fix.dataset.fixed !== "true"));

    vision.addEventListener("mv-agent-scan", (e) => console.info("mv-agent-scan", e.detail.score, e.detail.issues.length));
  </script>
</div>

API

Attributes

NameTipoDefaultDescription
splitnumber (0-100)55Scan line position, as the % of the region shown in human view (the rest is agent view).
scopeCSS selectorRestricts the analysis to matching elements inside the region (default: all wrapped content).
showall | issuesallFull agent view, or only the boxes with an issue. Also driven by the toggle in the panel.

Properties

NameTipoDescription
splitnumberCurrent line position (read/write; dragging does not rewrite the attribute).
scorenumberAgent readability, 0-100: 100 − 7 per blocking issue − 3 per minor issue (a group of duplicate names counts once).
issues{ type, severity, severityLabel, title, what, note, fix, role, name, count }[]Detected issues, blockers first. severity: "blocker" | "minor". A non-enumerable elements property holds the affected nodes.
tree{ role, label, name, level, states, rect, issue }[]Perceived tree, JSON-serialisable: ARIA role, readable label, accessible name, states, rect relative to the region, issue if any.

Methods

NameDescription
scan()Re-runs the analysis now, announces the result and returns { score, issues } (the analysis also runs on its own, batched per frame).
focusIssue(index)Moves the line so the element is in agent view, scrolls it on screen if needed, selects and pulses its box, and announces the issue and its fix.

Events

NameDescription
mv-agent-scanAnalysis finished with a new result (or an explicit scan()). detail: { score, issues }.

Content structure

NameDescription
(content)One child element: the region to analyse (card, section, form, whole page…). It stays fully interactive on both sides of the line.

CSS classes

NameDescription
mv-agent-vision-layer / -box / -tagAgent view layer (aria-hidden), wireframe boxes (data-kind control | heading | media | container, data-issue blocker | minor, data-selected) and their tree line.
mv-agent-vision-rail / -handle / -scanSplitter: role=slider handle and glowing scan line.
mv-agent-vision-summary / -list / -issuePanel: readability gauge, counts, display toggle, issue list (buttons).

CSS variables

NameDefaultDescription
--mv-agent-vision-accentvar(--mv-accent)Scan line and interactive box color.
--mv-agent-vision-blockervar(--mv-danger)Blocking issue color (always paired with an icon and a label).
--mv-agent-vision-minorvar(--mv-warning)Minor issue color.
--mv-agent-vision-radiusvar(--mv-radius-xl)Agent view layer radius (match it to the region's).
--mv-agent-vision-grid16pxPitch of the grid that replaces the visual rendering.

Accessibility

The tool is accessible itself. The handle is a role="slider" (arrows ±2, Shift ±10, Page Up/Down ±10, Home = all agent view, End = all human view) with aria-valuetext "48% human view, 52% agent view". The agent view layer is aria-hidden and pointer-events: none: the region keeps its keyboard, clicks and accessibility tree intact on both sides. The issue list is a real list of buttons (Tab, or Up/Down arrows, Home/End); the active issue carries aria-current. A polite live region announces the score when the analysis changes and, when an issue is selected, its description and fix. Severity is always an icon + label ("Blocker", "Minor") on top of color. Reduced motion: no typed-in labels or pulse, instant scrolling. No loop: everything is driven by MutationObserver, ResizeObserver and events, batched into one read-then-write pass per frame.

Esta página se tradujo con IA. Informar de un problema de traducción