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

Feat: Support responsive variants #5

Open
AbdallahAbis opened this issue Aug 29, 2022 · 12 comments
Open

Feat: Support responsive variants #5

AbdallahAbis opened this issue Aug 29, 2022 · 12 comments

Comments

@AbdallahAbis
Copy link

Would be great to support responsive variants, something like:

<ImageParentSkeletonComponent color='md:green lg:red' />

or

<ImageParentSkeletonComponent mdColor='green' lgColor='red' />
@AbdallahAbis AbdallahAbis changed the title Feat: Add responsive variants Feat: Support responsive variants Aug 29, 2022
@vinpac
Copy link
Owner

vinpac commented Sep 14, 2022

Interesting case. Let me think about it and come with a proposal later today

@AbdallahAbis
Copy link
Author

Sure, cause let's imagine you want a button's text to be flexible, sometimes you want it to be 2rem on mobile other times 1rem. There's no way to do that at the moment unless you pass conditional prop values using JavaScript.

@AbdallahAbis
Copy link
Author

@vinpac Any updates on this?

@vinpac
Copy link
Owner

vinpac commented Sep 22, 2022

Hey @AbdallahAbis . Still thinking about this. The idea behind windstitch is to provide a way to control when classnames are applied to a component based solely on variants. Adding breakpoints would create a new layer of consideration when applying a classname.

Maybe we can abstract that from the main package into its own package. Like:

import { responsive } from '@windstich/responsive'

const variant = responsive({
  xs: 0,
  sm: 480,
  md: 700,
  lg: 1000
})

const Button = w.button('', {
  variants: {
    color: responsive({
      green: 'bg-green-500',
      red: 'bg-red-500'
    })
  }
})

function Home () {
  return <>
     <Button color="green" />
     <Button color={{ xs: 'green', sm: 'green', lg: 'red' }} />
  </>
}

The responsive function could look like this:

function responsive<Breakpoints extends Record<string, number>>(breakpoints: Breakpoints) {
  return function variant<Variants extends Record<string, string>>(variants: Variants) {
    return (value: keyof Variants | Record<keyof Breakpoints, keyof Variants>) => {
      // ... calculate the classnames based on the current breakpoint
    }
  }
}

One challenge here would be to update the classname when window size changes. This would require some watcher running.

What do you think?

@AbdallahAbis
Copy link
Author

Looks great. is Windstitch responsible for calculating and generating styles? thought it only generates classNames and tailwind handles the rest?

@vinpac
Copy link
Owner

vinpac commented Sep 22, 2022

No no. Windstich is not responsible for calculating styles. It only applies classnames. The responsiveness on that would require a watcher.

That's my main concern because tailwind also handles responsive styles through their modifiers (e.g. md:bg-gray-500)

@AbdallahAbis
Copy link
Author

I thought that you get the variant classNames and just add the responsive modifier to them:

import { responsive } from '@windstich/responsive'

const variant = responsive({
  xs: 0,
  sm: 480,
  md: 700,
  lg: 1000
})

const Button = w.button('', {
  variants: {
    color: responsive({
      green: 'bg-green-500',
      red: 'bg-red-500'
    })
  }
})

function Home () {
  return <>
     <Button color="green" />
     <Button color={{ xs: 'green', sm: 'green', lg: 'red' }} />
  </>
}

the above will result in:

  <>
     <button className="bg-green-500" />
     <button className="bg-green-500 lg:bg-red-500" />
  </>

Windstitch doesn't have to add custom breakpoints, instead it will just generate classNames and tailwind generated breakpoints and styles will be used?

@vinpac
Copy link
Owner

vinpac commented Sep 22, 2022

Unfortunately that woudln't work as tailwind statically extracts classnames from our code, so a dynamic string doesn't generate any output css.

image

To support what you're mentioning we would have to do:

const variants = {
  green: { xs: 'bg-green-500', sm: 'sm:bg-green-500', lg: 'lg:bg-green-500' },
  red: { xs: 'bg-red-500', sm: 'sm:bg-red-500', lg: 'lg:bg-red-500' } 
 }

And let windstitch apply it.

@AbdallahAbis
Copy link
Author

Hmmm, I see.
And how is the user going to pass those responsive variants to a component?

@enyelsequeira
Copy link
Contributor

Hey @AbdallahAbis . Still thinking about this. The idea behind windstitch is to provide a way to control when classnames are applied to a component based solely on variants. Adding breakpoints would create a new layer of consideration when applying a classname.

Maybe we can abstract that from the main package into its own package. Like:

import { responsive } from '@windstich/responsive'

const variant = responsive({
  xs: 0,
  sm: 480,
  md: 700,
  lg: 1000
})

const Button = w.button('', {
  variants: {
    color: responsive({
      green: 'bg-green-500',
      red: 'bg-red-500'
    })
  }
})

function Home () {
  return <>
     <Button color="green" />
     <Button color={{ xs: 'green', sm: 'green', lg: 'red' }} />
  </>
}

The responsive function could look like this:

function responsive<Breakpoints extends Record<string, number>>(breakpoints: Breakpoints) {
  return function variant<Variants extends Record<string, string>>(variants: Variants) {
    return (value: keyof Variants | Record<keyof Breakpoints, keyof Variants>) => {
      // ... calculate the classnames based on the current breakpoint
    }
  }
}

One challenge here would be to update the classname when window size changes. This would require some watcher running.

What do you think?

Hey @vinpac is this the way to handle responsiveness? and is it added in the library already? I am also looking how it would work handling responsiveness

@vinpac
Copy link
Owner

vinpac commented Oct 20, 2022

Hey @enyelsequeira . This is still not added to the library. I will work on it as soon as possible. I was working on a conflicting classnames which have just being published as a Pull Request

@jpmaga
Copy link

jpmaga commented Feb 17, 2023

Hey there @vinpac, have you managed to get anywhere with this? We have an in-house solution very similar to windstitch, and we managed to get responsive variants using more or less the same you mentioned, using window.matchMedia and a watcher subsequently. Which works just fine on client-side, but it doesn't work so well when the page is rendered on the server, as expected. I would also prefer not to create responsive classes for every variant every time, if possible. So, I'm fresh out of ideas. :D

(we don't use tailwind often, though)

The dynamic variants, however, seem to work fine, haven't tested them much, but basically it uses css variables. if the prop is not an object it will use the style attribute to define it, otherwise it will add a style tag just above the component with the media query and the values. I don't see this being useful to windstitch, given it only cares for classnames but just throwing it out there, maybe you can make something with the idea.

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

No branches or pull requests

4 participants