Rosebox is a CSS-in-Typescript library that provides features like strong types, typed functions (e.g.,
linearGradient), additional expressive shorthand properties(e.g.,
paddingX, an object-based syntax for the values of complex properties (e.g.,
animation), and support for high-quality IntelliSense.
It maps CSS's data-types into Typescript. Some of these data-types are mapped directly to TS's intrinsic types like
number, while others are mapped to RB's custom-types, like
Length. It has been designed and developed with a focus on typo-reduction, better auto-completion, expressive API, and ease of data manipulation.
If you've done any development in React, then you've more likely than not used style-objects that have type React.CSSProperties. Let's put
React.CSSProperties (v17.0.1) to a type-checking test:
As you can see, the only type-error caught by the type system in the case of
React.CSSProperties is the one related to
flexDirection, but all the other properties pass the type-checking. Why? because all of them, except for
flexDirection has the type
string; the most permissive type in the universe.
With Rosebox, on the other hand, the type system catches the type-errors for all the properties. It's able to do so because properties in Rosebox are as fine-grained as they can be. They only get the
string type as the last resort.
Here's a version of
styleRB that would pass:
All unit-based types are implemented as generic types that take a type parameter specifying the type's unit. For example,
Length<'em'>. This comes in handy when you're exposing an API, and you want to clearly state the unit of the value you're expecting. Consider the following naive react-component:
Now, if we try to pass a
Duration<'s'> we will get an error:
Type 'Duration<"s">' is not assignable to type 'Duration<"ms">'
Of course, we don't always want to enforce a certain unit of
Duration or any other unit-based type for that matter; in that case, we just omit the type parameter (e.g
Neat, right? But that's only one way in which RB provides an expressive API. Another one is providing an object-interface for some complex properties like animation.
When manipulating colors, we usually need to convert them to string values before using them in our styles. Here's an example:
In RB, using
@rosebox/colors, you're just dealing with RB-types and returning RB-types, so you don't need that extra serialization step which is handled internally: