In recent years, Tailwind CSS has gained immense popularity as a utility-first CSS framework for rapidly building custom user interfaces. This powerful tool simplifies the process of creating your own design system and is incredibly user-friendly.
In this article, we'll explore how we integrated Tailwind CSS (version 3.0) with Bit and discuss the challenges we faced along the way.
This article uses React as the example, but the same concepts apply to any other framework.
To learn how to customize the Tailwind CSS configurations for your components and apps, see this blog post
A component preview is an isolated rendering of a component. It's a great way to test your components in different contexts and variations, showcase them, and document them.
To provide your component previews with Tailwind support, set your env with the Tailwind transformer.
Run the following to install the Tailwind webpack transformer in your workspace:
Head over to your env's *.env.ts
file, implement the preview service, and add the Tailwind webpack transformer to it:
/* @filename: react-tailwind.env.ts */
// ...
import { Preview } from '@teambit/preview';
import { tailwindTransformer } from '@learnbit/styling.transformers.tailwind';
export class ReactTailwindEnv extends ReactEnv {
name = 'react-tailwind-env';
/* customize the component preview to include tailwind */
preview(): EnvHandler<Preview> {
return ReactPreview.from({
mounter: require.resolve('./preview/mounter'),
transformers: [
tailwindTransformer({}),
],
});
}
}
export default new ReactTailwindEnv();
See full example of a React env here.
If you don't plan to change the default Tailwind configurations, it is recommended to use Tailwind's CDN. To Inject the CDN into your component previews, set the Tailwind Webpack Transformer like so:
tailwindTransformer({
cdn: true
})
Using the CDN reduces the build time of your components, and simplifies the Tailwind configuration process as no further steps are required.
This step is only needed if you don't use Tailwind's CDN (see previous step)!
Tailwind requires a main file to be loaded in order to generate the CSS classes. Since each component preview is isolated, it needs to load the main file, as well.
Run the following to install the Tailwind config component which includes the main file:
Fork this component to change the default Tailwind configuration and main file.
Import the Tailwind main file into each of your component composition files.
For example, the following is a React component compositions file that loads the Tailwind main file:
/* @filename: menu.compositions.tsx */
import { Button } from './button';
/* load the tailwind main file */
import '@learnbit/styling.config.tailwind/globals.tailwind.css';
export const BasicButton = () => {
return <Button type="button">Hello World</Button>;
};
See a full example here.
We recommend adding the Tailwind CSS main file to your component templates, so that it will be included, by default, in the composition files of components generated from the template.
Run the following to start your workspace and see the Tailwind styles applied to your components' previews:
For example, the following is a single preview of a button component.
Click on the code tab to see the button.composition.tsx
composition file, which is loaded by the preview:
To bundle your React app components with Tailwind styles, set your app component's plugin file with the Tailwind transformer.
Install the the transformer into your workspace:
Set your app component's plugin file with the Tailwind transformer:
/* tailwind-demo.react-18-app.tsx */
const {
tailwindTransformer,
} = require('@learnbit/styling.transformers.tailwind');
/** @type {import("@teambit/react.apps.react-app-types").ReactAppType} */
module.exports.default = {
name: 'tailwind-demo',
entry: [require.resolve('./demo-app.app-root')],
webpackTransformers: [tailwindTransformer()],
};
Add the Tailwind main file to your app's root file. For example:
/* @filename: demo-app.app-root.tsx */
import { createRoot } from 'react-dom/client';
import { DemoApp } from './app';
import '@learnbit-react/tailwind.tailwind-config/globals.tailwind.css';
const container = document.getElementById('root');
const root = createRoot(container!);
root.render(<DemoApp />);
See full example here.
Run the following with your app's name, to run it locally:
For example:
The Tailwind webpack transformer does the following to add Tailwind CSS support to your components:
*.tsx
and *.jsx
files of components in the workspace./* @filename: tailwind-transformer.ts */
//...
import type { WebpackConfigMutator } from '@teambit/webpack';
import tailwindcss, { Config } from 'tailwindcss';
import { tailwindConfig } from '@learnbit/styling.transformers.tailwind';
export function tailwindTransformer({
cdn,
config,
}: TailwindTransformerOptions = {}) {
const usedConfig = config || tailwindConfig;
return (configMutator: WebpackConfigMutator) => {
configMutator.addPostCssPlugins([tailwindcss(usedConfig)]);
if (cdn) {
configMutator.addElementToHtmlTemplate({
parent: 'head',
position: 'append',
tag: 'script',
attributes: {
src: 'https://cdn.tailwindcss.com/',
},
});
configMutator.addElementToHtmlTemplate({
parent: 'head',
position: 'append',
tag: 'script',
content: `tailwind.config = ${JSON.stringify(usedConfig, null, 2)}`,
});
}
return configMutator;
};
}
Lastly, since the component previews and documentation are also rendered in the components' remote scopes, we decided to inject to the preview's HTML page, the Tailwind CDN, which scans the page and generates Tailwind classes accordingly, in runtime. That allows your teammates to play with your Tailwind components' styles, in their scope, without having to rebuild the components.
For example, the following uses the Tailwind CDN. Insert a Tailwind class to see it rendered live. For example, try to enter bg-blue-700
:
See the button component page to play with the playground embedded in the component's documentation.