fix: keep contain-layout on outer container to preserve node borders

Moving contain-layout contain-style from the outer container to the
inner wrapper caused Chromium to treat the inner wrapper as a new
stacking context, painting it over the Root Border Overlay and hiding
node borders. Keep containment on the outer container alongside
isolation: isolate.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
dante01yoon
2026-03-17 12:56:40 +09:00
parent 461c71670b
commit de08700fa0
12 changed files with 8 additions and 14 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 KiB

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 KiB

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 KiB

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 KiB

After

Width:  |  Height:  |  Size: 108 KiB

View File

@@ -252,25 +252,19 @@ describe('LGraphNode', () => {
expect(wrapper.element.style.getPropertyValue('--node-height-x')).toBe('')
})
it('should isolate stacking context on outer container and apply containment only to inner wrapper', () => {
it('should isolate stacking context on outer container to prevent text bleed-through', () => {
const wrapper = mountLGraphNode({ nodeData: mockNodeData })
const outerClasses = wrapper.classes()
const innerWrapper = wrapper.find('[data-testid="node-inner-wrapper"]')
const innerClasses = innerWrapper.classes()
// Outer container must have isolation: isolate to prevent text
// from lower z-index nodes bleeding through (see #9988).
expect(outerClasses).toContain('isolate')
// CSS containment must NOT be on the outer container because it
// interferes with inter-node stacking compositing.
expect(outerClasses).not.toContain('contain-layout')
expect(outerClasses).not.toContain('contain-style')
// CSS containment belongs on the inner wrapper for performance
// without affecting stacking between sibling nodes.
expect(innerClasses).toContain('contain-layout')
expect(innerClasses).toContain('contain-style')
// CSS containment stays on outer container alongside isolate.
// Moving it to the inner wrapper causes the inner wrapper's
// stacking context to paint over the Root Border Overlay.
expect(outerClasses).toContain('contain-layout')
expect(outerClasses).toContain('contain-style')
})
})

View File

@@ -11,7 +11,7 @@
:class="
cn(
'group/node lg-node absolute isolate text-sm',
'flex min-w-(--min-node-width) flex-col',
'flex min-w-(--min-node-width) flex-col contain-layout contain-style',
cursorClass,
isSelected && 'outline-node-component-outline',
executing && 'outline-node-stroke-executing',
@@ -75,7 +75,7 @@
:class="
cn(
'flex flex-1 flex-col border border-solid border-transparent bg-node-component-header-surface',
'min-h-(--node-height) w-(--node-width) min-w-(--min-node-width) contain-layout contain-style',
'min-h-(--node-height) w-(--node-width) min-w-(--min-node-width)',
shapeClass,
hasAnyError && 'ring-4 ring-destructive-background',
{