Skip to content
Before dive in
Design goals

Design goals

1. Type-safety

Bringing a type system to Tailwind was the overarching goal of this project. Let's take a look at how you can benefit from type stability with tailwindest.

Get type definition of tailwind

Hover the TailwindClass

type TailwindClass = Tailwindest[keyof Tailwindest]

Infinite nest condition

typescript's recursive type computation allows you to write infinite Nested Break conditions.

Hover the "em"

const autocompleted = tw.style({
    "::after": {
        "::before": {
            "::file": {
                "::first-letter": {
                    "::first-line": {
                        "::marker": {
                            "::placeholder": {
                                "::selection": {
                                    ":active": {
                                        ":autofill": {
                                            backgroundColor: "em",
                                        },
                                    },
                                },
                            },
                        },
                    },
                },
            },
        },
    },
})

2. Readable

Design an intuitive, primitive, familiar API is essential process. Final conclusion is going back to the most primitive form, as if we were writing down pure CSS. And this led to the conclusion that the CSS in JS form is the best fit.

Most of the tailwindcss properties name is based on pure CSS properties, except tailwind's sole utility properties like mx-1.

const box = tw.style({
    display: "flex",
    flexDirection: "flex-row",
    alignItems: "items-center",
    justifyContent: "justify-center",
 
    gap: "gap-2",
 
    marginX: "mx-2",
})

Colocate nest conditions

In pure tailwind, you should write nest conditions like this.

const smConditions =
    "sm:flex sm:items-center sm:justify-center sm:p-2 sm:m-2 sm:border sm:rounded-sm"

As you can see, the sm: expression is repeated. But in tailwindest, you can colocate nest conditions in one object.

const easyToRead = tw.style({
    "@sm": {
        display: "sm:flex",
        alignItems: "sm:items-center",
        justifyContent: "sm:justify-center",
 
        padding: "sm:p-2",
        margin: "sm:m-2",
 
        borderWidth: "sm:border",
        borderRadius: "sm:rounded-sm",
    },
})

3. Reusable

tailwindest handles string. That means, we can reuse all the elements of function.

Reuse all elements

const box = tw.style({
    display: "flex",
    flexDirection: "flex-row",
    alignItems: "items-center",
    justifyContent: "justify-center",
    gap: "gap-2",
})
  1. classname: string

    get classname

    const boxClass = box.class
    // flex flex-row items-center justify-center gap-2
  2. styleSheet: object

    extract styleSheet

    const boxStyle = box.style
    /**
    {
        display: "flex",
        flexDirection: "flex-row",
        alignItems: "items-center",
        justifyContent: "justify-center",
        gap: "gap-2",
    }
    **/

classname and styleSheet are just string and object. So you can modifying it whatever you want.

It's time to dive 🏄

Now, you are ready to dive in. Let's get into it!