Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scoped preflight for gradual migration #134

Closed
holic opened this issue Mar 4, 2021 · 17 comments
Closed

Scoped preflight for gradual migration #134

holic opened this issue Mar 4, 2021 · 17 comments

Comments

@holic
Copy link

holic commented Mar 4, 2021

I'm adding twind to an existing React project with its own CSS (via emotion). I noticed that twind styles are well isolated to the components that use them, but once the component unmounts, some of the base styles (resets, I think) linger on the page.

Is there a recommended approach to cleanly removing these when the component is unmounted?

@holic
Copy link
Author

holic commented Mar 4, 2021

To clarify, I think I want to keep the preflight in place. I tried setup({ preflight: false }) and that had more side effects than I'd like. I don't mind if I have to fix up any side effects of using Twind with other things on the page, just want to ensure that Twind styles clean up as the components unmount.

@sastan
Copy link
Collaborator

sastan commented Mar 4, 2021

Why do you want them to be removed? They are in a style element. Your emotion styles are kept as well.

@holic
Copy link
Author

holic commented Mar 4, 2021

There's is some overlap between the twind base styles/resets and the existing styles on the page that I am trying to resolve. We're introducing twind incrementally, and the overlap in styles makes it hard to do so.

Maybe what I'm looking for is a virtual sheet that is mounted alongside each component that uses twind?

@holic
Copy link
Author

holic commented Mar 4, 2021

An example of a twind base style that gets injected when I'm using it with a component:
image

When that component is mounted on the page, anything of those elements with a margin get reset. So, for example, a set of plain <p> tags styled by Bootstrap will all lose their bottom margin.

I am okay with this problem/overlap existing when the component is mounted, but it remains when the component is unmounted.

@sastan
Copy link
Collaborator

sastan commented Mar 4, 2021

I see! Got you. The preflight causes issues. You want a scoped preflight. That may be difficult because the additional scope like .tw h1 increases the specificity and therefore overrules the utility classes. See this example

To solve that you must then increase the specificity of all Twind generated classes for example using the override variant. Here is an idea

Sadly Twind does not have a configurable way to increase the specificity for all generated classes.

@holic
Copy link
Author

holic commented Mar 4, 2021

Oh perfect, this might be exactly what I need. Will report back. Thank you for the quick help!

@holic
Copy link
Author

holic commented Mar 4, 2021

Oof, yeah, the specificity does not play nicely with other things. For example, all of react-select's default styles get reset when in a .tw container.

Any other ideas?

@sastan
Copy link
Collaborator

sastan commented Mar 4, 2021

No preflight – but a base style that is applied to all elements that are styled with Twind: Example

Or with hashed classes there is no need for a custom tw function: Example

@sastan
Copy link
Collaborator

sastan commented Mar 5, 2021

@holic Did the last comment help?

@holic
Copy link
Author

holic commented Mar 5, 2021 via email

@holic
Copy link
Author

holic commented Mar 8, 2021

Here's the issue I was seeing. With preflight disabled, some of the borders don't appear. If you remove preflight: false, you'll see the bottom border on the h1. Any idea what's going on here?

As far as I can tell from the Chrome inspector, these borders should appear - they aren't grayed out/struckthrough like I would expect if they were being overridden by other styles.

image

@holic
Copy link
Author

holic commented Mar 8, 2021

Ah, maybe it's the lack of this in the base style?
image
Specifically the missing solid without the preflight causes the border not to appear.

If I add border-solid without the preflight, it shows up but seems to override the border widths so the full border appears.

It's not until I add both border-solid and border-0 that it works as expected.

@sastan
Copy link
Collaborator

sastan commented Mar 8, 2021

Have you checked this comment: #134 (comment)

It is working there. Example

@sastan sastan changed the title Unmount base styles? Scoped preflight for gradual migration Mar 8, 2021
@sastan
Copy link
Collaborator

sastan commented Mar 8, 2021

BTW: I changed the title because we may be on to something here. That could evolve into an own module like twind/scoped

import { tw, setup } from 'twind/scoped'

@holic
Copy link
Author

holic commented Mar 8, 2021

Have you checked this comment: #134 (comment)

It is working there. Example

I did but Typescript was complaining about those spreads.

image

Even if I add // @ts-ignore here, I'm seeing ~the same results.

Here's a better reproduction of how I'm using twind and where it's not working.

Maybe it's because the borderBox key was losing its * selector? This seems to do the trick.


Edit: Nope, that's bad too, because then all downstream components get unset (e.g. a Bootstrap input field loses its border). Maybe we need all descendant selectors/classes to be prefixed with .tw too?

I might just live with the simple preflight: false for now and work around the border issue with border-solid border-0. I can't think of a great way to isolate the styles.

@sastan
Copy link
Collaborator

sastan commented Mar 8, 2021

I did but Typescript was complaining about those spreads.

You need to cast them:

import type { CSSRules } from 'twind'

setup({
  // Define base style for all Twind rules
  preflight: ({ html, body, '*,::before,::after': borderBox, }) => ({
    '.tw': {
      // Order is important
      ...(body as CSSRules),
      ...(html  as CSSRules),
      ...(borderBox  as CSSRules),
      margin: '0',
      padding: '0',
      '&::before,&::after': borderBox
    }
  }),
})

Maybe we need all descendant selectors/classes to be prefixed with .tw too?

Then we ran into specificity issues again. .tw button > .border-1

Maybe we should get the apply route you already started. Mixing different CSS frameworks is really tough.

I will stop looking for solutions. But if you need any help or have questions please reach out to me.

I would like to move this issue into discussions because I do not really see this as an issue with twind or something that could be solved by twind.

Would that be OK with you?

@holic
Copy link
Author

holic commented Mar 9, 2021

That seems reasonable! Thanks for all the help 🙏

@sastan sastan closed this as completed Mar 9, 2021
@tw-in-js tw-in-js locked and limited conversation to collaborators Mar 9, 2021

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants