Closed jondot closed 4 months ago
but without all the forwardRef, and manually creating props etc
Interesting. Could you share an example for this? Wondering how this works.
Yea, it's actually exactly the button example from above:
export const Button = classed.button({
variants: {
v: {
primary:
'inline-flex justify-center items-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-primary-600 hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500',
secondary:
'inline-flex justify-center items-center px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500',
disabled:
'opacity-50 cursor-not-allowed inline-flex justify-center items-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-primary-600 hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500',
},
},
defaultVariants: {
v: 'secondary',
},
})
And this is how my shadcn/ui
based button looks like:
export const Button = classed.button(
'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 dark:hover:bg-slate-800 dark:hover:text-slate-100 disabled:opacity-50 dark:focus:ring-slate-400 disabled:pointer-events-none dark:focus:ring-offset-slate-900 data-[state=open]:bg-slate-100 dark:data-[state=open]:bg-slate-800',
{
variants: {
variant: {
filled:
'bg-primary-600 text-white hover:bg-primary-500 dark:bg-slate-50 dark:text-slate-900',
destructive:
'bg-red-500 text-white hover:bg-red-600 dark:hover:bg-red-600',
outline:
'shadow-sm bg-transparent text-slate-900 border border-slate-300 hover:bg-slate-100 dark:border-slate-700 dark:text-slate-100',
subtle:
'bg-slate-100 text-slate-900 hover:bg-slate-200 dark:bg-slate-700 dark:text-slate-100',
ghost:
'bg-transparent hover:bg-slate-100 dark:hover:bg-slate-800 dark:text-slate-100 dark:hover:text-slate-100 data-[state=open]:bg-transparent dark:data-[state=open]:bg-transparent',
link: 'bg-transparent dark:bg-transparent underline-offset-4 hover:underline text-slate-900 dark:text-slate-100 hover:bg-transparent dark:hover:bg-transparent',
},
size: {
default: 'h-10 py-2 px-4',
sm: 'h-9 px-2 rounded-md',
lg: 'h-11 px-8 rounded-md',
},
},
defaultVariants: {
variant: 'outline',
size: 'default',
},
}
)
export type ButtonProps = Classed.ComponentProps<typeof Button>
The author clearly built a cva
alternative, so the interface is very compatible. I just copy-paste the values from shadcn/ui
into a classed.button
and everything works.
The infrastructure is hidden under the classed
library, typing works because they use plenty of advanced Typescript inference mechanisms.
tw-classed looks pretty cool…
As far as I can see, it doesn’t support twMerge - how could this fit in?
tw-classed looks pretty cool…
As far as I can see, it doesn’t support twMerge - how could this fit in?
It does if you use
const classed = createClassed({ merger: twMerge });
@shadcn maybe a migration from cva
to tw-classed
would be beneficial sooner rather than later, because it will likely result in a large diff for all components since a lot of boilerplate can be eliminated. Is this something on your radar already, and if not, would you be open to a PR?
I've replaced cva with my own reducer function but am interested in tw-classed. But given tw-classed is bringing css-in-js into the tailwind paradigm, is there any concern with it playing well with react server components (I think emotion/styled-components don't play so well)? Or do we see in this scenario that tw-classed will only be used with interactive client side components anyway, so not an issue?
See https://github.com/reactwg/react-18/discussions/110 and https://dev.to/srmagura/why-were-breaking-up-wiht-css-in-js-4g9b
This is an older issue, but there is also https://react-twc.vercel.app/ (https://github.com/gregberge/twc) which is pretty similar
This issue has been automatically closed because it received no activity for a while. If you think it was closed by accident, please leave a comment. Thank you.
Hi, Great repo! I've been doing something similar, but not as extensive, and considering throwing away my stuff and adopting yours. Once thing I've been doing differently is using
tw-classed
, so a component looks like this:Which is very similar to the intent of your usage of
cva
but without all the forwardRef, and manually creating props etc. It could cut the code for this repo by at least 3x.Did you ever consider this?