smelte
smelte copied to clipboard
Why styling using calculated classes instead of plain css?
Hello,
The title says it: I wonder why using calculated (using utils/classes.js) classes to style components instead of using plain css as much as possible? With the current implementation it's nearly impossible to customize styling, because <Component>.classes will be overridden in the final component. That kills much of the css/tailwind benefits.
For instance, I use something like this in a internal project (using postcss-nesting):
@import 'tailwindcss/base.css';
@import 'tailwindcss/components.css';
@import 'tailwindcss/utilities.css';
@layer base {
button {
@apply text-white font-bold py-2 px-4 rounded inline-flex items-center bg-blue-500 hover:bg-blue-600 sm:text-lg;
}
a {
@apply inline-block align-baseline font-bold text-blue-500;
}
.form-control {
@apply mt-2;
span {
@apply flex border-2 rounded py-2 px-3 inset-y-0 items-center pl-2;
}
span.error {
@apply border-red-700;
}
label {
@apply text-sm font-bold mb-1;
}
/* No outline on text input controls */
input {
@apply outline-none bg-white text-gray-900;
}
/* for labels above the control, comment the class below like "form-control horizontal-label" */
.horizontal-label {
@apply inline-block align-middle;
}
.error {
@apply border-red-600;
}
.hint {
@apply text-sm;
}
.hint.error {
@apply text-red-700 mt-1;
}
}
}
If this gets implemented, we could not only override current theme, but implement whole new themes easily. Properties such as TextField.color, TextField.iconClasses, TextField.bgColor would be obsolete - they should just be only css.
Of course a component
I think the implementation will gets much easier as well, avoiding all that "classes math".
I am with you @howesteve. This has been my biggest difficulty in using this framework so far. It seems like every time I try to customize the color/size/placement of something leveraging Tailwind, I end up having the hardest time getting the changes implemented because the framework is quite strongly opinionated about the theme. It's a bummer because these are by far the best components of any Svelte UI framework..
I tried a few approaches trying to get rid of the "classes math", it hurts indeed. Do you guys want to get involved in this one?
I'd like to get involved, yes. My suggestion is implementing what they call in tailwind's site Extracting component classes with @apply:
<button class="btn-indigo">
Click me
</button>
<style>
.btn-indigo {
@apply py-2 px-4 bg-indigo-500 text-white font-semibold rounded-lg shadow-md hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-400 focus:ring-opacity-75;
}
</style>
That way, we would have the benefits of the component's logic while still being able to override classes in components components (and even introducing entirely new themes).
Smelte components should introduce semantic classes, not final visual formats. The actual visual classes formatting should be implemented on the css only. This is more similar to what Bulma does, but without crippling the full tailwind power. Ex:
<TextField label="Test label" hint="Test hint" persistentHint color="blue" outlined={false} />
should have a default css implementation and local class assignments/overrides tailwind style:
<TextField label="Test label" hint="Test hint" persistentHint classes="bg-blue-500 outline-none" />
Using this implementation, several properties would be deprecated: color, outline, noUnderline, etc.; the component should use just classes like (postcss nesting enabled below):
css
.form-control {
@apply mt-2;
&input {
/* ... */
}
span {
@apply flex border-2 rounded py-2 px-3 inset-y-0 items-center pl-2;
}
span.error {
@apply border-red-700;
}
.error {
@apply border-red-600;
&.hint {
@apply text-red-600;
}
}
We could use local component
I wouldn't mind a new major version breaking changes, but I don't know about others.
@howesteve Just trying to think through this, how would the changes you propose affect the ability to add Tailwind's in-line styling?
Obviously one advantage of Tailwind is not having to go inside a style tag and apply styles on class names I'm making up.
@patagoniapy actually that is the way tailwind was designed to work using @apply globally and classes locally. In the current implementation, classes will be overridden with calculates classes, so it's already hard to override formatting, specially hard coded classes. The idea here is to format using css only and leave classes as untouched as possible, so you have easier formatting, the full css power, and can pass whatever you like in the classes knowing they will be respected.
I think between that and having a default css implementation on each component that is easily overridable using local classes would be a big plus. Adding the stability that you know what you pass to the class will be respected will make the dev experience much smoother. My other question is how much of a breaking change do you think this would this be?
Sure. You can set css on any of these, and they are in order of precedence:
css file < component
As I said, I think the best solution is using a global css file since is a single place to see all css formatting instead of on multiple component files. Another advantage is some global styles will be avaiable.
So nothing keeps you from with local component
So if you don't like the default text color, just redefine it on the global theme css file, on a separate css file, on the component
Yeah I think that is great. Would you want to possibly do an example PR on one component? Then I'd be willing to help over the next few weeks to go through make the changes. Maybe we want to fork the repo and then create one big PR once it's finished?
Since this is just very unofficial, I'm posting an example right here. This is using a local
would become something like this:
<style lang="postcss">
.sm-appbar {
@apply fixed top-0 w-full items-center flex-wrap flex left-0 z-30 p-0 h-16 elevation-3 bg-primary-300 dark:bg-dark-600;
}
</style>
<header class='sm-appbar'>
<slot />
</header>
I'll let @matyunya weigh in on how he would like to proceed on this, if at all. From there, I'm more than willing to contribute.
This is how DataTable styles work at the moment, I think it is the right approach.
<TextField label="Test label" hint="Test hint" persistentHint color="blue" outlined={false} /> should have a default css implementation and local class assignments/overrides tailwind style: <TextField label="Test label" hint="Test hint" persistentHint classes="bg-blue-500 outline-none" />
I agree with this one as well. The original prop naming came from Vuetify which is of little use. This is going to be a breaking change and a pretty big rewrite. Maybe we could discuss this on Discord?
Ok we can discuss there.
Sounds great.
@patagoniapy feel invited to join us at discord while we are discussing this.
@howesteve Is there a link to the server you all are on? Thanks
https://discord.gg/32e2zU6
Won't let me in for some reason, get a screen saying the invite is invalid.
I got that link from the smelte site (https://smeltejs.com/components/) and it worked for me. Maybe @matyunya has an alternative link? Or just get into discord and look for the smelte" channel, we're there.
@howesteve @matyunya yeah still not able to join with that invite code and since on discord you have to have an invite to the particular server, I'm out of luck for now. Perhaps a new server invite would work from @matyunya ?
My bad! https://discord.gg/nZc64MMdkU