lukejacksonn / oceanwind

Compiles tailwind shorthand into css at runtime. Succeeded by Twind.
https://twind.dev
264 stars 12 forks source link

Consider exposing supported syntax and its variants #9

Open bebraw opened 3 years ago

bebraw commented 3 years ago

I use TypeScript to provide typing over Oceanwind in my current work. I provide a sx prop for components where you can provide Oceanwind classes within a string (could be an array of strings).

At the moment, the type for this is any and that makes sx a little dangerous to use. To improve DX, it would be better to allow only syntax that's supported by Oceanwind.

Would it be feasible to generate the syntax and its different permutations within a module so that it's possible to type systems to infer available options? I am currently using this kind of approach against the theme for type inference for more specific props than sx.

lukejacksonn commented 3 years ago

This kind of developer experience sounds great and I'd certainly like to help facilitate generating the syntax file. I don't know exactly what format you require it in but the grammar file that the switch statement was initially generated with will probably be of use here regardless:

https://gist.github.com/kitten/219ddda1db5df4ad42a05abf0f2738dd#file-grammar-js

In fact @kitten is the most likely person to know if this is doable or not and how far off we are already. Might be worth reaching out to him if you are interested.

kitten commented 3 years ago

I think the trickiest part is generating types that work with the theme file. I know for a fact that it will be possible once Template Literal types Land in TypeScript: https://github.com/microsoft/TypeScript/pull/40336

bebraw commented 3 years ago

To give you a better idea, what I'm looking to do is to replace sx at my Box component with a better type. It would be enough to enumerate all the possible classes and their combinations there.

In the current approach I infer a lot based on the theme and I believe a similar way could work for typing. In essence, if there was something like type OceanwindClasses = 'flex' | 'flex-grow' | ..., that would be perfect. That's likely a composite so maybe you get type Padding = 'p-2' | 'p-4' | ... for each main feature and then compose the bigger type out of these.

Of course where this gets interesting is with all the possible variants since we can have hover:, sm:, and other modifiers but maybe there's a cool way to pull that off in the type system.

I agree template literate types may help a lot here. In some way the problem is about mapping the class grammar to the TypeScript type system and if we can achieve that, I believe it's great for developer experience and for various use cases.

lukejacksonn commented 3 years ago

Humm, I see. Well generating a big long string of possible options certainly isn't impossible, an exhaustive list would be huge though. A good majority of unique grammars are mapped out in the module tests file but it doesn't go so far as to test every color variant on all directives that accept a color even. That would be a lot already, and then it has to account for cases that extend theme.

So my initial thoughts are it would need to be smarter than a big long list of types. Perhaps that is where Template Literal types come in. But honestly I'm not a typescript expert! Would still love to see something like this working. I believe most of what is required is actually here but piecing it altogether could take a while 😅

bebraw commented 3 years ago

@lukejacksonn Yeah, I see what you are saying. A big long list of exhaustive options would be too much. It definitely looks like a grammar is needed for tackling this.

Does Tailwind have an explicit grammar or is it all implicit and within their PostCSS plugin definition?

Maybe it's good to revisit this issue when TypeScript gains improvements on this department.

kitten commented 3 years ago

@bebraw we already have a full grammar of Tailwind since part of the transformer to CSS was auto generated originally.

This could also generate the full things which isn't an issue at all (it also doesn't matter if they get big if it's generated)

However part of the theme and grammar is really dynamic depending on the theme.

bebraw commented 3 years ago

we already have a full grammar of Tailwind since part of the transformer to CSS was auto generated originally.

Ah, cool. Do you have the generator code somewhere public?

However part of the theme and grammar is really dynamic depending on the theme.

That's true. I was thinking maybe I could try to use your generator to generate some kind of type(s) while taking that into account. 😎

kitten commented 3 years ago

@bebraw certainly! The original code is here: https://gist.github.com/kitten/219ddda1db5df4ad42a05abf0f2738dd

bebraw commented 3 years ago

Awesome, thanks a lot.

bebraw commented 3 years ago

Now that TypeScript 4.1 is out, people are starting to type Tailwind. Example: https://twitter.com/markdalgleish/status/1329639099498577921 . Demo.

kitten commented 3 years ago

Agreed that it's the perfect time to trial this ✌️