Comments (12)
There are several ways to solve this:
- use
!
as modifier (docs)
<Button className="bg-red-600!">red</Button>
Maybe this should be more prominent in the docs.... ๐
- Use a dedicated property
function Button({ bgColor = "blue-600", className, children }) {
return (
<button className={tw`border text-white bg-${bgColor} ${className}`}>{children}</button>
);
}
<Button>blue</Button>
<Button bgColor="red-600">red</Button>
One remark on performance: Try to use the template literal syntax as it allows to cache the static parts (tw
will ignore falsey values):
function Button({ className = "", children }) {
return (
<button className={tw`border text-white bg-blue-600 ${className}`}>{children}</button>
);
}
PS: We are working on a styled component like API: #7 . Maybe you have thoughts or some input there as well.
from twind.
I'm closing this for now. But feel free to re-open if needed...
from twind.
It's declarative, clearly defined in the rendered markup, and it works exactly as it should as far as I can tell. I think this is great!
from twind.
Nice, I'm not against that at all!
from twind.
We are planing to add a best practices guide. These kind of questions are very important to use. Thank you.
Your demo could be written like this for optimal performance (only meant for future reference):
using inline plugins: Demo
import { tw } from 'https://cdn.skypack.dev/twind'
const shared = ({ tw }) => tw`h-40 border(2 red-100)`
// const shared = tw`h-40 border(2 red-100)`
const topClassName = tw`${shared} bg-red-400`
const bottomClassName = tw`${shared} bg-purple-400`
document.body.innerHTML = `
<div class="${topClassName}">
should be red
</div>
<div class="${bottomClassName}">
should be purple
</div>
`
using base style with !
overrides: Demo
import { tw } from 'https://cdn.skypack.dev/twind'
const baseClassName = tw`h-40 border(2 red-100) bg-red-400`
const bottomClassName = tw`${baseClassName} bg-purple-400!`
document.body.innerHTML = `
<div class="${baseClassName}">
should be red
</div>
<div class="${bottomClassName}">
should be purple
</div>
`
Please let us know what to think, if you have any more questions or improvements (API, docs) you like to see.
from twind.
Hi all,
twind authors- Brilliant work! ๐
As for overlapping classes..this is a problem I also often encounter when creating sharable React components using Tailwind. I think it's a very common scenario to want to provide default classes that are easily overridable at an instance level. It seems like the Tailwind docs encourage component abstractions, but at the same time, you canโt pass text-blue-500
to a component that has a competing text color class already defined (as an example). You would expect the last-defined className to win, but this is not usually the case.
For myself, custom props to define styles are not an ideal solution. I think !
is an okay solution from the userโs perspective, but it requires the use of important!
, which is probably best reserved for more dire situations.
I would love to see the compiler handle smart merging of competing classes as a first-class feature. I realize that this is not easy and there are lots of considerations like how to handle variants and similiar directives. But, it would be really nice not to have to think about it!
A (possibly bad) idea that came to mind:
A custom default
variant.
- More declarative
- Possibly easier to parse?
// Reusable Button Component
const Button = ({children, className, ...rest}) => {
const mergedClassNames = tw`default:text-blue-500 text-xl ${props.className}`;
// or tw`text(default:blue-500 xl) ${props.className}`;
return (
<button className={mergedClassNames} {...rest}>
{children}
</button>
)
}
// Using the Button
const App = () => (
<Button className={tw`text-purple-500`}>Purple Wins</Button>
)
from twind.
Thanks for the detailed description.
I don't know if we can ever support default
or resolving of overlapping classes. The problem is that text-*
is not only for color
but used for a lot of different styles. This would mean that the parser or translator needs to have deep knowledge about what CSS styles a plugin generates for a directive and de-duplicates those based on the CSS properties in the resulting CSS object.
Additionally this would introduce another presedence dimension: the order directives are written.
We have two user-land solutions for this kind of problem:
- Use
!
as modifier - Use a dedicated property
color
property
I can understand why you would like an integrated solution for this.
Please investigate further and keep use informed about your findings.
from twind.
Thanks for the response. Iโve tried to implement something similar in the past so I definitely understand the challenges. My thought was that the use of the default
variant could help in narrowing down the type of competing class names (text-blue-500
vs text-xl
for example). But, even then, you would need to generate all the available options on the fly or keep a list in memory.
Either way, I appreciate the consideration and all the work youโve put into this awesome project!
from twind.
After a good night sleep i had an idea: an override
variant (name to be discussed) - this variant would increase the selector specificity on rules it is applied to.
tw`text-blue-500`
// => .text-blue-500 { ... }
tw`override:text-purple-500`
// => .override\:text-purple-500.override\:text-purple-500 { ... }
This could be used like this:
const Button = ({ children, className, ...props }) => {
const mergedClassNames = tw`text-blue-500 text-xl override:(${props.className})`
return (
<button className={mergedClassNames} {...props}>
{children}
</button>
)
}
const App = () => (
<Button className="text-purple-500 text-2xl">Purple and 2xl win</Button>
)
@mfolnovic @gojutin Would that help?
from twind.
This can already be implements in user-land:
setup({
variants: {
':override': '&&',
},
})
const Button = ({ children, className, ...props }) => {
const mergedClassNames = tw`text(blue-500 xl) override:(${props.className})`
return (
<button className={mergedClassNames} {...props}>
{children}
</button>
)
}
const App = () => (
<Button className="text(purple-500 2xl)">Purple and 2xl win</Button>
)
I'm open to to integrate this into twind. But we should maybe come up with a better name.
@lukejacksonn What do you think?
from twind.
I concur. Simple, elegant solution that requires no changes to core, love it!
from twind.
@lukejacksonn I just have updated the styled PR and found that this override
variant might be useful there as well. We should think about adding this to the core.
from twind.
Related Issues (20)
- [Feature]: flex-shrink-* is deprecated HOT 1
- missing data HOT 1
- How to use tailwindcss plugins? HOT 3
- Is there a way to make tailwind-scrollbar plugin to work with twind? HOT 3
- [Bug]: keyframes added with injectGlobal only contain the last keyframe HOT 2
- [Bug]: Classes added with injectGlobal can't reference each other with @apply HOT 2
- [Bug]: Classes added with injectGlobal can't be used with variants HOT 2
- [Feature]: allow peer dep of typescript v5 HOT 2
- [Bug]: max-w-{number} does not work
- defineConfig / setup mixed up[Docs]:
- Template literals like className={tw`bg-green-${c}`}
- How to style host and slot elements with Lit HOT 2
- [Docs]: twind.dev is out of date and still seems active HOT 1
- [Feature]: support vars in square brackts
- [Bug]: How to extend theme in Tailwind v3.4 HOT 2
- Browser version doesn't work (non-ES module version) HOT 7
- Applying classes on Lit element CSS block HOT 1
- [Bug]: withTwind doesn't play nicely with Light DOM Lit elements
- [Bug]: Lit & Dark Mode not usable with "class" mode HOT 1
- [Bug]: Update typescript version to 5.x.x HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. ๐๐๐
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google โค๏ธ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from twind.