diff --git a/static/css/iris-demo.css b/static/css/iris-demo.css
index bac94fa077..96e555ea8d 100644
--- a/static/css/iris-demo.css
+++ b/static/css/iris-demo.css
@@ -18,11 +18,10 @@
.iris:not(.iris-preview) .iris-stagewrap { max-width: 75%; margin-left: auto; margin-right: auto; }
@media (max-width: 640px) { .iris:not(.iris-preview) .iris-stagewrap { max-width: 100%; } }
.iris-stage { position: relative; aspect-ratio: 613.5 / 423.5; /* VIEW in iris-demo.js */ border-radius: 11px; overflow: hidden; background: #0D212C; }
-/* The four published versions of the drawing, stacked twice. In a stack, a step shows the versions it needs and the
- script sets how they blend; isolation keeps that blend inside the stack. The new stack fades in over the old one. */
+/* The published versions of the drawing, in two stacks. In a stack, a step shows the versions it needs as background
+ images, and the script sets how they blend. The new stack fades in over the old one. */
.iris-artset { position: absolute; inset: 0; isolation: isolate; opacity: 0; transition: opacity .45s; }
-.iris .iris-art { position: absolute; inset: 0; width: 100%; height: 100%; max-width: none; margin: 0; opacity: 0; pointer-events: none; user-select: none; }
-.iris .iris-art.is-on { opacity: 1; }
+.iris .iris-art { position: absolute; margin: 0; background-size: 100% 100%; background-repeat: no-repeat; pointer-events: none; user-select: none; }
.iris-over { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.iris-route { fill: none; stroke: none; }
.iris-hit { fill: transparent; cursor: pointer; }
diff --git a/static/js/iris-demo.js b/static/js/iris-demo.js
index 3466b044c2..1d5bb7936d 100644
--- a/static/js/iris-demo.js
+++ b/static/js/iris-demo.js
@@ -564,18 +564,26 @@
Each version of the drawing shows its lit service's label box, and data-integration.svg also shows the
Context Retriever box. The stage draws the same box, with the current name, at the same place, and
shows it whenever a version in `in` is lit (see compose()). Boxes are x, y, width, height, copied from
- langcache.svg and context-retriever.svg. */
+ langcache.svg and context-retriever.svg.
+ The Redis and agent labels are lit in every version, so the stage draws them as text too, always shown
+ (`always`), with their boxes copied from agent-memory.svg. They then look exactly like the labels the stage
+ adds, such as Maya's. The agent's box is as tall as Maya's, so its text sits as Maya's does (`base`). */
var RELABEL = {
cache: { box: [471.578, 518.156, 99.2506, 24.4832], lines: ["AGENT PLAYBOOKS"], in: ["cache"] },
- retriever: { box: [498.461, 235.889, 99.2506, 31.2039], lines: ["CONTEXT", "GATEWAY"], in: ["retriever"] }
+ retriever: { box: [498.461, 235.889, 99.2506, 31.2039], lines: ["CONTEXT", "GATEWAY"], in: ["retriever"] },
+ redis: { box: [370.684, 287.974, 84.6654, 32.7885], lines: ["REDIS SEARCH", "(IN REDIS DB)"], always: true },
+ agent: { box: [632.932, 436.729, 43.1543, 24.751], lines: ["AGENT"], always: true, rx: 3.78037, stroke: 0.840082, base: 3.69 }
};
function buildRelabels(NS) {
var out = {};
Object.keys(RELABEL).forEach(function (k) {
var R = RELABEL[k], b = R.box, g = document.createElementNS(NS, "g");
- var mid = b[1] + b[3] / 2, gap = 10, first = mid - (R.lines.length - 1) * gap / 2 + 2.95; // 2.95: half the glyphs' cap height
- g.setAttribute("class", "iris-relabel");
- g.innerHTML = '' +
+ var mid = b[1] + b[3] / 2, gap = 10, first = mid - (R.lines.length - 1) * gap / 2 + (R.base || 2.95); // 2.95: half the glyphs' cap height
+ g.setAttribute("class", "iris-relabel" + (R.always ? " is-on" : ""));
+ /* An always-shown box first covers the drawing's own box, 2 units larger all round: the drawing can land up to
+ a device pixel away from the overlay, so its outline would otherwise show at the edges. */
+ g.innerHTML = (R.always ? '' : "") +
+ '' +
R.lines.map(function (t, i) {
return '' + esc(t) + "";
}).join("");
@@ -674,22 +682,19 @@
var box = el("div", "iris-stage");
box.setAttribute("role", "img");
/* Two stacks of the versions. A step blends its versions in the stack that isn't showing, then
- fades that stack in over the other, so a half-faded version never blends the wrong way. */
+ fades that stack in over the other, so a half-faded version never blends the wrong way.
+ Each stack is one element with the versions as its background images, blended with
+ background-blend-mode. Stacked images blended with mix-blend-mode would do the same, but Chrome
+ draws them at a lower resolution, and "darken" then thins the labels' text. */
var sets = [0, 1].map(function () {
- var set = el("div", "iris-artset"), layers = {};
- ["retriever", "cache", "memory"].forEach(function (k) {
- var img = el("img", "iris-art");
- img.style.left = vx(0); img.style.top = vy(0); img.style.width = vw(ART_W); img.style.height = vh(ART_H);
- img.src = artBase + ART[k];
- img.alt = "";
- img.decoding = "async";
- img.draggable = false;
- set.appendChild(img);
- layers[k] = img;
- });
+ var set = el("div", "iris-artset"), art = el("div", "iris-art");
+ art.style.left = vx(0); art.style.top = vy(0); art.style.width = vw(ART_W); art.style.height = vh(ART_H);
+ set.appendChild(art);
box.appendChild(set);
- return { el: set, layers: layers };
+ return { el: set, art: art };
});
+ /* Load every version up front, so the first step that uses one doesn't wait for it. */
+ var preload = ["retriever", "cache", "memory"].map(function (k) { var i = new Image(); i.src = artBase + ART[k]; return i; });
var cur = sets[1];
var NS = "http://www.w3.org/2000/svg";
var over = document.createElementNS(NS, "svg");
@@ -750,13 +755,11 @@
/* Show some versions of the drawing: the first one as is, the rest blended onto it. */
function compose(keys, blend) {
- var first = true, next = cur === sets[0] ? sets[1] : sets[0];
- ["retriever", "cache", "memory"].forEach(function (k) {
- var on = keys.indexOf(k) >= 0, img = next.layers[k];
- img.classList.toggle("is-on", on);
- img.style.mixBlendMode = on && !first ? (blend || "lighten") : "normal";
- if (on) first = false;
- });
+ var next = cur === sets[0] ? sets[1] : sets[0];
+ var shown = ["retriever", "cache", "memory"].filter(function (k) { return keys.indexOf(k) >= 0; });
+ next.art.style.backgroundImage = shown.map(function (k) { return 'url("' + artBase + ART[k] + '")'; }).join(", ");
+ next.art.style.backgroundBlendMode = shown.length > 1 ? (blend || "lighten") : "normal";
+ next.art.dataset.versions = shown.join(" "); // what the stack shows, for the tests
/* The showing stack stays put underneath; the new one starts clear on top and fades in. */
cur.el.style.transition = "none";
cur.el.style.opacity = "1";
@@ -771,8 +774,10 @@
cur = next;
/* Agent Playbooks' disc is lit where its version is, as its label is. */
pbDisc.classList.toggle("is-lit", keys.indexOf("cache") >= 0 && (keys.length === 1 || blend !== "darken"));
- /* A label shows where a version that has it is lit; "darken" keeps only what every version lights, which no label is. */
+ /* A label shows where a version that has it is lit; "darken" keeps only what every version lights, which no service's
+ label is. The Redis and agent labels always show. */
Object.keys(relabels).forEach(function (k) {
+ if (RELABEL[k].always) return;
var shown = RELABEL[k].in.some(function (v) { return keys.indexOf(v) >= 0; });
relabels[k].classList.toggle("is-on", shown && (keys.length === 1 || blend !== "darken"));
});