Library hover preview breaks components that use container queries

Problem

ComponentPreview.tsx wraps the preview in a shrink-to-fit wrapper:

#component-wrapper { display: inline-block; min-width: 120px; }

This breaks container queries in two ways:

  • Container components (container-type: inline-size) ignore their content when their width is calculated, so the wrapper collapses to its 120px minimum.
  • Components that query an ancestor container find no container in the preview, so their @container rules never match.

Either way, the preview shows the mobile layout instead of the real one.

Steps to reproduce

  1. Create an SDC whose root has container-type: inline-size and which switches to two columns at @container (min-width: 768px).
  2. Hover over it in the Library.
  3. Expected: a scaled-down two-column layout. Actual: one narrow column, about 120px wide.

Proposed resolution

A container-query component has no intrinsic width, so the preview has to pick one. In ComponentPreview.tsx, before measuring (on iframe load, and again after <canvas-island> hydration):

  1. Detect whether the component uses container queries:
    • an element in #component-wrapper has a computed containerType other than normal, or
    • a CSSContainerRule in the iframe's stylesheets contains a style rule whose selector matches an element in #component-wrapper. Skip stylesheets that throw on cssRules (cross-origin). For rules nested inside a style rule, use the parent rule's selector.
  2. If so, set the wrapper to display: block; container-type: inline-size; so it takes the full iframe width (COMPONENT_PREVIEW_IFRAME_WIDTH) and acts as the query container. Otherwise leave it as is.
  3. Measure and scale as usual.

Only matching rules count, so unrelated @container rules in a theme's global CSS don't affect other components. Small components such as buttons keep their compact shrink-to-fit preview.

Workaround (that I'm currently using)

A theme can append preview-only CSS via hook_js_settings_alter() → drupalSettings.canvas.globalAssets.css:

#component-wrapper:has(.my-container-component) {
  display: block;
  container-type: inline-size;
}

This depends on the internal #component-wrapper ID, and the list of components has to be maintained by hand.

Edited by Fons Vandamme