Skip to content
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
f0bdd76
added functionality to hide library on footer scroll
fullcolorcoder Apr 16, 2026
743785f
MWPW-192736: validate milolibs branch param to prevent DOM XSS
zagi25 Apr 17, 2026
e35f7f9
Update content-replace.js
echen-adobe Apr 17, 2026
8eace50
Merge pull request #370 from adobecom/save-expanded-footer-fix
fullcolorcoder Apr 17, 2026
da6e50c
MWPW-192327 Fix color popover appearing under nav (#372)
meganthecoder Apr 17, 2026
1a88c50
fix color edit tab navigation (#368)
vvineett Apr 20, 2026
312764b
keep floating search bar until scroll reaches footer of explore page …
vvineett Apr 20, 2026
0161e1c
MWPW-192648 Color Wheel - Generate random resets primary color marker…
meganthecoder Apr 20, 2026
f52bb67
MWPW-192929 Color - Add lock to all harmonies (#379)
meganthecoder Apr 20, 2026
d04b33c
MWPW-192826 Color Wheel - Primary color can move (#375)
meganthecoder Apr 20, 2026
4243863
MWPW-193218 Fix color harmonies (#383)
meganthecoder Apr 21, 2026
da8cdff
Add console log for CDN test
nateyolles Apr 21, 2026
ba413e6
Merge pull request #387 from adobecom/nateyolles-patch-1
nateyolles Apr 21, 2026
899f1aa
CN Redirect Update 2 (#294)
echen-adobe Apr 22, 2026
ebefcc2
MWPW-192777 Fix color wheel marker stuck for #000000 (#389)
meganthecoder Apr 22, 2026
85a6491
MWPW-193349 Color Wheel - fix tab duplication (#390)
meganthecoder Apr 22, 2026
ab9e1f6
[MWPW-192254] fix analytics event as per data analytics feedback (#393)
vvineett Apr 22, 2026
f1eae9a
MWPW-193195 Color - Apply gradient toolbar (#384)
meganthecoder Apr 22, 2026
ebef323
Merge pull request #374 from adobecom/template-x-ckg-headings
hadobe Apr 23, 2026
a9bf6a6
Merge pull request #373 from zagi25/MWPW-192736
hadobe Apr 23, 2026
93b2285
Remove console log CDN test (#399)
meganthecoder Apr 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions 404.html
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@
['dk', '/'],
['it', '/'],
['br', '/'],
['cn', '/'],
['de', '/'],
['es', '/'],
['fi', '/'],
Expand All @@ -119,7 +118,6 @@
['vn_en', '/'],
['vn_vi', '/'],
['za', '/'],
['zh-Hans-CN', '/cn/' ],
['zh-Hant-TW', '/tw/'],
]
);
Expand Down
3 changes: 3 additions & 0 deletions express/code/blocks/color-blindness/color-blindness.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ export default async function decorate(block) {
layoutInstance = await createColorToolLayout(section, {
palette: initialPalette,
toolbar: {
daaLh: 'color-blindness',
variant: 'sticky-on-scroll',
showEdit: false,
showPaletteName: true,
Expand All @@ -101,6 +102,7 @@ export default async function decorate(block) {
activeId: 'color-blindness',
navLinks,
controls,
daaLh: 'color-blindness',
},
});

Expand Down Expand Up @@ -237,6 +239,7 @@ export default async function decorate(block) {
type: 'controls-only',
controls,
enableState: false,
daaLh: 'color-blindness',
onUndo: () => fullMenuEl?.querySelector('.undo-btn')?.click(),
onRedo: () => fullMenuEl?.querySelector('.redo-btn')?.click(),
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ export default async function decorate(block) {
name: initialPalette.name,
},
toolbar: {
daaLh: 'color-contrast-checker',
variant: 'sticky-on-scroll',
showEdit: false,
showPaletteName: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export const WCAG_THRESHOLDS = {

export function createDefaultActionMenuConfig(placeholders = {}) {
return {
daaLh: 'color-contrast-checker',
navLinks: [
{ id: 'palette', href: '/create/color-wheel', label: placeholders.colorPaletteLabel || 'Color palette' },
{ id: 'contrast', href: '/create/color-contrast-analyzer', label: placeholders.contrastCheckerLabel || 'Contrast checker' },
Expand Down
3 changes: 3 additions & 0 deletions express/code/blocks/color-extract/helpers/toolbar.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { createTag, getLibs } from '../../../scripts/utils.js';
import { createExpressTooltip } from '../../../scripts/color-shared/spectrum/components/express-tooltip.js';
import { UNDO_ICON, REDO_ICON } from '../../../scripts/color-shared/components/actionMenuIcons.js';
import { decorateAnalyticsAttributes } from '../../../scripts/color-shared/utils/utilities.js';

/* S2 icons from Figma — Extract-toolbar (node 3582:110610) */
const ICON_EYEDROPPER = '<svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"><mask id="eyedropper-mask" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="20" height="20"><path d="M18.2705 2.16211C17.709 1.49316 16.9385 1.10449 16.1016 1.06738C15.2002 1.05468 14.2881 1.40234 13.5976 2.09277L12.2988 3.38379C11.3457 2.88281 10.1357 3.03223 9.33495 3.83301L8.95018 4.21778C8.03099 5.13599 7.9807 6.58668 8.77635 7.57728L4.91405 11.4404C3.24803 13.1055 1.78026 14.5732 1.75487 14.5996C0.74999 15.6045 0.74999 17.2402 1.75487 18.2451C2.2578 18.7481 2.91796 18.999 3.57714 18.999C4.2373 18.999 4.89745 18.7481 5.40038 18.2451L12.4206 11.2256C12.8847 11.6072 13.4482 11.8096 14.0176 11.8096C14.664 11.8096 15.3115 11.5635 15.8037 11.0713L16.1885 10.6865C16.9873 9.8877 17.1387 8.68262 16.6416 7.73048L17.8496 6.54298L17.8545 6.5381C19.1435 5.24904 19.3184 3.40821 18.2705 2.16211ZM4.33985 17.1846C3.9209 17.6035 3.23633 17.6055 2.81544 17.1846C2.39552 16.7647 2.39552 16.0801 2.81935 15.6572C2.86818 15.6065 4.32423 14.1514 5.97462 12.501L9.81739 8.65723L11.3428 10.1826L4.33985 17.1846ZM16.7969 5.47461L15.1328 7.10938C14.9902 7.25 14.9092 7.44141 14.9082 7.64161C14.9072 7.84083 14.9863 8.03321 15.1279 8.17481C15.5283 8.5752 15.5283 9.22559 15.1279 9.62598L14.7432 10.0107C14.3428 10.4111 13.6924 10.4111 13.292 10.0107L10.0107 6.7295C9.61036 6.32911 9.61036 5.67872 10.0107 5.27833L10.3955 4.89356C10.5957 4.69336 10.8584 4.59376 11.1211 4.59376C11.3838 4.59376 11.6465 4.69337 11.8467 4.89356C12.1387 5.18653 12.6133 5.18653 12.9053 4.89551L14.6563 3.15528C15.0508 2.75977 15.5449 2.54493 16.0361 2.56641C16.4541 2.58496 16.8291 2.77832 17.1221 3.12696C17.7559 3.88087 17.3975 4.87109 16.7969 5.47461Z" fill="#292929"/><path d="M4.2 6.3C4.2 6.6866 3.8866 7 3.5 7C3.1134 7 2.8 6.6866 2.8 6.3V0.7C2.8 0.313401 3.1134 0 3.5 0C3.8866 0 4.2 0.313401 4.2 0.7V6.3Z" fill="black"/><path d="M0.7 4.2C0.313401 4.2 0 3.8866 0 3.5C0 3.1134 0.313401 2.8 0.7 2.8L6.3 2.8C6.6866 2.8 7 3.1134 7 3.5C7 3.8866 6.6866 4.2 6.3 4.2L0.7 4.2Z" fill="black"/></mask><g mask="url(#eyedropper-mask)"><rect width="20" height="20" fill="#292929"/></g></svg>';
Expand Down Expand Up @@ -120,6 +121,8 @@ export default async function createToolbar(options = {}) {

const undoBtn = await createIconButton(UNDO_ICON, 'Undo', options.onUndo);
const redoBtn = await createIconButton(REDO_ICON, 'Redo', options.onRedo);
decorateAnalyticsAttributes(undoBtn, { linkLabel: 'Undo' });
decorateAnalyticsAttributes(redoBtn, { linkLabel: 'Redo' });
undoBtn.setAttribute('aria-disabled', 'true');
redoBtn.setAttribute('aria-disabled', 'true');
historyGroup.append(undoBtn, redoBtn);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,12 @@ export function setupStickyBounds(block, searchBar) {
endSentinel.dataset.searchBarEndSentinel = 'true';
endSentinel.setAttribute('aria-hidden', 'true');
endSentinel.style.cssText = 'display:block;inline-size:1px;block-size:1px;';
colorExploreBlock.after(endSentinel);
const footer = document.querySelector('footer');
if (footer) {
footer.before(endSentinel);
} else {
colorExploreBlock.after(endSentinel);
}

let stickyEnabled = true;

Expand Down
45 changes: 35 additions & 10 deletions express/code/blocks/color-wheel/color-wheel.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ function buildDefaultActionMenuConfig(strings) {
return {
id: ACTION_MENU_ID,
activeId: 'palette',
daaLh: 'color-wheel',
navLinks: [
{ id: 'palette', label: strings.createPalette, href: '/create/color-wheel' },
{ id: 'contrast', label: strings.contrastChecker, href: '/create/color-contrast-analyzer' },
Expand All @@ -234,6 +235,7 @@ let primaryColorAdapter = null;
let sidebarNaturalWidth = 0;
let sidebarTransitionCleanup = null;
let historyCleanup = null;
let currentInitToken = 0;

function swatchHexListFromState(state) {
const swatches = state?.swatches || [];
Expand Down Expand Up @@ -475,15 +477,15 @@ function buildPrimaryColorContent(controller) {
primaryColorAdapter = null;

const state = controller.getState();
const baseColor = swatchHexListFromState(state)[0];
const baseColorIndex = state.baseColorIndex ?? 0;
const baseColor = state.swatches?.[baseColorIndex]?.hex || '#FF0000';
const adapter = createBaseColorAdapter(
baseColor,
'HEX',
{
onColorChange: (detail) => {
if (!detail?.hex) return;
controller.setBaseColor(detail.hex);
controller.setSwatchHex(0, detail.hex);
},
onColorChangeEnd: () => {
// eslint-disable-next-line no-underscore-dangle
Expand All @@ -493,10 +495,11 @@ function buildPrimaryColorContent(controller) {
const locked = detail?.locked;
const current = swatchRailController?.getState?.()?.lockedByIndex || new Set();
const next = new Set(current);
const currentBaseIndex = controller.getState().baseColorIndex ?? 0;
if (locked) {
next.add(0);
next.add(currentBaseIndex);
} else {
next.delete(0);
next.delete(currentBaseIndex);
}
swatchRailController?.setState?.({ lockedByIndex: next });
},
Expand Down Expand Up @@ -614,7 +617,12 @@ function createSwatchRailControllerBridge(controller) {
} else {
incoming = [];
}
const prevSize = lockedByIndex.size;
lockedByIndex = new Set(incoming.filter((index) => Number.isInteger(index) && index >= 0));
const lockAdded = lockedByIndex.size > prevSize;
if (lockAdded && controller.getState().harmonyRule !== 'CUSTOM') {
controller.setHarmonyRule('CUSTOM');
}
}

const current = controller.getState();
Expand Down Expand Up @@ -774,13 +782,20 @@ export default async function decorate(block) {
}
block.className = 'color-wheel';

// Each init() call claims a token. After every await, bail if a newer call has started.
// This prevents a stale concurrent init from appending duplicate tabs/layout to the DOM.
currentInitToken += 1;
const myToken = currentInitToken;

try {
const [strings, { getResolvedPalette, getResolvedPaletteName }] = await Promise.all([
loadPlaceholders(),
Promise.resolve(createColorPaletteParamApi()),
loadHeavyModules(),
]);

if (myToken !== currentInitToken) return;

// First load: authored content was preserved during the async wait; clear it now
if (!isReinit) {
cleanup();
Expand Down Expand Up @@ -809,6 +824,7 @@ export default async function decorate(block) {
layoutInstance = await createColorToolLayout(section, {
palette: initialPalette,
toolbar: {
daaLh: 'color-wheel',
variant: 'sticky-on-scroll',
showEdit: false,
showPalette: true,
Expand All @@ -830,6 +846,7 @@ export default async function decorate(block) {
// If no HISTORY_EVENT fires (e.g. all colors locked, palette unchanged),
// reset the flag so it doesn't corrupt the next undo/redo
queueMicrotask(() => { isGeneratingRandom = false; });
primaryColorAdapter?.element?.resetOriginalColor?.();
},
transformPalette: makeTransformPalette(
() => activeHarmonyRule,
Expand Down Expand Up @@ -878,17 +895,17 @@ export default async function decorate(block) {
},
});

if (myToken !== currentInitToken) return;

const stripHost = createTag('div', { class: 'color-wheel-strip-host' });
layoutInstance.slots.canvas.appendChild(stripHost);

let activeTab = 'color-wheel';

const updateBaseColorBadge = () => {
const hide = activeTab !== 'color-wheel' || activeHarmonyRule === 'CUSTOM';
const hideLock = activeTab === 'color-wheel' && activeHarmonyRule !== 'CUSTOM';
stripHost.querySelectorAll('color-swatch-rail').forEach((rail) => {
rail.hideBaseColorBadge = hide;
rail.hideLock = hideLock;
});
};

Expand All @@ -907,6 +924,8 @@ export default async function decorate(block) {
}),
]);

if (myToken !== currentInitToken) return;

// Both resolved — wire up action menu history and append tabs
const actionMenuApi = layoutInstance.actionMenu;
let restoringFromHistory = false;
Expand Down Expand Up @@ -984,6 +1003,7 @@ export default async function decorate(block) {
onGenerateRandom: () => {
isGeneratingRandom = true;
queueMicrotask(() => { isGeneratingRandom = false; });
primaryColorAdapter?.element?.resetOriginalColor?.();
},
transformPalette: makeTransformPalette(
() => activeHarmonyRule,
Expand Down Expand Up @@ -1031,8 +1051,12 @@ export default async function decorate(block) {
const badgeRuleUnsubscribe = controller.subscribe((state) => {
const rule = state.harmonyRule || 'CUSTOM';
if (rule !== activeHarmonyRule) {
const wasCustom = activeHarmonyRule === 'CUSTOM';
activeHarmonyRule = rule;
updateBaseColorBadge();
if (wasCustom && rule !== 'CUSTOM') {
swatchRailController?.setState?.({ lockedByIndex: new Set() });
}
}
});
const prevHistoryCleanup = historyCleanup;
Expand Down Expand Up @@ -1070,11 +1094,12 @@ export default async function decorate(block) {
paletteUnsubscribe = controller.subscribe((state) => {
currentPalette = paletteFromThemeState(state);
layoutInstance?.context?.set('palette', currentPalette);
const firstHex = swatchHexListFromState(state)[0];
const baseIdx = state.baseColorIndex ?? 0;
const baseHex = state.swatches?.[baseIdx]?.hex;
const currentColor = primaryColorAdapter?.element?.color;
if (primaryColorAdapter?.setColor && firstHex
&& String(currentColor).toUpperCase() !== String(firstHex).toUpperCase()) {
primaryColorAdapter.setColor(firstHex);
if (primaryColorAdapter?.setColor && baseHex
&& String(currentColor).toUpperCase() !== String(baseHex).toUpperCase()) {
primaryColorAdapter.setColor(baseHex);
}
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1324,7 +1324,7 @@ export class ColorSwatchRail extends LitElement {
const stackedContent = html`
<div class="bottom-info bottom-info--stacked" part="bottom-info">
${showEdit ? html`<input type="color" id="edit-input-${index}" class="edit-input-native" tabindex="-1" aria-hidden="true" value=${swatch.hex} @input=${(ev) => this._onNativePickerChange(index, ev)} @change=${() => this._markNativePickerClosedSoon(50)} @blur=${() => this._markNativePickerClosedSoon(50)} />` : ''}
${f.hexCode ? ((showEdit || f.copyFromHex) ? html`<button type="button" class="hex-code hex-code--${showEdit ? 'editable' : 'copyable'} swatch-column-focusable" tabindex="-1" @click=${showEdit ? (ev) => this._handleColorPicker(index, ev.currentTarget) : (ev) => this._handleCopy(swatch.hex, ev.currentTarget)} aria-label=${showEdit ? 'Edit color' : 'Copy hex'} title=${showEdit ? 'Edit color' : 'Copy hex'}>${swatch.hex}</button>` : html`<span class="hex-code hex-code--static">${swatch.hex}</span>`) : ''}
${f.hexCode ? ((showEdit || f.copyFromHex) ? html`<button type="button" class="hex-code hex-code--${showEdit ? 'editable' : 'copyable'} swatch-column-focusable${this._activeEditIndex === index ? ' hex-code--editor-open' : ''}" tabindex="-1" @click=${showEdit ? (ev) => this._handleColorPicker(index, ev.currentTarget) : (ev) => this._handleCopy(swatch.hex, ev.currentTarget)} aria-label=${showEdit ? 'Edit color' : 'Copy hex'} title=${showEdit ? 'Edit color' : 'Copy hex'}>${swatch.hex}</button>` : html`<span class="hex-code hex-code--static">${swatch.hex}</span>`) : ''}
</div>
${stackedIcons}
`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1021,11 +1021,17 @@ export const style = css`
height: 32px;
border-radius: var(--Corner-radius-corner-radius-100);
}
.swatch-column[data-contrast="dark"] button.hex-code:hover,
@media (hover: hover) {
.swatch-column[data-contrast="dark"] button.hex-code:hover {
background-color: rgba(255, 255, 255, 0.12);
}
.swatch-column[data-contrast="light"] button.hex-code:hover {
background-color: rgba(0, 0, 0, 0.12);
}
}
.swatch-column[data-contrast="dark"] button.hex-code.hex-code--editor-open {
background-color: rgba(255, 255, 255, 0.12);
}
.swatch-column[data-contrast="light"] button.hex-code:hover,
.swatch-column[data-contrast="light"] button.hex-code.hex-code--editor-open {
background-color: rgba(0, 0, 0, 0.12);
}
Expand Down Expand Up @@ -1063,11 +1069,13 @@ export const style = css`



.swatch-column[data-contrast="dark"] .icon-button:hover {
background-color: rgba(255, 255, 255, 0.12);
}
.swatch-column[data-contrast="light"] .icon-button:hover {
background-color: rgba(0, 0, 0, 0.12);
@media (hover: hover) {
.swatch-column[data-contrast="dark"] .icon-button:hover {
background-color: rgba(255, 255, 255, 0.12);
}
.swatch-column[data-contrast="light"] .icon-button:hover {
background-color: rgba(0, 0, 0, 0.12);
}
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ class BaseColor extends LitElement {
this._originalSaturation = 0;
this._originalBrightness = 0;
this._pickerInputEnabled = false;
this._keyboardActive = false;
}

get _rgb() {
Expand Down Expand Up @@ -463,10 +464,12 @@ class BaseColor extends LitElement {
_onPointerDown(e) {
this._lastPointerType = e.pointerType;
this._pickerInputEnabled = true;
this._keyboardActive = false;
}

_onPickerKeyDown() {
this._pickerInputEnabled = true;
this._keyboardActive = true;
}

_blurOnTouch(target) {
Expand All @@ -479,7 +482,7 @@ class BaseColor extends LitElement {
// --- Color area (Saturation/Brightness) ---

_snapColorAreaToOriginal(area, saturation, brightness) {
if (!this._hasOriginal) return { saturation, brightness };
if (!this._hasOriginal || this._keyboardActive) return { saturation, brightness };
const ds = Math.abs(saturation - this._originalSaturation);
const db = Math.abs(brightness - this._originalBrightness);
if (ds > ORIGINAL_COLOR_AREA_SNAP_PCT || db > ORIGINAL_COLOR_AREA_SNAP_PCT) {
Expand Down Expand Up @@ -524,7 +527,7 @@ class BaseColor extends LitElement {
if (slider.value == null) return;

let hue = slider.value;
if (this._hasOriginal) {
if (this._hasOriginal && !this._keyboardActive) {
const diff = Math.abs(hue - this._originalHue);
const wrappedDiff = Math.min(diff, 360 - diff);
if (wrappedDiff <= ORIGINAL_COLOR_HUE_SNAP_DEG) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -388,9 +388,10 @@ export class ColorWheelExpress extends ColorWheel {
this.getCanvasPosition();
this._dragIndex = index;

const markerV = this.swatches[index]?.hsv?.v != null
const rawV = this.swatches[index]?.hsv?.v != null
? Number(this.swatches[index].hsv.v)
: this.wheelBrightness;
const markerV = rawV > 0 ? rawV : this.wheelBrightness;

const moveHandler = (e) => {
this._dragFixedBrightness = markerV;
Expand Down Expand Up @@ -441,10 +442,10 @@ export class ColorWheelExpress extends ColorWheel {
this.paint();
}

if (this.swatches.length > 0 && active?.hsv != null) {
if (this.swatches.length > 0 && active?.hsv != null && this._dragIndex < 0) {
const activeV = Math.round(Number(active.hsv.v) ?? 100);
const v = Math.min(100, Math.max(0, activeV));
if (this.wheelBrightness !== v) {
if (v > 0 && this.wheelBrightness !== v) {
this.wheelBrightness = v;
this.generateColorWheel();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ export async function createActionMenuComponent(options = {}) {
transformPalette,
getName,
enableState = true,
daaLh = null,
} = options;

if (!TYPES.includes(type)) {
Expand Down Expand Up @@ -340,6 +341,7 @@ export async function createActionMenuComponent(options = {}) {
}

const container = createTag('div', { class: `action-menu-${type}` });
if (daaLh) container.setAttribute('daa-lh', daaLh);
const buttonRefs = {};
const sections = [];

Expand Down
Loading
Loading