Skip to content

Latest commit

 

History

History
159 lines (133 loc) · 5.03 KB

README.md

File metadata and controls

159 lines (133 loc) · 5.03 KB


Tailwind to Object
Tailwind for email rendering

npm version TypeScript Build status

Fast and simple zero-dependency library of a single-argument function that converts Tailwind classes of default configuration to style objects using pre-compiled key-value pairs of class names and corresponding styles. Perfect for email rendering! Can be used on front-end, back-end and your microwave if it supports JavaScript. Check list of supported classes (can take a while to load).

npm i tailwind-to-object
# Or
yarn add tailwind-to-object

API

tailwindToObject

Accepts a space-delimited string of Tailwind classes as the only argument and returns an object of camel-cased styles.

import tailwindToObject from 'tailwind-to-object';

const style = tailwindToObject(`
  text-2xl 
  font-bold 
  text-center 
  !px-3 
  text-red-200 
  bg-[#FFFFFF] 
  border-[5px] 
  -top-4
  w-[calc(100%_-_100px)]
  h-1/2
`);

console.log(style);
/*
{   
    // text-2xl
    fontSize: '1.5rem',
    lineHeight: '2rem',
    // font-bold
    fontWeight: '700',
    // text-center
    textAlign: 'center',
    // !px-3
    paddingLeft: '0.75rem !important', 
    paddingRight: '0.75rem !important',
    // text-red-200
    color: '#FECACA',
    // bg-[#FFFFFF] 
    background: '#FFFFFF',
    // border-[5px]
    borderWidth: '5px',
    // -top-4
    top: '-1rem',
    // w-[calc(100%_-_100px)]
    width: 'calc(100% - 100px)',
    // h-1/2
    height: '50%',
}
*/

Example usage with React

You can simulate the regular className property in your React component that is going to be converted and applied as a style object. Optionally, install tailwind-merge to avoid potential conflicts. Since the library is not related to any framework, you can create something with similar idea for your own environment. Feel free to create a PR to add more examples.

// tailwindComponents.ts
import { ComponentProps, createElement } from 'react';
import { twMerge } from 'tailwind-merge';
import tailwindToObject from 'tailwind-to-object';

// put your custom classes here
const classesToReplace = {
  'my-custom-class': 'text-[#FF0000] bg-white',
  // since the function doesn't use Tailwind config, you may want to define custom font sizes here
  'text-sm': 'text-[14px]', 
};

const replaceClasses = (classNames: string[]) => {
  const classesToBeApplied = [];

  for (const cls of classNames) {
    if (classesToReplace[cls as keyof typeof classesToReplace]) {
      classesToBeApplied.push(classesToReplace[cls as keyof typeof classesToReplace]);
    } else {
      classesToBeApplied.push(cls);
    }
  }

  return classesToBeApplied;
};

function createTag<T extends keyof JSX.IntrinsicElements>(tag: T) {
  const component = ({ className, style, ...rest }: ComponentProps<T>) => {
    const classNames = replaceClasses(className?.trim().split(/\s+/) ?? []);

    const tailwindStyle = classNames.length ? tailwindToObject(twMerge(...classNames)) : {};
    return createElement(tag, {
      style: { ...tailwindStyle, ...(style ?? {}) },
      ...rest,
    });
  };

  component.displayName = tag;

  return component;
}

export const Div = createTag('div');
export const Span = createTag('span');
export const Table = createTag('table');
export const Tbody = createTag('tbody');
export const Thead = createTag('thead');
export const Tr = createTag('tr');
export const Td = createTag('td');
export const Th = createTag('th');
export const Ul = createTag('ul');
export const Ol = createTag('ol');
export const Li = createTag('li');
export const P = createTag('p');
export const A = createTag('a');
export const Button = createTag('button');
export const Img = createTag('img');
export const H1 = createTag('h1');
export const H2 = createTag('h2');
export const H3 = createTag('h3');
export const H4 = createTag('h4');
export const H5 = createTag('h5');
export const H6 = createTag('h6');

export default createTag;

Now you can use the new components like that:

import { Div } from './tailwindComponents';
// ...
<Div className="mt-6 leading-6 font-semibold my-custom-class" style={{ ...someOtherStyles }}>
    Hello World
</Div>

Note that, by default, if Tailwind class is not supported, tailwindToObject is going to throw an error.