Skip to content

Releases: danpacho/tailwindest

v3.2.2

08 Jul 07:31
919d547

Choose a tag to compare

Bug Fixes 🐛

tools.rotary's compose method does not correctly handle merging behavior. It disappears original T/F property when return new instance using compose.

Now these compose tests are passed correctly.

it("should handle multiple compositions on ToggleStyler", () => {
    const toggle = tw.toggle({
        base: { color: "gray" },
        truthy: { color: "green" },
        falsy: { color: "red" },
    })

    const composed1 = toggle.compose({ backgroundColor: "white" })
    const composed2 = composed1.compose({ padding: "10px" })
    const composed3 = composed2.compose({
        color: "black",
    })

    expect(composed1.style(true)).toEqual({
        color: "green",
        backgroundColor: "white",
    })
    expect(composed2.style(false)).toEqual({
        color: "red",
        backgroundColor: "white",
        padding: "10px",
    })
    expect(composed3.style(true)).toEqual({
        color: "green",
        backgroundColor: "white",
        padding: "10px",
    })
})
  • 164 bug toggle styler compose method preserve issue @danpacho (#165)

Full Changelog: v3.2.1...v3.2.2

v3.2.1

25 Jun 13:17
d1cafe3

Choose a tag to compare

New Features

  • [bug + feature] override variants base when compose, add multiple class literal for class @danpacho (#163)

Bug Fixes

  • [bug + feature] override variants base when compose, add multiple class literal for class @danpacho (#163)

Overview

  • Fix rotary.compose function's base style overriding logic.

    const btn1 = tw.rotary({
        variants: { 
            warning: {...}
        },
        base: {
            fontSize: 'text-xs'
        },
    })
    
    const btn2 = btn.compose({
         fontSize: 'text-xl' // change base font size to xl
    })
    
    const res1 = btn1.class("warning") // text-xs ...
    const res2 = btn2.class("warning") // text-xl ...
  • Support add class method's multiple extra classes.

    const base = tw.style({...})
    
    const withExtra = base.class("c1", "c2", ["c3", "c4"], "c5") // ... c1 c2 c3 c4 c5
  • Support statically typed className strings for class method's extra classes.

      import type { Tailwind, TailwindNestGroups } from "~/tailwind.ts"
    
      export type Tailwindest = CreateTailwindest<{
           tailwind: Tailwind
           tailwindNestGroups: TailwindNestGroups
           useArbitrary: true
      }>
      export type TailwindLiteral = CreateTailwindLiteral<Tailwind>
    
      export const tw = createTools<{
           tailwindest: Tailwindest
           tailwindLiteral: TailwindLiteral
           useArbitrary: true  // enable arbitrary strings
           useTypedClassLiteral: true // ✅ enable typed class literal <-- [added]
      >()
    
    // now, extra classes arguments are fully typed.
    const box = tw.style({...}).class("bg-red-100") // ✅ <-- statically typed

Full Changelog: v3.2.0...v3.2.1

v3.2.0

21 Apr 07:55
f170b52

Choose a tag to compare

New Features 🚀

Bug Fixes 🐛

API Changes

createTools generic parameter

import {
    createTools,
    type CreateTailwindest,
    type CreateTailwindLiteral,
} from "tailwindest"

import type { Tailwind, TailwindNestGroups } from "./tailwind"

export type Tailwindest = CreateTailwindest<{
    tailwind: Tailwind
    tailwindNestGroups: TailwindNestGroups
    groupPrefix: "$" // prefix for nest groups, [optional]
    useArbitrary: true // enable arbitrary values, [optional]
}>
export type TailwindLiteral = CreateTailwindLiteral<Tailwind>

export const tw = createTools<{
    tailwindest: Tailwindest
    tailwindLiteral: TailwindLiteral
    useArbitrary: true // enable arbitrary values, [optional]
}>()

From 3.2.0, generic parameter should be passed explicitly like below.

{
    tailwindest: Tailwindest
    tailwindLiteral: TailwindLiteral
    useArbitrary: true // enable arbitrary values, [optional]
}

Full Changelog: v3.1.1...v3.2.0

v3.1.1

22 Mar 07:42
6e47111

Choose a tag to compare

Bug Fixes 🐛

  • [bug] twMerge does not match createtools - merger typing @danpacho (#151)

  • Change public merger interface for more generic approach.

    export type Merger<ClassList extends Array<any> = any[]> = (
        ...classList: ClassList
    ) => string
  • Change internal join, def logic. Remove duplicated merging process, fix invalid argument spreading.

  • Export public interface types for merging

    • TailwindestMerger : merger function shape
    • TailwindestClassList : default tailwindest's native merging target valid class lists.
  • Can inject custom merger, based on TailwindestMerger and TailwindestClassList.

    const merger_1: TailwindestMerger<TailwindestClassList> = (...values) => { ... }
    const merger_2: TailwindestMerger<Array<string> | string> = (...values) => { ... }
    ...

Full Changelog: v3.1.0...v3.1.1

v3.1.0 🚀

12 Mar 12:30

Choose a tag to compare

Introducing a new API for flexible and powerful styling.

tw.def(classList, ...styleList)

const condition: boolean = true;

const container = tw.def(

  // 🚀 Powered by clsx
  [
    "flex",
    "size-fit",
    "flex-col",
    "items-center",
    "justify-center",
    "gap-y-12",                        // ✅ Statically typed literals
    "md:flex-row md:gap-x-7",          // ✅ Arbitrary strings
    "lg:gap-x-24",
    condition ? "p-3" : "p-1",         // ✅ Conditional styling
    ["dark:text-white", "text-black"], // ✅ Array-based styling
  ],

  // 🚀 Default merging behavior
  {                                    // ✅ Record-based styling
    backgroundColor: "bg-white",
    dark: {
      backgroundColor: "dark:bg-black",
    },
  },
  {                                   // ✅ Support for infinite record styling
    // Additional styles here...
  }
);

Key Features:

  • Classname management with clsx-like functionality.
  • Infinite Tailwindest record styling for maximum flexibility.
  • Statically typed literals tailored for tailwindcss.
  • Returns a simple string for easy integration.

This API shines for foundational styling needs, offering a clean and intuitive way to build styles.

tw.join(...classList)

The join function now supports statically typed literals for tailwindcss, making it safer and more reliable. It also accepts any string, giving you the flexibility to pass custom strings while harnessing TypeScript’s type-checking power.

tw.mergeRecord(...recordList: Array<Style>)

  • Now supports infinite style records for merging.
  • Updated merging behavior: Instead of simply overriding by key (with arrays previously being concatenated), it now provides smarter, more predictable merging logic.

Note

This refined API suite offers developers a robust, type-safe, and flexible way to handle styling, blending the best of tailwindcss with TypeScript’s precision.

Here’s the polished version with your additional section about legacy code changes, integrated naturally into the documentation. I’ve refined the phrasing for clarity and professionalism while keeping the technical accuracy intact.

Legacy Code Updates Required

Warning

Please note that legacy code will need to be updated to align with these changes.

Before:

const tw = createTools<Tailwindest>();

After:

const tw = createTools<{
    tailwindest: TailwindCustom;
}>();

I appreciate your understanding as we transition to this improved structure, which provides better type safety and consistency moving forward.

New Features 🚀

  • [feature request] flexible way to define styles @danpacho (#146)

Breaking 🤯

  • [feature request] flexible way to define styles @danpacho (#146)

Full Changelog: v3.0.2...v3.1.0

v3.0.2

11 Mar 13:17

Choose a tag to compare

New Features 🚀

  • [feat] Add disable variants option at create tailwind type @danpacho (#142)

Bug Fixes 🐛

  • [bug] deepmerge nullable object transformation issue @danpacho (#145)
  • [bug] Remove native prefix for custom tailwind plugins @danpacho (#140)

Full Changelog: v3.0.1...v3.0.2

v3.0.1

28 Feb 10:00
023577f

Choose a tag to compare

Bug Fixes

Full Changelog: v3.0.0...v3.0.1

v3.0.0 🚀

25 Feb 06:41
f71c26b

Choose a tag to compare

v3 release

Today marks huge steps for tailwindest and TypeScript lovers.

As far as I know, there is a persistent demand for type safety in tailwindcss, and tailwindest focuses on solving that problem.

However, there have been requests to improve tailwindest for various reasons.

Thankfully, with these v3 updates, all users can now build a fully type-typed version of the tailwindcss product without any duck-typings and headaches.

1. create-tailwind-type

Now you can generate a complete TypeScript type definition for your own tailwind configuration with a single command.

create-tailwind-type-banner

npx create-tailwind-type

Previously, tailwindest provided pre-defined tailwindcss class name types by default. However, there were some major issues:

  1. Human Error: Because the number of tailwind class names is enormous, human error can occur.
  2. Customization Difficulty: The tailwindest type supports customization via individual fields, but it is somewhat verbose and can cause headaches.
  3. Maintenance: Correct and perfect tailwindcss types are needed; however, when minor features are added or some classes are removed, all types must be redefined.

For these reasons, v3 addresses these issues with create-tailwind-type.

It uses:

  1. The internal tailwind compiler
  2. postcss to analyze className properties

and finally generates an efficient type set by analyzing the entire className structure.

This allows you to generate your own version of a perfect tailwind type set.

Furthermore, excellent documentation is available. All the docs have been generated and analyzed through the work of @jbs-marcus, with the idea of static site data extraction. Thank you @jbs-marcus.

2. Tailwindest v3

tailwindest-banner

Tailwindest offers CSS-in-JS styling solutions with a pre-defined Tailwindest type.

From now on, tailwindest no longer provides any pre-defined type set; it only supplies the styling tool logic itself.

Before v3, we used the Tailwindest type set when creating tools like this:

import { createTools, type Tailwindest } from "tailwindest"

const tw = createTools<Tailwindest>()

Now, the type is entirely dependent on the user, meaning that you can customize everything generated by create-tailwind-type.

Migration Guidelines

  1. Create Tailwind Types

    First, you need to build your own types using a tailwind.css file that includes all your customization configurations.

npx create-tailwind-type -A # disable arbitrary values

Warning

Currently, the -A option should be passed.

This command generates type definitions for each custom configuration.

  1. Create Tools

    After step 1, you can use the generated types to create tools.

    import { createTools, type CreateTailwindest } from "tailwindest"
    import type { Tailwind, TailwindNestGroups } from "./tailwind" // Import generated tailwind types
    import { twMerge } from "tailwind-merge"
    
    export const tw = createTools<
        CreateTailwindest<{
            tailwind: Tailwind
            tailwindNestGroups: TailwindNestGroups
            groupPrefix: "$" // prefix for nest groups, [optional]
        }>
    >({
        merger: twMerge, // set tailwind-merge as merger, [optional]
    })

    Additionally, tools like twMerge, which serve as tailwind custom style order mergers, can be injected via configuration. Merging each style property correctly in tailwindcss can be challenging.

Added Features

  1. Additional Styling Arguments for .class() and .style()

    t.style({
         backgroundColor: "bg-red-100"
    }).class("bg-red-200 flex")
    
    // returns "bg-red-200 flex" if <tailwind-merge> is injected, or "bg-red-100 bg-red-200 flex" otherwise
    
    t.style({
         backgroundColor: "bg-red-100"
    }).style({
         backgroundColor: "bg-red-200"
    })
    
    // returns merged objects.

    All tools can now accept additional styling arguments for convenience.

  2. join is Added

    tw.join() is a wrapper for clsx, the well-known classname generation package.

    In issue #125, there was a request to simplify the library. The integration with clsx was chosen as the best option. However, strict type support for join is not available because it significantly slows down the TypeScript language server. If you need complete type support for the join function, please refer to tailwind-intellisense-regex-list.

    close #125

  3. merger Option Added to createTools

    From now on, createTools accepts an options argument for future purposes. The merger option is used to merge an array of className strings into a single string. For this purpose, tailwind-merge is a perfect fit. If the user wants to merge class names before generating the final output, simply inject the merger option. All classes will then be processed through the merger.

Breaking API Changes

There are two API changes:

  1. For createTools.style(stylesheet), the returned class and style are now functions.

    t.style(styles).class    // ❌
    t.style(styles).class()  // ✅
    
    t.style(styles).style    // ❌
    t.style(styles).style()  // ✅
  2. To create a Tailwindest type set, use CreateTailwindest.

    type Tailwindest = CreateTailwindest<{
            tailwind: Tailwind
            tailwindNestGroups: TailwindNestGroups
            groupPrefix: "$" // prefix for nest groups, [optional]
    }>

    The CreateTailwindest type accepts a generation configuration interface.

    interface TailwindestConfig {
        /**
         * Tailwind type
         */
        tailwind: any
        /**
         * Tailwind nest group literal type
         */
        tailwindNestGroups: string
        /**
         * Prefix of nest group
         * @default ''
         */
        groupPrefix?: string
        /**
         * Option to enable arbitrary strings
         *
         * If enabled, all `${string}` can be used as valid style property
         */
        useArbitrary?: true | false
    }

Legacy Supports

  • The Tailwindest type will still be provided for tailwindcss v3 users.

A huge thank you to everyone using Tailwindest! Happy coding 🚀

Full Changelog: v2.3.6...v3.0.0

v2.3.6 🔮

11 Sep 01:55
bbf3654

Choose a tag to compare

Bug Fixes 🐛

Full Changelog: v2.3.5...v2.3.6

v2.3.5 🔮

01 Sep 04:59

Choose a tag to compare

New Features 🚀

  • Refactor: add x, y direction for overflow property @danpacho (#117)

Add missing x, y directions for overflow property for adjust proper expected behavior of multiple overflow props

Because, tailwind allows us to write overflow classes like this.

<Box className="overflow-hidden overflow-x-auto overflow-y-scroll" />

Now, we can write it using tailwindest via new properties, overflowX and overflowY

const box = tw.style({
    overflow: "overflow-hidden",
    overflowX: "overflow-x-auto",
    overflowY: "overflow-y-scroll",
})

<Box className={box.class} />

Credits 🔮

Thank you @jbs-marcus!

Full Changelog: v2.3.4...v2.3.5