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
@containerrules never match.
Either way, the preview shows the mobile layout instead of the real one.
Steps to reproduce
- Create an SDC whose root has
container-type: inline-sizeand which switches to two columns at@container (min-width: 768px). - Hover over it in the Library.
- 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):
- Detect whether the component uses container queries:
- an element in
#component-wrapperhas a computedcontainerTypeother thannormal, or - a
CSSContainerRulein the iframe's stylesheets contains a style rule whose selector matches an element in#component-wrapper. Skip stylesheets that throw oncssRules(cross-origin). For rules nested inside a style rule, use the parent rule's selector.
- an element in
- 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. - 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.