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>
|
Before Width: | Height: | Size: 90 KiB After Width: | Height: | Size: 90 KiB |
|
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 113 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 108 KiB |
|
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 107 KiB |
|
Before Width: | Height: | Size: 138 KiB After Width: | Height: | Size: 138 KiB |
|
Before Width: | Height: | Size: 140 KiB After Width: | Height: | Size: 140 KiB |
|
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 108 KiB |
@@ -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')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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',
|
||||
{
|
||||
|
||||