pixiebrix-extension icon indicating copy to clipboard operation
pixiebrix-extension copied to clipboard

Figure out ergonomics of CSS modules in ShadowDOM components

Open fregante opened this issue 1 year ago • 5 comments

From https://github.com/pixiebrix/pixiebrix-extension/pull/7666#issue-2141113671 by @twschiller

  • Figure out ergonomics of CSS modules in enhancements we add in ShadowDOM. loadAsUrl yields a CSS file that hasn't been mangled even if module.scss is in the name

I think we need to start considering components in shadow DOM as standalone:

  • move them to their own isolatedWidgets directory
  • build them separately in webpack as entry points

If I'm not mistaken, webpack can actually natively handle CSS injection in this case, but we'd have to give up mini-css-extract-plugin.

fregante avatar Feb 19 '24 06:02 fregante

Latest mention:

  • https://github.com/pixiebrix/pixiebrix-extension/pull/7937/files#r1526366404

fregante avatar Mar 15 '24 14:03 fregante

Reminder to consider with this issue and approach:

  • Some styles leak through the shadow DOM (e.g., root font size)
  • So, can't rely on REM in any page editions (and Bootstrap uses REM sizing)

twschiller avatar Mar 16 '24 13:03 twschiller

I pushed a PR to fix that so we don't have to consider it anymore.

As for the solution to this general issue:

  1. [x] expose a single "ShadowRoot" or "IsolatedModule" component that accepts stylesheets
  2. [ ] add src/isolatedModules folder
  3. [ ] ensure that every file in the folder exports <IsolatedModule><anything underneath/></IsolatedModule>
  4. [ ] maybe block ShadowRoot and attachShadow() usage outside the folder
  5. [x] add all of these modules to webpack
  6. [x] replace all .css?loadAsUrl usages with <IsolatedModule stylesheet="ThisModule.css"> (it should be one stylesheet and it should be self-contained, because shadow DOM components are self-contained)

Once this is done, components will be safely reusable anywhere, whether inline (e.g. in Storybook), in modals or in iframes (via wrapper file that calls render(<ThatIsolatedModule nonce={fromUrl}/>, document.querySelector('#abc'))).

Iframes may or may not be removed at that point, but we wouldn't need to worry about that.

fregante avatar Mar 17 '24 02:03 fregante

More info, may be useful: https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM#applying_styles_inside_the_shadow_dom

fregante avatar Mar 22 '24 04:03 fregante

Related improvements:

  • [x] ReactDOM.render replacement to attach widgets without having to first create a wrapper risk conflicts on that too; this can also automatically listen to onContextInvalidated
  • [x] Extend style reset to include ::selection, ::scrollbar, etc
    • https://github.com/pixiebrix/pixiebrix-extension/pull/7942
  • [ ] <FramedComponent> like this, but renders inside an iframe (follows content size, supports nested import()s)
    • possible thanks to https://github.com/pixiebrix/pixiebrix-extension/pull/7940
  • [ ] <Overlay> component that locks scrolling (uses useScrollLock)
    • some overlap with https://github.com/pixiebrix/pixiebrix-extension/issues/8028 https://github.com/pixiebrix/pixiebrix-extension/issues/3418
  • [ ] <Popover> component https://github.com/pixiebrix/pixiebrix-extension/issues/8029

fregante avatar Apr 03 '24 09:04 fregante