Hear Ye, Hear Ye! A Call for Aid in the Realm of Codecraft: The Tale of the Missing Styles
Tags: vite, npm, typescript, tailwindcss
Published: 2024-06-22 06:50:56

**For the plain English reader:** 

Hello everyone,

I'm working on creating an NPM package using Vite with React in library mode. I've configured Tailwind CSS in the package and added a few custom CSS classes. Everything seems to work fine when I run the project locally.

However, when I publish the NPM package and install it in a new project, I run into an issue. The styles defined in the tailwind.css file are applied correctly to the components. But the Tailwind classes used directly within my SpaceButton.tsx component are not working at all.

Here's what I've noticed:

Styles in tailwind.css: These styles are correctly applied when I use the component in a new project.
Tailwind classes in SpaceButton.tsx: These classes do not apply when the component is used in a new project.

_ALL THE RELEVANT FILES ARE AT THE BOTTOM OF THE ARTICLE_

**For the Adventurous:** 

Greetings, noble coders and artisans of the digital realm!

I come before thee with a tale most curious, a quest most perplexing, and a plea for wisdom from the wise and valiant of this great coding kingdom. In the grand halls of SpaceCode Studios, we embarked on a noble endeavor: to craft a wondrous NPM package using the mighty tools of Vite, React, and the enchanted mode of the library. With Tailwind CSS as our trusty steed, we adorned our creation with splendid styles and custom classes.

The Quest and the Conundrum
In the heart of our enchanted repository, the SpaceButton.tsx component was forged. Its beauty was unparalleled, its styles resplendent. Yet, lo and behold, when we released our creation into the wilds of the NPM registry and summoned it into a new project, a most confounding issue arose.

The styles meticulously woven into the tailwind.css file pulled through, gracing our component with their intended glory. But alas, the Tailwind styles embedded directly within the SpaceButton.tsx component itself did not manifest as they should. It was as if a dark spell had been cast, obscuring the Tailwind magic from taking hold.

The Plea for Wisdom
Oh noble and wise inhabitants of the coding realms, I beseech thee! What arcane knowledge am I lacking? What hidden rune or forgotten incantation must be invoked to vanquish this vexing issue?

Here lies the repository of our grand endeavor, a tome of knowledge open to all who dare to peruse its depths:

[SpaceCode Studios: spaceUI](https://github.com/SpaceCode-Studios/spaceUI)

The Mystery Unfolded
To offer clarity upon our plight, here is the essence of our conundrum:

Tailwind Configuration: The custom styles in tailwind.css are indeed summoned when the package is invoked in a new project.
Component Styles: The Tailwind classes within SpaceButton.tsx are lost to the ether, their magic not rendered in the final component.

A Call to Arms
If thou hast faced a similar foe and triumphed, or if thy wisdom shines brightly upon this dark mystery, we implore thee to share thy knowledge. What ancient scroll or modern trickery must we employ to ensure that our component’s styles remain steadfast?

May this call reach the far corners of the coding kingdoms, and may the combined wisdom of our peers bring forth a solution most elegant. We await thy counsel with bated breath and hopeful hearts.

In service to the code and the craft,

Jonker Koorts of SpaceCode Studios

**_Here are all the relevant files:_** 

1. SpaceButton.tsx

```
import React from "react";
import { cn } from "../utils";

type BackGroundColor = "SpaceBlack" | "SpaceOutline" | "SpaceBlue";

type SpaceButtonProps = {
  buttonText: string;
  className?: string;
  backgroundColor?: BackGroundColor;
};

export const SpaceButton: React.FC<SpaceButtonProps> = ({
  buttonText,
  className,
  backgroundColor,
}) => {
  return (
    <button className={cn(`px-5 py-3 rounded-md ${backgroundColor}`, className)}>
      {buttonText}
    </button>
  );
};
```

2. Main.ts 

```
import "./tailwind.css";
export { SpaceButton } from "./Button/SpaceButton";
```

3. utils.ts

```
import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}
```

4. tailwind.css

```
@tailwind base;
@tailwind components;
@tailwind utilities;

/* SpaceBlack - Colors */
.SpaceBlack {
    background-color: #474747;
    color: white;
}

.SpaceBlack:hover {
    background-color: #505050;
    color: white;
}

/* SpaceOutline - Colors */
.SpaceOutline {
    background-color: hsl(0 0% 100%);
    color: black;
    border-width: 1px;
}

.SpaceOutline:hover {
    background-color: hsl(0, 0%, 94%);
    color: black;
    border-width: 1px;
}

/* SpaceBlue - Color */
.SpaceBlue {
    background-color: #285AD6;
    color: white;
}

.SpaceBlue:hover {
    background-color: #3068f6;
    color: white;
}

/* Apply transitions */
.SpaceBlack,
.SpaceBlack:hover,
.SpaceOutline,
.SpaceOutline:hover,
.SpaceBlue,
.SpaceBlue:hover {
    transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
    transition-timing-function: cubic-bezier(.4,0,.2,1);
    transition-duration: 0.5s;
}
```

5. Package.json

```
{
  "name": "spacecodeui01",
  "version": "0.1.1",
  "type": "module",
  "files": [
    "dist"
  ],
  "main": "./dist/space-ui.umd.cjs",
  "module": "./dist/space-ui.js",
  "exports": {
    ".": {
      "import": "./dist/space-ui.js",
      "require": "./dist/space-ui.umd.cjs"
    },
    "./dist/style.css": "./dist/style.css"
  },
  "sideEffects": false,
  "scripts": {
    "dev": "vite",
    "prebuild": "rm -rf dist",
    "build": "tsc && vite build",
    "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
    "preview": "vite preview",
    "prepublish": "npm run build",
    "storybook": "storybook dev -p 6006",
    "build-storybook": "storybook build"
  },
  "dependencies": {
    "clsx": "^2.1.1",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "tailwind-merge": "^2.3.0",
    "vite-tsconfig-paths": "^4.3.2"
  },
  "devDependencies": {
    "@chromatic-com/storybook": "^1.5.0",
    "@storybook/addon-essentials": "^8.1.10",
    "@storybook/addon-interactions": "^8.1.10",
    "@storybook/addon-links": "^8.1.10",
    "@storybook/addon-onboarding": "^8.1.10",
    "@storybook/blocks": "^8.1.10",
    "@storybook/react": "^8.1.10",
    "@storybook/react-vite": "^8.1.10",
    "@storybook/test": "^8.1.10",
    "@types/node": "^20.14.6",
    "@types/react": "^18.2.55",
    "@types/react-dom": "^18.2.19",
    "@typescript-eslint/eslint-plugin": "^6.21.0",
    "@typescript-eslint/parser": "^6.21.0",
    "@vitejs/plugin-react": "^4.2.1",
    "autoprefixer": "^10.4.19",
    "eslint": "^8.56.0",
    "eslint-plugin-react-hooks": "^4.6.0",
    "eslint-plugin-react-refresh": "^0.4.5",
    "eslint-plugin-storybook": "^0.8.0",
    "postcss": "^8.4.38",
    "storybook": "^8.1.10",
    "tailwindcss": "^3.4.4",
    "typescript": "^5.2.2",
    "vite": "^5.1.0",
    "vite-plugin-dts": "^3.9.1"
  }
}
```

6. tailwind.config.ts

```
/** @type {import('tailwindcss').Config} */
export default {
  // important: true,
  content: [
    // reference the library only
    "./lib/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
};
```

7. tsconfig.json

```
{
  "compilerOptions": {
    "target": "ES2020",
    "useDefineForClassFields": true,
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "skipLibCheck": true,
    "paths": {
      "space-ui": ["./lib/main.ts"]
    },

    /* Bundler mode */
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",

    /* Linting */
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true
  },
  "include": ["src", "lib"],
  "references": [{ "path": "./tsconfig.node.json" }]
}
```

8. vite.config.ts 

```
import { defineConfig } from "vite";
import { resolve } from "path";
import react from "@vitejs/plugin-react";
import tsconfigPaths from "vite-tsconfig-paths";
import dts from "vite-plugin-dts";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react(), tsconfigPaths(), dts({ rollupTypes: true })],
  build: {
    // library entry and output settings
    lib: {
      entry: resolve(__dirname, "lib/main.ts"),
      name: "space-ui",
      fileName: "space-ui",
    },
    // bundler options
    // externalize react-related imports
    rollupOptions: {
      external: ["react", "react-dom", "react/jsx-runtime"],
      output: {
        globals: {
          react: "React",
          "react-dom": "ReactDOM",
          "react/jsx-runtime": "react/jsx-runtime",
        },
      },
    },
  },
});
```