garronej / tss-react

✨ Dynamic CSS-in-TS solution, based on Emotion
https://tss-react.dev
MIT License
659 stars 37 forks source link

Using with Shadowed Web Components #202

Open christopherjbaker opened 11 months ago

christopherjbaker commented 11 months ago

When working with Web Components in Shadow mode, it is very common to define :host styles. They could be put in a GlobalStyles, but because these are about styling the component itself, rather than say the html/body, putting them in a GlobalStyles call breaks the usability of the tss-react pattern. These are not global styles in the idea of the term, but they do need to be treated as global when injected.

Would it be possible for global-ish styles (technically created as globals, but conceptualized and used as local) to still be used in the local structure? This could be implemented as a specific exception to the :host keyword. It could also be implemented as a wrapper that is removed at runtime (such as :global(:host); this would have the added benefit of being usable with other elements that might want this behaviour. Either would work for me.

An example from my project:

I need to use css something like this:

:host {
  width: 1920px;
  height: 1080px;
}

.inner {
  width: "100%",
  height: "100%",
  background: url(image.png) center/contain no-repeat,
}

However, when putting it into makeStyles like this:

const [useStyles, HostStyles] = makeStyles<{
  variant: CometProps["variant"]
}>((theme, { variant }) => ({
  ":host": {
    width: `${variants[variant].width}px`,
    height: `${variants[variant].height}px`,
    ...theme.shadow,
  },
  inner: {
    width: "100%",
    height: "100%",
    background: `url(${variants[variant].image}) center/contain no-repeat`,
  },
}))

A prefix is still added to the :host key, resulting in something like .comet-1wpixln-Comet-:host as the "class name", which is obviously not valid. I need that entry in the style object to stay as :host without anything added to it.

garronej commented 11 months ago

Hi @christopherjbaker,

I would need a more precise example of the desired behaviour. I'm having trouble understanding the use-case. Thanks

christopherjbaker commented 11 months ago

Sorry, I got pulled into other things. I updated the question a bit and added more details. Does that help?

garronej commented 11 months ago

I think what you are describing could be implemented as a simple plugin.

It's not documented but the modern API of tss-react implements a plugin system.

Main usecase is to implement global theme overwrite when tss-react is used with MUI.

The plugin system is only available with the modern API though but the modern API is mutch better than the makeStyles API in every regards.

The way the plugin system work is by letting you provide a usePlugin hook to createTss.
https://github.com/garronej/tss-react/blob/f7566d381a33bbccef347eefac9955232dc8ed85/src/mui/mui.ts#L16

You can see the MUI plugin implementation here:
https://github.com/garronej/tss-react/blob/main/src/mui/themeStyleOverridesPlugin.ts

You could intercept the :host rules and apply them in the reader if not already applied.