CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-tailwind-variants

First-class variant API for Tailwind CSS that enables developers to create reusable component styles with type-safe variants, slots support, and automatic conflict resolution

Pending
Overview
Eval results
Files

lite-mode.mddocs/

Lite Mode

Tailwind Variants Lite Mode provides a lightweight version of the library with reduced bundle size by excluding tailwind-merge integration. This mode is ideal for applications that prefer minimal dependencies or implement their own conflict resolution.

Import

import { tv, createTV, cn, cnBase, defaultConfig } from "tailwind-variants/lite";

For CommonJS:

const { tv, createTV, cn } = require("tailwind-variants/lite");

Core Functions

tv (Lite)

Lightweight version of the main tv function without tailwind-merge integration.

const tv: TVLite;

The lite tv function provides the same variant API as the full version but without automatic conflict resolution. All class names are concatenated without merging conflicting Tailwind classes.

createTV (Lite)

Creates a lite tv instance (no configuration needed since tailwind-merge is not available).

function createTV(): TVLite;

Returns: A lite tv function instance

cn (Lite)

Basic class name utility without tailwind-merge integration.

const cn: <T extends CnOptions>(...classes: T) => CnReturn;

Parameters:

  • ...classes - Variable number of class values

Returns: Concatenated class string or undefined

cnBase

Base class name utility (same as full version).

const cnBase: <T extends CnOptions>(...classes: T) => CnReturn;

cnAdapter

Internal adapter function used by lite mode for class name processing.

const cnAdapter: (...classnames: CnOptions) => (config?: any) => CnReturn;

Parameters:

  • ...classnames - Variable number of class values

Returns: Function that accepts optional config and returns processed class string

Note: This is primarily an internal function but available as a public export.

Usage Examples

Basic Component

import { tv } from "tailwind-variants/lite";

const button = tv({
  base: "font-medium rounded-lg px-4 py-2",
  variants: {
    color: {
      primary: "bg-blue-500 text-white hover:bg-blue-600",
      secondary: "bg-gray-500 text-white hover:bg-gray-600",
    },
    size: {
      sm: "px-3 py-1.5 text-sm",
      lg: "px-6 py-3 text-lg",
    },
  },
  defaultVariants: {
    color: "primary",
    size: "sm",
  },
});

// Usage
const primaryButton = button({ color: "primary", size: "lg" });
// Returns: "font-medium rounded-lg px-4 py-2 bg-blue-500 text-white hover:bg-blue-600 px-6 py-3 text-lg"

Slots Example

import { tv } from "tailwind-variants/lite";

const card = tv({
  slots: {
    base: "rounded-lg border shadow-sm bg-white",
    header: "px-6 py-4 border-b border-gray-200",
    body: "px-6 py-4",
    footer: "px-6 py-4 border-t border-gray-100 bg-gray-50",
  },
  variants: {
    padding: {
      none: {
        header: "px-0 py-0",
        body: "px-0 py-0",
        footer: "px-0 py-0",
      },
      sm: {
        header: "px-4 py-3",
        body: "px-4 py-3",
        footer: "px-4 py-3",
      },
    },
  },
});

const { base, header, body, footer } = card({ padding: "sm" });

Class Name Utility

import { cn } from "tailwind-variants/lite";

// Basic usage
const classes = cn(
  "px-4 py-2 rounded",
  isActive && "bg-blue-500 text-white",
  { "opacity-50": isDisabled }
);
// Returns concatenated classes without conflict resolution

Differences from Full Mode

No Conflict Resolution

The lite mode does not include tailwind-merge, so conflicting classes are not automatically resolved:

// Full mode with tailwind-merge
import { tv } from "tailwind-variants";
const fullButton = tv({ base: "px-4 px-6" }); // Resolves to "px-6"

// Lite mode
import { tv } from "tailwind-variants/lite";
const liteButton = tv({ base: "px-4 px-6" }); // Returns "px-4 px-6"

Smaller Bundle Size

By excluding tailwind-merge dependency, the lite mode significantly reduces bundle size:

  • Full mode: ~XX KB (with tailwind-merge)
  • Lite mode: ~XX KB (without tailwind-merge)

No Configuration

Since tailwind-merge is not available, configuration options related to it are ignored:

// This has no effect in lite mode
const button = tv({
  base: "px-4 py-2",
}, { twMerge: true, twMergeConfig: { /* config */ } });

Manual Conflict Resolution

When using lite mode, you need to handle class conflicts manually:

import { tv } from "tailwind-variants/lite";

// Manually avoid conflicts
const button = tv({
  base: "font-medium rounded-lg",
  variants: {
    size: {
      sm: "px-3 py-1.5 text-sm",      // Don't repeat px/py in base
      md: "px-4 py-2 text-base",      // Ensure no conflicts
      lg: "px-6 py-3 text-lg",
    },
  },
});

Type Definitions

interface TVLite {
  <V extends TVVariants<S, B>, CV extends TVCompoundVariants<V, S, B>, DV extends TVDefaultVariants<V, S>, B extends ClassValue = undefined, S extends TVSlots = undefined>(options: {
    base?: B;
    slots?: S;
    variants?: V;
    compoundVariants?: CV[];
    compoundSlots?: TVCompoundSlots<V, S, B>[];
    defaultVariants?: DV;
  }): TVReturnType<V, S, B>;
}

Best Practices

Avoid Class Conflicts

When using lite mode, structure your variants to avoid class conflicts:

// Good: No conflicting classes
const button = tv({
  base: "font-medium rounded-lg transition-colors",
  variants: {
    color: {
      primary: "bg-blue-500 text-white hover:bg-blue-600",
      secondary: "bg-gray-100 text-gray-900 hover:bg-gray-200",
    },
    size: {
      sm: "px-3 py-1.5 text-sm",
      md: "px-4 py-2 text-base",
    },
  },
});

// Avoid: Conflicting padding classes
const badButton = tv({
  base: "px-4 py-2 font-medium",
  variants: {
    size: {
      sm: "px-2 py-1 text-sm",  // Conflicts with base px-4 py-2
      lg: "px-6 py-3 text-lg",  // Conflicts with base px-4 py-2
    },
  },
});

Use Compound Variants for Complex Logic

const button = tv({
  base: "font-medium rounded-lg",
  variants: {
    color: {
      primary: "bg-blue-500 text-white",
      danger: "bg-red-500 text-white",
    },
    outline: {
      true: "bg-transparent border-2",
      false: "",
    },
  },
  compoundVariants: [
    {
      color: "primary",
      outline: true,
      class: "border-blue-500 text-blue-500 hover:bg-blue-50",
    },
    {
      color: "danger",
      outline: true,
      class: "border-red-500 text-red-500 hover:bg-red-50",
    },
  ],
});

Install with Tessl CLI

npx tessl i tessl/npm-tailwind-variants

docs

core-api.md

index.md

lite-mode.md

utilities.md

tile.json