Skip to content
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

New classNames API for Tailwind (and other CSS library) support #5451

Open
JedWatson opened this issue Oct 31, 2022 · 7 comments
Open

New classNames API for Tailwind (and other CSS library) support #5451

JedWatson opened this issue Oct 31, 2022 · 7 comments
Labels

Comments

@JedWatson
Copy link
Owner

We're working on a new feature/release that I thought was worth documenting the plan and rationale here for ahead of the PRs and releases coming for it. If you've got any feedback, please share below.

Goal 1: Tailwind Support

Tailwind (and other utility class frameworks) have gained a lot of momentum recently, and with increasing diversity of new front-end frameworks and build systems, it's less easy than it used to be to assume that CSS-in-JS / Emotion will "Just Work" for everyone. In particular, if you're building your own component library / design system with something like Tailwind and using React Select it's a fair bit of work to map design tokens and theme properly from CSS classes to React Select's theme context.

Wouldn't it be better if you could just style React Select with your own class names? that's the plan 😁

The new classNames API

Step one is adding a new classNames API. A small nod to a popular library, this will sit alongside the current styles prop, and let you provide (as the name suggests) class names instead of css property values for each Component in React Select, based on the same state argument provided to the styles functions.

So if you wanted a red border around your Select component on focus, where currently you could do this:

<Select styles={{
  control: (styles, { isFocused }) => ({ ...styles, borderColor: isFocused ? 'grey' : 'red' })
  }} />

Now you can apply class names to get the same effect:

<Select classNames={{
  control: ({ isFocused }) => isFocused ? 'border-red-600' : 'border-grey-300'
  }} />

ℹ️ Note: you won't have a good time using tailwind's native support for pseudo-states, because the browser doesn't think the Control component is focused when the input or menu are "focused" (internally we call this "pseudo-focus") so classes like focus:border-grey-300 won't work. This is why we're sticking with the (state) => string signature for the new prop

Goal 2: The new unstyled prop

Not necessarily in the same release (depends on how the implementation plays out) but we're also planning to introduce an unstyled prop which will remove all the presentation styles from React Select (leaving some important functional styles, like those for menu positioning and input width in multi select)

This will make it easier to completely specify your own styles or classNames to control the look of React Select, without having to specifically override the default theme we apply.

ℹ️ Note: removing the dependency on emotion for styles isn't specifically part of this same goal, although the two are related; the new unstyled prop is specifically only to make theming-from-scratch easier. We'll (probably) still be using emotion under the hood for applying functional styles.

Goal 3: Decouple from Emotion

This is a longer-term thing that we're going to experiment with, but will have to see how things play out – actually shipping it may require a rework of how the component is bundled, and how the entry points work, which would mean a new major. We'll see.

But theoretically there are a few wins here to be had:

  • Provide CSS as classNames to the base component, even when using Emotion to generate them
  • Export the functions used to style React Select with the default theme, so they can be extended or applied in with the classNames prop in user land, but using any css-in-js library
  • Move functional CSS (like menu positioning) to inline styles, and then provide an unstyled export with no dependency on css-in-js at all so consumers providing their own classNames don't have to bundle a copy of Emotion that they don't need

Long term we expect to continue using Emotion as the built-in "just works out of the box" solution for styling React Select, but it would be great to offer more flexibility and reduced bundle size for people who want to include their own solution. So, this is our current plan and roadmap for that.

Watch this issue for PRs that come in as we work through the backlog, and shout out if you have any other ideas for how we might go about improving this part of React Select!

@module17
Copy link

module17 commented Nov 1, 2022

This proposal sounds great and a welcomed addition. A "headless" export would be ideal for Tailwind users.

@tlouth19
Copy link

Very excited for this 🚀

@incammicia
Copy link

incammicia commented Nov 23, 2022

Great stuff, is there a timeline for this? The doc says it will be available from 5.7.0.

@rnike
Copy link

rnike commented Nov 30, 2022

I believe this is the pr #5487

@kevinbailey25
Copy link

Any status update on the decoupling from Emotion?

@volkandkaya
Copy link

Would be interested in how decoupling from Emotion is going as well.

@ClementChaumel
Copy link

Is there any update on this? I would be willing to work on it if needed (esp. the decoupling for emotion one)
Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

8 participants