Skip to content

Commit d01af47

Browse files
committed
fix(painter-dom): custom hover wins on locked SDTs under chrome:'none' (SD-3322)
The custom hover background was overridden for LOCKED controls under chrome:'none'. The base lock-hover rules (a built-in tint on inline, transparent on block) have equal specificity to the plain custom hover rules but come later in source order, so they won; the chrome-none lock-hover reset only reset z-index, not background. Re-assert the custom hover background in that reset block - it carries the extra .superdoc-cc-chrome-none class, so it outranks the base lock-hover rules. A locked control now follows --sd-content-controls-custom-*-hover-bg. With no custom var set the default is empty, so the built-in lock-hover tint no longer leaks under chrome:'none' for locked controls (consistently empty). Only the contract-templates demo has locked chrome-none controls, and it wants the custom hover, not the tint. Add a regression test asserting the custom hover vars are re-asserted after the base lock-hover rules (source order = it wins). painter-dom 1179/1179 green.
1 parent ba1f849 commit d01af47

2 files changed

Lines changed: 37 additions & 4 deletions

File tree

packages/layout-engine/painters/dom/src/styles.test.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,30 @@ describe('ensureSdtContainerStyles', () => {
352352
'border-left: var(--sd-content-controls-custom-block-border-left, var(--sd-content-controls-custom-block-border, 0 solid transparent));',
353353
);
354354
});
355+
356+
it('locked-hover under chrome-none follows the custom hover background, not the built-in lock-hover (SD-3322)', () => {
357+
ensureSdtContainerStyles(document);
358+
const styleEl = document.querySelector('[data-superdoc-sdt-container-styles="true"]');
359+
const cssText = styleEl?.textContent ?? '';
360+
361+
// The base lock-hover rules (built-in tint on inline, transparent on block)
362+
// come first and have equal specificity to the plain custom hover rules, so
363+
// they would otherwise win for locked controls.
364+
const baseInlineLockHover = cssText.indexOf('background-color: var(--sd-content-controls-lock-hover-bg');
365+
const baseBlockLockHover = cssText.indexOf(
366+
'.superdoc-structured-content-block[data-lock-mode].sdt-group-hover:not(.ProseMirror-selectednode) {',
367+
);
368+
expect(baseInlineLockHover).toBeGreaterThan(-1);
369+
expect(baseBlockLockHover).toBeGreaterThan(-1);
370+
371+
// The chrome-none lock-hover reset re-asserts the custom hover background
372+
// AFTER them (extra .superdoc-cc-chrome-none class + later source order wins),
373+
// so a locked control under chrome:'none' uses the custom variable.
374+
const customInlineHoverReassert = cssText.lastIndexOf('--sd-content-controls-custom-inline-hover-bg');
375+
const customBlockHoverReassert = cssText.lastIndexOf('--sd-content-controls-custom-block-hover-bg');
376+
expect(customInlineHoverReassert).toBeGreaterThan(baseInlineLockHover);
377+
expect(customBlockHoverReassert).toBeGreaterThan(baseBlockLockHover);
378+
});
355379
});
356380

357381
describe('ensureTrackChangeStyles', () => {

packages/layout-engine/painters/dom/src/styles.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -885,11 +885,20 @@ const SDT_CONTAINER_STYLES = `
885885
border: none;
886886
}
887887
888-
/* Reset the lock-hover z-index boost so a suppressed SDT does not stack
889-
* above host-attached custom UI. Mirrors the base lock-hover selectors with
890-
* the chrome-none prefix so specificity stays above the boost rule. */
891-
.superdoc-cc-chrome-none .superdoc-structured-content-block[data-lock-mode].sdt-group-hover:not(.ProseMirror-selectednode),
888+
/* Chrome opt-out for the lock-hover affordance. The base lock-hover rules above
889+
* paint a built-in tint and boost z-index on hovered locked controls; under
890+
* chrome:'none' that would override the custom hover background and stack above
891+
* host-attached UI. Re-assert the custom hover background (so a locked control
892+
* follows --sd-content-controls-custom-*-hover-bg, defaulting to empty - no tint
893+
* leaks) and reset the z-index. Mirrors the base lock-hover selectors with the
894+
* chrome-none prefix, so the extra class wins over the base rules. Split inline
895+
* vs block because each reads its own hover variable. */
892896
.superdoc-cc-chrome-none .superdoc-structured-content-inline[data-lock-mode]:hover:not(.ProseMirror-selectednode, [data-appearance='hidden']) {
897+
background: var(--sd-content-controls-custom-inline-hover-bg, var(--sd-content-controls-custom-inline-bg, none));
898+
z-index: auto;
899+
}
900+
.superdoc-cc-chrome-none .superdoc-structured-content-block[data-lock-mode].sdt-group-hover:not(.ProseMirror-selectednode) {
901+
background: var(--sd-content-controls-custom-block-hover-bg, var(--sd-content-controls-custom-block-bg, none));
893902
z-index: auto;
894903
}
895904

0 commit comments

Comments
 (0)