This commit is contained in:
Abdul Wahab
2026-09-01 10:04:59 +05:00
parent 8b6bbaef3d
commit 6343ec689b
4 changed files with 426 additions and 75 deletions
+34 -13
View File
@@ -1077,9 +1077,10 @@ const questions = [
{/* Screen 04b: the configure hub. Every remaining question already
holds an answer (defaults are pre-filled the moment a surface tile
is checked), so the run can end here. The cards are skeletons;
summaries and edited marks are written by renderHub() in
scripts/palette-picker.js on every arrival. Placement is the
approved masonry: tall per-surface cards anchor the outer columns. */}
previews, tabs, tooltip summaries, and edited marks are written by
renderHub() in scripts/palette-picker.js on every arrival. The
column wrappers are display: contents, so the five near-uniform
cards flow the grid three over two. */}
<section class="picker-screen" data-screen="04b" data-step="Configure" aria-hidden="true" aria-labelledby="picker-hub-title">
<div class="picker-container">
<div class="picker-hub">
@@ -1092,51 +1093,71 @@ const questions = [
<div class="picker-hub-grid">
<div class="picker-hub-col">
<button class="picker-hub-card" type="button" data-hub-target="06" data-hub-category="material">
<button class="picker-hub-card" type="button" data-hub-target="06" data-hub-category="material" aria-describedby="picker-hub-tip-06">
<span class="picker-hub-eyebrow">Material</span>
<span class="picker-hub-title">Motion
<svg class="picker-hub-arrow" viewBox="0 0 16 8" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="square" aria-hidden="true"><path d="M0 4h14M10 0l4 4-4 4"></path></svg>
<span class="picker-hub-mark" data-hub-mark hidden>Edited</span>
</span>
<span class="picker-hub-summary" data-hub-summary></span>
<span class="picker-hub-preview" data-hub-preview aria-hidden="true"></span>
<span class="picker-hub-tabs" data-hub-tabs hidden></span>
<span class="picker-hub-tip" role="tooltip" id="picker-hub-tip-06" data-hub-tip>
<span class="picker-hub-summary" data-hub-summary></span>
</span>
</button>
<button class="picker-hub-card" type="button" data-hub-target="08" data-hub-category="material">
<button class="picker-hub-card" type="button" data-hub-target="08" data-hub-category="material" aria-describedby="picker-hub-tip-08">
<span class="picker-hub-eyebrow">Material</span>
<span class="picker-hub-title">Boundaries
<svg class="picker-hub-arrow" viewBox="0 0 16 8" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="square" aria-hidden="true"><path d="M0 4h14M10 0l4 4-4 4"></path></svg>
<span class="picker-hub-mark" data-hub-mark hidden>Edited</span>
</span>
<span class="picker-hub-summary" data-hub-summary></span>
<span class="picker-hub-preview" data-hub-preview aria-hidden="true"></span>
<span class="picker-hub-tabs" data-hub-tabs hidden></span>
<span class="picker-hub-tip" role="tooltip" id="picker-hub-tip-08" data-hub-tip>
<span class="picker-hub-summary" data-hub-summary></span>
</span>
</button>
</div>
<div class="picker-hub-col">
<button class="picker-hub-card" type="button" data-hub-target="11" data-hub-category="iconography">
<button class="picker-hub-card" type="button" data-hub-target="11" data-hub-category="iconography" aria-describedby="picker-hub-tip-11">
<span class="picker-hub-eyebrow">Iconography</span>
<span class="picker-hub-title">Icon set
<svg class="picker-hub-arrow" viewBox="0 0 16 8" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="square" aria-hidden="true"><path d="M0 4h14M10 0l4 4-4 4"></path></svg>
<span class="picker-hub-mark" data-hub-mark hidden>Edited</span>
</span>
<span class="picker-hub-summary" data-hub-summary></span>
<span class="picker-hub-preview" data-hub-preview aria-hidden="true"></span>
<span class="picker-hub-tabs" data-hub-tabs hidden></span>
<span class="picker-hub-tip" role="tooltip" id="picker-hub-tip-11" data-hub-tip>
<span class="picker-hub-summary" data-hub-summary></span>
</span>
</button>
<button class="picker-hub-card" type="button" data-hub-target="09" data-hub-category="material">
<button class="picker-hub-card" type="button" data-hub-target="09" data-hub-category="material" aria-describedby="picker-hub-tip-09">
<span class="picker-hub-eyebrow">Material</span>
<span class="picker-hub-title">Corners
<svg class="picker-hub-arrow" viewBox="0 0 16 8" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="square" aria-hidden="true"><path d="M0 4h14M10 0l4 4-4 4"></path></svg>
<span class="picker-hub-mark" data-hub-mark hidden>Edited</span>
</span>
<span class="picker-hub-summary" data-hub-summary></span>
<span class="picker-hub-preview" data-hub-preview aria-hidden="true"></span>
<span class="picker-hub-tabs" data-hub-tabs hidden></span>
<span class="picker-hub-tip" role="tooltip" id="picker-hub-tip-09" data-hub-tip>
<span class="picker-hub-summary" data-hub-summary></span>
</span>
</button>
</div>
<div class="picker-hub-col">
<button class="picker-hub-card" type="button" data-hub-target="10" data-hub-category="material">
<button class="picker-hub-card" type="button" data-hub-target="10" data-hub-category="material" aria-describedby="picker-hub-tip-10">
<span class="picker-hub-eyebrow">Material</span>
<span class="picker-hub-title">Depth
<svg class="picker-hub-arrow" viewBox="0 0 16 8" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="square" aria-hidden="true"><path d="M0 4h14M10 0l4 4-4 4"></path></svg>
<span class="picker-hub-mark" data-hub-mark hidden>Edited</span>
</span>
<span class="picker-hub-summary" data-hub-summary></span>
<span class="picker-hub-preview" data-hub-preview aria-hidden="true"></span>
<span class="picker-hub-tabs" data-hub-tabs hidden></span>
<span class="picker-hub-tip" role="tooltip" id="picker-hub-tip-10" data-hub-tip>
<span class="picker-hub-summary" data-hub-summary></span>
</span>
</button>
</div>
</div>
+226 -48
View File
@@ -2347,61 +2347,239 @@ function hubOptionDesc(group, value) {
return (desc.dataset.copy ?? desc.textContent).trim();
}
/* ============================================================
Hub previews: each card's body is a clone of its question's own
artboard, painted with the committed palette and the previewed
surface's answers.
The material clones borrow design-context.css's proof frame: the
committed bodies there key off data-dcx-* attributes on the frame
because a clone cannot ride the #picker-form:has() selectors its
original took its rendition from once the answer has to differ per
card. The stylesheet is already on this page, so nothing is
restated. The motion clone is the one exception: its scenes exist
only as #picker-form:has() rules with no dcx mirror, so it keeps
its scene classes, stays keyed to the live motion-energy radio,
and the renderer parks that radio on the previewed surface's
answer the same way the question screens park it. The keyframes
are infinite, so the clone loops on its own; the hover-restart
wiring never reaches it (replayMotion holds the boards it listed
at load, and screen 06's hover rows are display: none here).
============================================================ */
const HUB_PREVIEW_MARK_GROUPS = {
strategy: 'color-strategy',
boundary: 'boundary-style',
corner: 'corner-style',
depth: 'depth-style',
layout: 'layout-structure',
};
/* One surface's committed structural answers, read off the same hidden
fields the summary rows read; the checked radio covers a flat group
whose field this surface never rendered. */
function hubPreviewMarks(mode) {
const marks = { surface: mode };
for (const [mark, group] of Object.entries(HUB_PREVIEW_MARK_GROUPS)) {
marks[mark] = document.querySelector(`input[type="hidden"][data-surface-field="${group}-${mode}"]`)?.value
|| document.querySelector(`input[name="${group}"]:checked`)?.value || '';
}
return marks;
}
/* Clone one question's mounted artboard into a proof frame, the same
lift design-context.js's proofHtml performs: ids do not survive (they
would collide with the originals), the surface attribute moves to the
frame, and the committed palette is painted on the frame under the
--pkc-* names the dcx bodies read. */
function hubProof(source, marks = null) {
const wrap = document.createElement('span');
wrap.className = 'picker-hub-proof';
if (marks) {
wrap.classList.add('dcx-proof--board');
for (const [key, value] of Object.entries(marks)) {
if (value) wrap.setAttribute(`data-dcx-${key}`, value);
}
syncCommittedPalette(wrap, 'pkc');
}
const clone = source.cloneNode(true);
clone.hidden = false;
clone.removeAttribute('data-surface');
for (const node of [clone, ...clone.querySelectorAll('[id]')]) node.removeAttribute('id');
/* The icon sheet's lookup hooks must not survive either: the hub card
sits before screen 11 in the DOM, so a clone still carrying them
would shadow the originals for every later querySelector, including
the document's own icon proof. */
for (const node of [clone, ...clone.querySelectorAll('[data-icon-field], [data-icon-strip]')]) {
node.removeAttribute('data-icon-sheet');
node.removeAttribute('data-icon-field');
node.removeAttribute('data-icon-strip');
}
wrap.append(clone);
return wrap;
}
const hubQuestionBoard = (screen, mode) => document.querySelector(
`.picker-screen[data-screen="${screen}"] .picker-artboard[data-surface="${mode}"]`,
);
/* The preview and its tab strip for one card. The active tab carries
the patina dot and the surface's answer, so the choice reads without
hovering; the tooltip carries the summary rows. */
function renderHubPreview(cardNode, rows) {
const previewSlot = cardNode.querySelector('[data-hub-preview]');
const tabsSlot = cardNode.querySelector('[data-hub-tabs]');
const screen = cardNode.dataset.hubTarget;
const group = HUB_GROUPS[screen];
if (group === 'icon-pack') {
tabsSlot.hidden = true;
tabsSlot.replaceChildren();
previewSlot.replaceChildren(hubProof(iconSheet));
/* The glyphs are fetched on screen 11's first arrival, which a run
that stops at the hub never makes; fetch them here and re-render
once. The empty marker is the failed state, which must not refetch
on every arrival. */
if (!iconField.querySelector('.picker-icon-cell') && !('empty' in iconField.dataset)) {
loadIconPacks().then(renderHub);
}
return;
}
const modes = rows.map((row) => row.mode);
const mode = modes.includes(cardNode.dataset.hubSurface) ? cardNode.dataset.hubSurface : modes[0];
cardNode.dataset.hubSurface = mode ?? '';
const board = mode ? hubQuestionBoard(screen, mode) : null;
if (!board) {
previewSlot.replaceChildren();
tabsSlot.hidden = true;
tabsSlot.replaceChildren();
return;
}
if (group === 'motion-energy') {
surfaceQuestions.find((question) => question.screen === screen)?.park(mode);
const proof = hubProof(board);
syncCommittedPalette(proof.firstChild);
previewSlot.replaceChildren(proof);
/* The route stops are measured off the clone's own layout, exactly
what screen 06 does for the originals on arrival. */
requestAnimationFrame(() => plotMotionRoute(proof.firstChild));
} else {
previewSlot.replaceChildren(hubProof(board, hubPreviewMarks(mode)));
}
tabsSlot.hidden = rows.length === 0;
tabsSlot.replaceChildren(...rows.map((row) => {
const tab = document.createElement('span');
tab.className = 'picker-hub-tab';
tab.dataset.hubTab = row.mode;
const dot = document.createElement('i');
dot.className = 'picker-hub-tab-dot';
dot.setAttribute('aria-hidden', 'true');
tab.append(dot, hubSurfaceLabel(row.mode));
if (row.mode === mode) {
tab.dataset.on = '';
const value = document.createElement('span');
value.className = 'picker-hub-tab-value';
value.textContent = hubOptionTitle(group, row.value);
tab.append(value);
}
return tab;
}));
}
function renderHubCard(cardNode) {
const group = HUB_GROUPS[cardNode.dataset.hubTarget];
if (!group) return;
const summary = cardNode.querySelector('[data-hub-summary]');
const mark = cardNode.querySelector('[data-hub-mark]');
const previewSlot = cardNode.querySelector('[data-hub-preview]');
const tabsSlot = cardNode.querySelector('[data-hub-tabs]');
const target = document.querySelector(`.picker-screen[data-screen="${cardNode.dataset.hubTarget}"]`);
const skipped = Boolean(target?.hasAttribute('data-skip'));
cardNode.classList.toggle('is-skipped', skipped);
cardNode.disabled = skipped;
cardNode.setAttribute('aria-disabled', skipped ? 'true' : 'false');
if (skipped) {
summary.replaceChildren();
previewSlot.replaceChildren(hubPlainLine('Not asked of these surfaces'));
tabsSlot.hidden = true;
tabsSlot.replaceChildren();
cardNode.classList.remove('is-edited');
mark.hidden = true;
return;
}
const rows = hubSurfaceRows(group);
let edited;
let lines;
if (rows.length === 0) {
const checked = document.querySelector(`input[name="${group}"]:checked`);
edited = hubEdited.has(group);
lines = [hubRow(
'All surfaces',
checked ? hubOptionTitle(group, checked.value) : '',
group,
checked?.value,
)];
} else {
edited = rows.some((row) => row.chosen);
if (rows.length > 1 && rows.every((row) => row.value === rows[0].value)) {
lines = [hubRow('All surfaces', hubOptionTitle(group, rows[0].value), group, rows[0].value)];
} else if (rows.length === 1) {
lines = [hubRow(hubSurfaceLabel(rows[0].mode), hubOptionTitle(group, rows[0].value), group, rows[0].value)];
} else {
lines = rows.map((row) => hubRow(
hubSurfaceLabel(row.mode),
hubOptionTitle(group, row.value),
group,
row.value,
));
}
}
summary.replaceChildren(...lines);
cardNode.classList.toggle('is-edited', edited);
mark.hidden = !edited;
renderHubPreview(cardNode, rows);
}
function renderHub() {
if (!hubScreen) return;
for (const cardNode of hubScreen.querySelectorAll('.picker-hub-card')) {
const group = HUB_GROUPS[cardNode.dataset.hubTarget];
if (!group) continue;
const summary = cardNode.querySelector('[data-hub-summary]');
const mark = cardNode.querySelector('[data-hub-mark]');
const target = document.querySelector(`.picker-screen[data-screen="${cardNode.dataset.hubTarget}"]`);
const skipped = Boolean(target?.hasAttribute('data-skip'));
cardNode.classList.toggle('is-skipped', skipped);
cardNode.disabled = skipped;
cardNode.setAttribute('aria-disabled', skipped ? 'true' : 'false');
if (skipped) {
summary.replaceChildren(hubPlainLine('Not asked of these surfaces'));
cardNode.classList.remove('is-edited');
mark.hidden = true;
continue;
}
const rows = hubSurfaceRows(group);
let edited;
let lines;
if (rows.length === 0) {
const checked = document.querySelector(`input[name="${group}"]:checked`);
edited = hubEdited.has(group);
lines = [hubRow(
'All surfaces',
checked ? hubOptionTitle(group, checked.value) : '',
group,
checked?.value,
)];
} else {
edited = rows.some((row) => row.chosen);
if (rows.length > 1 && rows.every((row) => row.value === rows[0].value)) {
lines = [hubRow('All surfaces', hubOptionTitle(group, rows[0].value), group, rows[0].value)];
} else if (rows.length === 1) {
lines = [hubRow(hubSurfaceLabel(rows[0].mode), hubOptionTitle(group, rows[0].value), group, rows[0].value)];
} else {
lines = rows.map((row) => hubRow(
hubSurfaceLabel(row.mode),
hubOptionTitle(group, row.value),
group,
row.value,
));
}
}
summary.replaceChildren(...lines);
cardNode.classList.toggle('is-edited', edited);
mark.hidden = !edited;
}
for (const cardNode of hubScreen.querySelectorAll('.picker-hub-card')) renderHubCard(cardNode);
}
/* The tooltip floats above the card and flips below when the card sits
too near the viewport top to hold it; when neither side holds the
whole panel, the roomier side takes it. Measured when the pointer or
focus arrives, before the reveal transition starts; the tip is
opacity-hidden rather than display-hidden, so its height is real. */
function placeHubTip(cardNode) {
const tip = cardNode.querySelector('[data-hub-tip]');
if (!tip) return;
const rect = cardNode.getBoundingClientRect();
const need = tip.offsetHeight + 20;
const above = rect.top;
const below = window.innerHeight - rect.bottom;
cardNode.dataset.tipAt = (above >= need || above >= below) ? 'above' : 'below';
}
hubScreen?.addEventListener('pointerover', (event) => {
const cardNode = event.target.closest('.picker-hub-card');
if (cardNode) placeHubTip(cardNode);
});
hubScreen?.addEventListener('focusin', (event) => {
const cardNode = event.target.closest('.picker-hub-card');
if (cardNode) placeHubTip(cardNode);
});
/* Cards and the finish CTA jump by screen id. The inline nav script
owns goTo(); it listens for this event, so no swap logic is
duplicated here. A disabled card never reaches this handler. */
duplicated here. A disabled card never reaches this handler. A mini
tab hit re-clones its own card instead and never travels: the card
click must stay the jump to the question. */
hubScreen?.addEventListener('click', (event) => {
const tab = event.target.closest('[data-hub-tab]');
if (tab) {
event.stopPropagation();
const cardNode = tab.closest('.picker-hub-card');
cardNode.dataset.hubSurface = tab.dataset.hubTab;
renderHubCard(cardNode);
return;
}
const cardNode = event.target.closest('[data-hub-target]');
if (!cardNode || cardNode.disabled) return;
document.dispatchEvent(new CustomEvent('picker:goto', {
+153 -8
View File
@@ -7909,10 +7909,12 @@ body.picker-page {
}
/* ============================================================
Screen 04b: the configure hub. Three packed columns of cards;
the tall per-surface cards (motion, depth) anchor the outer
tracks. Sharp corners and hairline rules, the same vocabulary
as the option rows. Summaries are written by renderHub().
Screen 04b: the configure hub. Five near-uniform preview cards
flow a three-column grid, three over two; the column wrappers
are display: contents so the markup's masonry grouping costs
nothing. Sharp corners and hairline rules, the same vocabulary
as the option rows. Previews, tabs, and the tooltip's summary
rows are written by renderHub().
============================================================ */
.picker-hub {
display: grid;
@@ -7930,14 +7932,12 @@ body.picker-page {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 14px;
align-items: start;
align-items: stretch;
width: min(100%, 1080px);
}
.picker-hub-col {
display: grid;
gap: 14px;
align-content: start;
display: contents;
}
.picker-hub-card {
@@ -8075,6 +8075,151 @@ body.picker-page {
line-height: 1.5;
}
/* The card body: a clone of the question's own artboard, written by
renderHubPreview(). The frame borrows design-context.css's
.dcx-proof--board hooks for the committed bodies, so no rendition
rule is restated here. Pointer events stay off: everything inside
the card except a mini tab is the jump to the question. */
.picker-hub-preview {
display: block;
pointer-events: none;
}
.picker-hub-proof {
display: block;
}
/* The mini tab strip: the surface-tab vocabulary at card scale. Spans
rather than buttons because the card itself is one, and a button
cannot hold another. */
.picker-hub-tabs {
display: flex;
flex-wrap: wrap;
gap: 3px;
width: fit-content;
max-width: 100%;
padding: 3px;
background: var(--ks-lacquer-raised);
border: 1px solid var(--ks-rule);
border-radius: 2px;
}
.picker-hub-tabs[hidden] {
display: none;
}
.picker-hub-tab {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 6px 10px;
color: var(--ks-text-muted);
font-size: 12.5px;
letter-spacing: 0.015em;
border-radius: 2px;
cursor: pointer;
transition:
background-color 180ms var(--ks-ease),
color 180ms var(--ks-ease);
}
.picker-hub-tab:hover {
color: var(--ks-champagne);
background: color-mix(in oklab, var(--ks-patina) 9%, var(--ks-lacquer-raised));
}
.picker-hub-tab[data-on] {
color: var(--ks-champagne);
background: color-mix(in oklab, var(--ks-patina) 14%, var(--ks-lacquer-raised));
}
/* The same report the full-size strip's dot gives: filled on the tab
being previewed, hollow on the rest. */
.picker-hub-tab-dot {
flex: none;
width: 7px;
height: 7px;
border: 1px solid color-mix(in oklab, var(--ks-patina) 55%, transparent);
border-radius: 50%;
}
.picker-hub-tab[data-on] .picker-hub-tab-dot {
background: var(--ks-patina);
border-color: var(--ks-patina);
}
.picker-hub-tab-value {
color: color-mix(in oklab, var(--ks-patina) 85%, var(--ks-champagne));
}
/* The summary rows' new home: a floating panel on the card's own
hover and focus, the contrast alert tip's pattern at card width.
Above by default; placeHubTip() flips it below when the card sits
too near the viewport top. The hovered card rises over its
neighbours so the panel is never clipped by the masonry. */
.picker-hub-card:is(:hover, :focus-within) {
z-index: 3;
}
.picker-hub-tip {
position: absolute;
left: -1px;
right: -1px;
bottom: calc(100% + 10px);
z-index: 12;
padding: 16px 18px;
display: grid;
gap: 14px;
opacity: 0;
background: var(--ks-lacquer-raised);
border: 1px solid var(--ks-rule);
border-radius: 2px;
pointer-events: none;
transform: translateY(3px);
transition:
opacity 180ms var(--ks-ease),
transform 180ms var(--ks-ease);
}
.picker-hub-tip::after {
content: "";
position: absolute;
left: 50%;
bottom: -5px;
width: 8px;
height: 8px;
background: var(--ks-lacquer-raised);
border-right: 1px solid var(--ks-rule);
border-bottom: 1px solid var(--ks-rule);
transform: translateX(-50%) rotate(45deg);
}
.picker-hub-card[data-tip-at="below"] .picker-hub-tip {
top: calc(100% + 10px);
bottom: auto;
transform: translateY(-3px);
}
.picker-hub-card[data-tip-at="below"] .picker-hub-tip::after {
top: -5px;
bottom: auto;
border: 0;
border-left: 1px solid var(--ks-rule);
border-top: 1px solid var(--ks-rule);
}
.picker-hub-card:not(.is-skipped):is(:hover, :focus-within) .picker-hub-tip {
opacity: 1;
transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
.picker-hub-tip,
.picker-hub-tab {
transition: none;
}
}
/* A question no chosen surface takes: present so the menu keeps its
shape, muted so nobody is invited into a screen the run skips. */
.picker-hub-card.is-skipped,
@@ -292,7 +292,7 @@ figure.cell iframe { display: block; border: 0; background: transparent; positio
<figcaption><span class="cell-num">26</span> Selected: Landing page + Restrained</figcaption>
<div class="scaler" data-width="918" data-height="492.21875">
<div class="clip" style="width:918px;height:492.21875px">
<iframe title="26. Selected: Landing page + Restrained" data-cell="motion--persuade--restrained" data-cell-num="26" data-section="motion" scrolling="no" style="width:1600px;height:1000px"></iframe>
<iframe title="26. Selected: Landing page + Restrained" data-cell="motion--persuade--restrained" data-cell-num="26" data-section="motion" data-premium-motion scrolling="no" style="width:1600px;height:1000px"></iframe>
</div>
</div>
</figure>
@@ -300,7 +300,7 @@ figure.cell iframe { display: block; border: 0; background: transparent; positio
<figcaption><span class="cell-num">27</span> Selected: Landing page + Responsive</figcaption>
<div class="scaler" data-width="918" data-height="492.21875">
<div class="clip" style="width:918px;height:492.21875px">
<iframe title="27. Selected: Landing page + Responsive" data-cell="motion--persuade--responsive" data-cell-num="27" data-section="motion" scrolling="no" style="width:1600px;height:1000px"></iframe>
<iframe title="27. Selected: Landing page + Responsive" data-cell="motion--persuade--responsive" data-cell-num="27" data-section="motion" data-premium-motion scrolling="no" style="width:1600px;height:1000px"></iframe>
</div>
</div>
</figure>
@@ -308,7 +308,7 @@ figure.cell iframe { display: block; border: 0; background: transparent; positio
<figcaption><span class="cell-num">28</span> Selected: Landing page + Choreographed</figcaption>
<div class="scaler" data-width="918" data-height="492.21875">
<div class="clip" style="width:918px;height:492.21875px">
<iframe title="28. Selected: Landing page + Choreographed" data-cell="motion--persuade--choreographed" data-cell-num="28" data-section="motion" scrolling="no" style="width:1600px;height:1000px"></iframe>
<iframe title="28. Selected: Landing page + Choreographed" data-cell="motion--persuade--choreographed" data-cell-num="28" data-section="motion" data-premium-motion scrolling="no" style="width:1600px;height:1000px"></iframe>
</div>
</div>
</figure>
@@ -316,7 +316,7 @@ figure.cell iframe { display: block; border: 0; background: transparent; positio
<figcaption><span class="cell-num">29</span> Selected: Portfolio + Restrained</figcaption>
<div class="scaler" data-width="918" data-height="492.21875">
<div class="clip" style="width:918px;height:492.21875px">
<iframe title="29. Selected: Portfolio + Restrained" data-cell="motion--experience--restrained" data-cell-num="29" data-section="motion" scrolling="no" style="width:1600px;height:1000px"></iframe>
<iframe title="29. Selected: Portfolio + Restrained" data-cell="motion--experience--restrained" data-cell-num="29" data-section="motion" data-premium-motion scrolling="no" style="width:1600px;height:1000px"></iframe>
</div>
</div>
</figure>
@@ -324,7 +324,7 @@ figure.cell iframe { display: block; border: 0; background: transparent; positio
<figcaption><span class="cell-num">30</span> Selected: Portfolio + Responsive</figcaption>
<div class="scaler" data-width="918" data-height="492.21875">
<div class="clip" style="width:918px;height:492.21875px">
<iframe title="30. Selected: Portfolio + Responsive" data-cell="motion--experience--responsive" data-cell-num="30" data-section="motion" scrolling="no" style="width:1600px;height:1000px"></iframe>
<iframe title="30. Selected: Portfolio + Responsive" data-cell="motion--experience--responsive" data-cell-num="30" data-section="motion" data-premium-motion scrolling="no" style="width:1600px;height:1000px"></iframe>
</div>
</div>
</figure>
@@ -332,7 +332,7 @@ figure.cell iframe { display: block; border: 0; background: transparent; positio
<figcaption><span class="cell-num">31</span> Selected: Portfolio + Choreographed</figcaption>
<div class="scaler" data-width="918" data-height="492.21875">
<div class="clip" style="width:918px;height:492.21875px">
<iframe title="31. Selected: Portfolio + Choreographed" data-cell="motion--experience--choreographed" data-cell-num="31" data-section="motion" scrolling="no" style="width:1600px;height:1000px"></iframe>
<iframe title="31. Selected: Portfolio + Choreographed" data-cell="motion--experience--choreographed" data-cell-num="31" data-section="motion" data-premium-motion scrolling="no" style="width:1600px;height:1000px"></iframe>
</div>
</div>
</figure>
@@ -855,6 +855,7 @@ function paletteVars() {
};
}
function applyToFrame(iframe) {
if (iframe.hasAttribute('data-premium-motion')) return;
var win = iframe.contentWindow;
if (!win || !win.__applyPalette) return;
win.__applyPalette(paletteVars());
@@ -873,6 +874,11 @@ var cellById = {};
PAYLOAD.cells.forEach(function (cell) { cellById[cell.id] = cell; });
Array.prototype.forEach.call(document.querySelectorAll('iframe[data-cell]'), function (iframe) {
var cell = cellById[iframe.getAttribute('data-cell')];
var cellNumber = Number(iframe.getAttribute('data-cell-num'));
if (iframe.hasAttribute('data-premium-motion')) {
iframe.src = '../motion-previews-premium.html?embed=' + cellNumber;
return;
}
iframe.addEventListener('load', function () { applyToFrame(iframe); });
iframe.srcdoc = buildDoc(cell);
if (cell.section === 'motion') {
@@ -1297,6 +1303,7 @@ Array.prototype.forEach.call(document.querySelectorAll('.scaler'), function (sca
if (!targetNumbers.has(cell.number)) return;
var frame = document.querySelector('iframe[data-cell-num="' + cell.number + '"]');
if (!frame) return;
if (frame.hasAttribute('data-premium-motion')) return;
frame.srcdoc = buildDerivedDoc(cell);
});
})();