Incredible fast template toolkit for making new or re-styling existing components with Tailwind CSS.

Last update: Jun 18, 2022

Stail

Incredible fast template toolkit for making new or re-styling existing components with Tailwind CSS.

Why it's needed?

First of all, I'm tired from CSS-in-JS libraries. They are powerful but slow. Why? Because they building/prefixing/recalculating everything in browser. For example, if you use template literals for your components in emotion it will make new AST -> CSS string -> style element change for every render with different output. Why? Because in your ${(props) => props.value} you can return anything starting from a number and ending by returning all new styled.

Why not just use Tailwind in classNames

Just look at this className:

<div
  onClick={onClick}
  className={`flex h-56 max-w-71 rounded-lg flex-col relative overflow-hidden flex-1 border border-[#2d34365a] bg-[#2d343653] cursor-pointer flex-basis-30 m-1 sm:h-64 sm:flex-basis-40 sm:m-2 lg:h-96 lg:flex-basis-60 lg:m-3 ${
    className || ''
  }`}
>
  {/** Card body */}
</div>

And this is not the biggest className line that I've ever seen.

Let's rewrite this into Stail:

const Card = stail.div`
  // Layout
  flex flex-col relative flex-1
  // Style
  rounded-lg border border-[#2d34365a] bg-[#2d343653]
  cursor-pointer overflow-hidden

  /**
   * Media
   * H      Basis             Margin   Addition
   */
  h-56      flex-basis-30     m-1      max-w-71
  sm:h-64   sm:flex-basis-40  sm:m-2
  lg:h-96   lg:flex-basis-60  lg:m-3
`

<Card onClick={onClick} className={className}>
{/** Card body */}
</Card>

As you can see it's much easier to read and write. Everything is on their place. Also with Tailwind CSS plugin for VS Code you can easily check what each item is representing in end CSS file

How to install

yarn add stail

Or

npm install --save stail

That's it. You don't need to configure TailwindCSS to use it with Stail. It will just work from the box.

What features Stail supports?

Comments

Stail supports single line columns like // My Comment so as multiline /* ... */

Props passing

const IconButton = stail.button`
  rounded-[50%] py-0 px-2 inline-flex mr-0 w-[fit-content] ${(props) =>
    props.active
      ? undefined
      : 'bg-transparent hover:bg-white/10 active:bg-white/25'}
`

Value passing

const EmptySection = stail.div`
  flex ${
    !isSafari && 'backdrop-blur'
  } // Can be used for platform specific things.
`

Dom element wrappers

Stail have shortcuts for all native browser element under stail.* name. So if you want to make some small component, you don't need to write everything.

const Wrapper = stail.div`flex flex-nowrap`

Restyle any component that supports className prop

const Select = stail(ReactSelect)`py-1 px-4 bg-white/50`

Filter props that passing to dom element or component

By default stail will not pass props that starts from $ sign to dom elements, so if you use components from stail.* or you create your own like stail("div") you are free to use props like $active without need to clear it

const Select = stail(ReactSelect, {
  displayName: 'UISelect', // For React DevTools
  shouldForwardProp(prop) => !['active', 'index'].includes(prop)
})`
  py-1 px-4
  ${({active}) => active ? 'bg-white/50' : 'bg-white/40'}
`

VS Code support using Tailwind CSS IntelliSense plugin

You can enable auto-complete and CSS on hover in your IDE by adding additional config to the settings.json file:

{
  // Stail auto-complete and highlight
  "tailwindCSS.experimental.classRegex": [
    [
      "stail\\.?\\(?\\s*[\\w]+\\s*\\)?`[^\\$`]*\\$\\{\\s*\\([^\\)]*\\)\\s*\\=\\>\\s*\\(?([^\\}]*)\\}",
      "'([^']*)'"
    ],
    "stail\\.?\\(?\\s*[\\w,]+\\s*\\)?`([^`]*)"
  ]
}

Overriding base component at render-time for native dom elements

const MySuperButton = stail.div`
  // ...some classes for your button
`

render(
  <MySuperButton as="a" href="#">
    Now I'm a link
  </MySuperButton>,
)

Integration with other CSS-in-JS libraries

Almost all React project nowadays have some CSS-in-JS library that people use, so sometimes it's a requirement to support components that were build using them.

Stail support wrapping any component that can accept className property, so result component of any CSS-in-JS library is supported.

For example with styled-components

import styled from 'styled-components'
import stail from 'stail'

const Buttom = styled.button`
  padding: 8px 16px;
  //...
`
const SmallButton = stail(Button)`
  !py-1 !px-2 // styled-components prepend className that comes from a props, so in case you're overriding styles use !important
`

That's it.

Some libraries provide utilities that provide more deep integration to stail. For example: emotion, linaria, goober, etc.

Emotion integration

Stail can be used alongside emotion by using @emotion/css package and css ability

import { css } from '@emotion/css'
import stail from 'stail'

const Wrapper = stail.div`
  flex flex-1 rounded

  // Let's disable tap highlight for this component
  ${css`
    -webkit-tap-highlight-color: transparent;
  `}
`

This makes it possible to add own CSS to your Stailed component.

Warning! Please don't use css from a @emotion/react package, because it's requires a lot of runtime that we don't want to integrate. Later we can create separate entry-point for this kind of integration.

Linaria

import { css } from '@linaria/core'
import stail from 'stail'

const Wrapper = stail.div`
  flex flex-1 rounded

  ${css`
    -webkit-tap-highlight-color: transparent;
  `}
`

The benefit of Linaria is that it's zero-runtime library, so it's much easier to bundle

Goober

import { css } from 'goober'
import stail from 'stail'

const Wrapper = stail.div`
  flex flex-1 rounded

  ${css`
    -webkit-tap-highlight-color: transparent;
  `}
`

Please be accurate, because Goober is not well maintained and it doesn't support comments in it.

Tailwind Plugins

Stail provides additional plugins for Tailwind which makes writing complex styles much easier.

Tailwind child plugin

This plugin make it possible to apply style for a direct child component. This can be useful when you are wrapping component

For example let's imagine the following css:

.wrapper {
  & > div {
    border-radius: 0;
    border-right: 1px solid rgba(0,0,0,0.1)
    &:last-child {
      border-right-width: 0;
    }
  }
}

This can be converted into: child-div:rounded-none child-div:border-r child-div:border-black/10 child-div:last:border-r-0

Or in stail

const Wrapper = stail.div`
child-div:rounded-none
child-div:border-r child-div:border-black/10
// Remove border from last element
child-div:last:border-r-0
`

Installation

In your tailwind.config.js file, please add this to your plugins array:

plugins: [
  //... other plugins
  require('stail/plugins').child(),
]

By default plugin enables support for a & > div(child-div:*), & > svg(child-svg:*), & >span(child-span:*) and wildcard selector & > *(child:*).

You can modify this list by adding tags field into plugin initialization:

plugins: [
  //... other plugins
  require('stail/plugins').child({
    tags: ['svg', 'div', 'span', 'a', 'button'],
  }),
]

GitHub

https://github.com/BoGeek/stail
You might also like...

This repository allows you to create a React template component folder. It optionally includes scss and css files

Generate-React-Components - grc grc let you generate react components in typescript in a folder you specify and it will include .tsx, .scss, .css file

Nov 26, 2021

Framework-agnostic CSS-in-JS with support for server-side rendering, browser prefixing, and minimum CSS generation

Aphrodite Framework-agnostic CSS-in-JS with support for server-side rendering, browser prefixing, and minimum CSS generation. Support for colocating y

Jun 19, 2022

Seamless mapping of class names to CSS modules inside of React components.

Seamless mapping of class names to CSS modules inside of React components.

React CSS Modules React CSS Modules implement automatic mapping of CSS modules. Every CSS class is assigned a local-scoped identifier with a global un

Jun 19, 2022

Style your React components with simplicity using css inside your comments.

Style your React components with simplicity using css inside your comments.

Oct 12, 2021

Vite plugin that emulates Scoped CSS for React components

vite-react-css Vite plugin that emulates Scoped CSS for React components (using generated class names) Compatible with SSR Automatic code-splitting Ho

Feb 7, 2022

A basic authentication template based on React v17.

A basic authentication template based on React v17.

React based authentication page template This is my starter template for Login, Register and Forgot Password using ReactJS with simple form validation

Jun 15, 2022

Avneesh's Portfolio Template Built With React

Avneesh's Portfolio Template Built With React

Welcome to a Portfolio Template 👋 This is Avneesh's portfolio, feel free to use it and contribute to it 🏠 Homepage ✨ Demo Using the template To use

Jun 9, 2022

Typograpy components for react and styled-components

Typograpy components for react and styled-components

styled-typography Typograpy components for react and styled-components styled-typography is a small set of components, using styled-components, to bet

May 1, 2022

Visual primitives for the component age. Use the best bits of ES6 and CSS to style your apps without stress 💅

Visual primitives for the component age. Use the best bits of ES6 and CSS to style your apps without stress 💅

Visual primitives for the component age. Use the best bits of ES6 and CSS to style your apps without stress 💅 Looking for v5? The master branch is un

Jun 27, 2022
Comments
  • 1. Optimize buildTemplate steps

    buildTemplate is too complex and has some actions that undoing steps was done few lines before. We should find much simpler way for removing comments and triming

    Reviewed by Arilas at 2021-10-21 10:09
  • 2. Docs

    Consider using https://docusaurus.io/ doc builder with algolio search.

    Should have:

    • [ ] Installation (with IDE setup)
    • [ ] Getting Started
    • [ ] Styling
    • [ ] Variants
    • [ ] API
    • [ ] FAQ
    • [ ] Tailwind Plugins
    • [ ] Integrations (emotion/styled-components/etc)
    • [ ] SSR
    • [ ] Advanced usage
    Reviewed by Arilas at 2021-10-29 06:49
  • 3. Variants API

    For most use-cases, people are using function interpolation to make it possible to design components based on props.

    This can be transformed into declarative API as Variants.

    What we should consider:

    • It should be possible to make some variants as required, without specifying the default value
    • It should be possible to make some variants optional and the developer should not write style for default value (e.g. type="flat" in the example doesn't have specified value)
    • It should work with boolean types (e.g. active: { true: 'classes', false: 'classes' } )
    • Should be easy to work with
    • Should support comments and Primitive Interpolations

    The possible ways to implement this can be:

    1. Options object:
    export interface ButtonProps {
      type?: 'rounded' | 'flat'
      variant?: 'filled' | 'outlined'
      // ...
    }
    export const Button = stail<ButtonProps>("button", {
      variants: {
        type: {
          rounded: 'rounded-full',
        },
        variant: {
          filled: 'bg-gray-400 text-white hover:bg-gray-300 active:bg-gray-200',
          outlined: 'bg-white border-gray-400 text-gray-400 hover:border-gray-300 active:border-gray-200'
        }
      },
      defaultProps: {
        type: 'rounded',
        variant: 'filled'
      }
    })`px-4 py-2 text-xl font-bold`
    
    <Button>Rounded filled</Button>
    <Button variant="outlined">Rounded outlined</Button>
    <Button type="flat" variant="outlined">Flat outlined</Button>
    
    1. Variant helper:
    export interface ButtonProps {
      type?: 'rounded' | 'flat'
      variant?: 'filled' | 'outlined'
      // ...
    }
    export const Button = stail.button<ButtonProps>`
    px-4 py-2 text-xl font-bold
    
    ${variant(
      "type",
      {
        rounded: 'rounded-full',
      },
      "rounded"
    )}
    
    ${variant(
      "variant",
      {
        filled: 'bg-gray-400 text-white hover:bg-gray-300 active:bg-gray-200',
        outlined: 'bg-white border-gray-400 text-gray-400 hover:border-gray-300 active:border-gray-200'
      },
      "filled"
    )}`
    
    <Button>Rounded filled</Button>
    <Button variant="outlined">Rounded outlined</Button>
    <Button type="flat" variant="outlined">Flat outlined</Button>
    

    As I can see the second option is more native and gives developers more freedom to design component

    Reviewed by Arilas at 2021-10-29 06:49
  • 4. Implement babel plugin

    Stail should have babel plugin, that will:

    1. remove comments and trim everything on build-time instead of runtime.
    2. add displayName in development environment
    Reviewed by Arilas at 2021-10-21 10:03
Whirlwind is a utility-first styling framework specifically designed for React Native. It is heavily inspired by Tachyons and Tailwind CSS and uses low-level building blocks for rapidly building custom designs.

React Native Whirlwind ??️ A utility-first CSS framework designed for React Native. Whirlwind is a utility-first CSS framework specifically designed f

May 6, 2022
Material-tailwind - An easy-to-use components library for Tailwind CSS and Material Design
Material-tailwind - An easy-to-use components library for Tailwind CSS and Material Design

Material-tailwind - An easy-to-use components library for Tailwind CSS and Material Design

Jun 20, 2022
Encapsulated styling for your javascript components with all the power of javascript and CSS combined.

Stilr Encapsulated styling for your javascript components with all the power of javascript and CSS combined. Unique class names (Content Hash Based) U

May 30, 2022
🎨 Aesthetic is an end-to-end multi-platform styling framework that offers a strict design system, robust atomic CSS-in-JS engine, a structural style sheet specification (SSS), a low-runtime solution, and much more!

Aesthetic Start using Aesthetic now! aestheticsuite.dev Aesthetic is an end-to-end, multi-platform styling and design suite, that offers the following

Jun 14, 2022
Starter template for NextJs with TypeScript. Supports Tailwind with CSS-Modules
Starter template for NextJs with TypeScript. Supports Tailwind with CSS-Modules

Starter template for NextJs with TypeScript. Supports Tailwind with CSS-Modules. Jest and @react/testing-library configured and ready to go. Also ESLint, Prettier, Husky, Commit-lint and Atomic Design for components.

Jun 9, 2022
Create tailwind css react components like styled components with classes name on multiple lines

Create Tailwind CSS React components like styled components with class names on multiple lines and conditional class rendering

Jun 21, 2022
Court.css - A naive CSS Utility framework based on JSX and css custom properties

court.css ?? A (work in progress) JSX-based, CSS utility framework with a predic

Mar 14, 2022
A toolchain for React component styling.

Radium yarn add radium # or npm install --save radium Radium is a set of tools to manage inline styles on React elements. It gives you powerful stylin

Jun 23, 2022
TailwindCSS plugin that helps styling radix state

TailwindCSS Radix TailwindCSS plugin that helps styling radix state. Installation yarn yarn add tailwindcss-radix npm npm i tailwindcss-radix Usage Yo

Jun 22, 2022
🏠 Airbnb website using React, Next.js and Tailwind CSS
🏠 Airbnb website using React, Next.js and Tailwind CSS

This example shows how to use Tailwind CSS (v2.2) with Next.js. It follows the steps outlined in the official Tailwind docs.

May 2, 2022