Den Dribbles

Getting Started With React + TypeScript + Tailwind + Classnames In Minutes

July 25, 2020

In this morning quick start, we are going to bootstrap a create-react-app with Tailwind and see how you can get it all up and running quickly with some state-based styling using classnames.

Installation

First, we need to create the TypeScript React app with create-react-app.

Second, we will install the other packages required for today.

# Create the app
npx create-react-app hello-tailwind --template typescript
# Change into our new app
cd hello-tailwind
# Using Yarn
yarn add tailwindcss classnames @types/classnames

Updating package.json

This part took quick inspiration from Dave Ceddia’s post with a modern update.

Let’s update our scripts to have the following:

{
  "scripts": {
    "build:tailwind": "tailwindcss build src/index.css -o src/tailwind.output.css",
    "prestart": "npm run build:tailwind",
    "prebuild": "npm run build:tailwind"
  }
}

prestart and prebuild scripts will run before any start and build script that is run. We are telling it to build the index.css file and output it to src/tailwind.output.css.

Add Tailwind imports

Update src/index.css to look like the following:

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

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto",
    "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans",
    "Helvetica Neue", sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

code {
  font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
    monospace;
}

Then, we will need to update our index.tsx file to change the import from index.css to tailwind.output.css:

import React from "react"
import ReactDOM from "react-dom"
import "./tailwind.output.css"
import App from "./App"
import * as serviceWorker from "./serviceWorker"

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("root")
)

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister()

Now we are ready to run!

Playing around with App.tsx

Run yarn start to get our application up and running.

Once up, let’s update our App.tsx file to look like the following:

import React from "react"

function App() {
  return (
    <div className="bg-gray-200 flex items-center justify-center h-screen">
      <button
        className="p-3 rounded-sm bg-blue-500 hover:bg-blue-700"
        onClick={() => setToggle(!toggle)}
      >
        Toggle
      </button>
    </div>
  )
}

export default App

When we run the app, we should now get the following:

Base application

These classnames come from the Tailwind docs. The docs are very user friendly! Search for your CSS properties and apply them from there.

As an added bonus, if you are a VSCode user, check out their VSCode extension to help autocomplete classnames!

Updating the App.tsx file to work based on logic

We can now add logic in based on useState to toggle between different states.

Update App.tsx to show the following:

import React from "react"
// import cx from 'classnames';

function App() {
  const [toggle, setToggle] = React.useState<boolean>(false)
  console.log("toggle", toggle)

  const buttonClasses = toggle
    ? "bg-red-500 hover:bg-red-500"
    : "bg-blue-500 hover:bg-blue-500"
  return (
    <div className="bg-gray-200 flex items-center justify-center h-screen">
      <button
        className={`p-3 rounded-sm ${buttonClasses}`}
        onClick={() => setToggle(!toggle)}
      >
        Toggle
      </button>
    </div>
  )
}

export default App

Once we run the app now, if we click the button we will see the background change to red!

Toggled App state

Using classnames

For more complex logic, we can use the classnames package to help us define which classnames to apply.

import React from "react"
import cx from "classnames"

function App() {
  const [toggle, setToggle] = React.useState<boolean>(false)

  const buttonClasses = cx({
    "bg-blue-500 hover:bg-blue-700": !toggle,
    "bg-red-500 hover:bg-red-500": toggle,
  })
  return (
    <div className="bg-gray-200 flex items-center justify-center h-screen">
      <button
        className={`p-3 rounded-sm ${buttonClasses}`}
        onClick={() => setToggle(!toggle)}
      >
        Toggle
      </button>
    </div>
  )
}

export default App

While this example is trivial, it becomes important for when you are defining variants based on props. We could swap out toggle to be logic such as status === 'error', etc. to reflect different possibilities through our application.

Conclusion

This has been a quick morning coffee and blog post on getting up and running with Tailwind without getting into the nitty gritty details.

Tailwind has a great reputation and for good reason - I highly recommend using this playground to try out what else it does offer.

Resources and Further Reading

  1. VSCode extension
  2. Tailwind - Installation
  3. Tailwind - Flex
  4. Tailwind - Text Color
  5. Tailwind - Background Color
  6. Tailwind - Border Radius
  7. Tailwind - Padding
  8. Tailwind with CRA - Dave Ceddia
  9. Classnames - GitHub

Image credit: Mael BALLAND


Related Articles

December 09, 2020

See how you can dynamically create UIs based on React State using dynamic imports, Next.js 10 and React State

December 02, 2020

Have you ever wanted to build a UI Component Library with TypeScript and React? This blog post will take you through a straightforward set up that uses the bare minimum to get a working component library that you can re-use across your different React projects.

November 16, 2020

This post will go through a simple example of setting up simple authentication with a user and password to your Next.js website.

November 08, 2020

This blog post will explore the new internationalised routing in Next.js 10 and how you can use this to your advantage with react-intl for React.js

November 08, 2020

This blog post will explore the new Next.js Image component for an optimised image experience on the web.

November 06, 2020

See a roundup of my look into Vercel's new analytics feature that you can enable on a Vercel project and see how I used GTMetrix to help push some numbers.

November 05, 2020

Learn how to deploy the base Next.js 10 app with the Vercel CLI and/or the Vercel GitHub Integration

November 04, 2020

Learn how to export static HTML from a Nextjs 10 project to host

October 28, 2020

Updating my previous post on using Create React App with Snowpack for the latest versions and NPM 7

August 18, 2020

Look at how we can work around one of the Service Worker's biggest misunderstanding

A personal blog on all things of interest. Written by Dennis O'Keeffe, Follow me on Twitter