Tailwind CSS tutorial for graph visualization

Our article on how to build a React graph visualization app using Styled Components is one of our most popular developer guides. In this tutorial, we’ll show you another way to customize your ReGraph app, using version 4 of Tailwind.

What is Tailwind CSS?

Tailwind CSS is a utility-first CSS framework for creating highly-customized user interfaces fast.

Relying on utility classes makes it easier to apply design elements consistently and build responsive designs – there’s no need for masses of CSS. It also comes with sensible off-the-shelf style defaults to get started quickly, but you’ll want to take advantage of the many customization options.

Why use Tailwind CSS with ReGraph?

Developers choose ReGraph because it’s the best toolkit for building high-performance graph visualizations to add to their React applications.

The ability to customize every element, interface, interaction and workflow means they can create the exact design their users want. There’s also a live-coding playground to try out design ideas and share them with teammates.

This approach sits well with Tailwind CSS users. They too benefit from fast prototyping, virtually limitless customization options, and attractive color schemes for beautiful, eye-catching interfaces.

I’ll walk you through the best way to use Tailwind CSS and ReGraph to create something special.

About the insurance fraud dataset

For our Tailwind CSS tutorial we’ll use an extract from a fictitious vehicle insurance claim dataset. To see the full insurance fraud investigation in action, read Designing simple visual models that empower & delight users.

An insurance fraud visualization showing links between policies, policy holder details, insurance claims, vehicle damage, doctors, witnesses and mechanics
The full insurance fraud dataset investigates links between policies, policy holder details, insurance claims, vehicle damage, doctors, witnesses and mechanics

Our data connects nodes representing mechanics with the repairs they carried out on damaged vehicles. Some damage – like that caused by rear-end collisions – is far more common, but you’d also expect a range of repairs across different vehicles.

If a mechanic claims they fixed an unusually high number of issues affecting one specific vehicle part, it could be a sign of claim inflation. This is a big problem in the automotive insurance industry: policyholders conspire with fraudulent mechanics to claim for more damage than actually occurred. We’ll visualize our dataset and see what insights we can uncover.

Our data model lists how many times each mechanic fixed a specific vehicle part:

[
  { "mechanic": "Aufderhar LLC", "type": "Driver's Front Door", "count": 6 },
  ...
  { "mechanic": "Fraser's", "type": "Driver's Rear Door", "count": 14 },
  ...
  { "mechanic": "Thiel's Auto", "type": "Wing Mirror", "count": 4 }
]

We’ll save the data as src/data.json ready to import later.

FREE: Start your ReGraph trial today

Visualize your data! Request full access to our ReGraph SDK, demos and live-coding playground.

TRY REGRAPH

Get started with ReGraph

Let’s create an empty React application using Vite. You can follow the Getting Started Guide in our documentation or follow the steps below.

npm create vite@latest regraph-and-tailwind -- --react
cd regraph-and-tailwind

We include the latest version of ReGraph, downloaded from the ReGraph SDK site:

cp ~/Downloads/regraph-[version].tgz .
npm install file:regraph-[version].tgz

With ReGraph installed, we can create our first simple visualization of the data. We define a function to convert the data from the data.json file into ReGraph links and nodes. We also define two functions – styleNode and styleLink – to create ReGraph node and link objects respectively.

The link widths will scale according to the number of times a mechanic billed for repairs to a particular vehicle part.

Replace the contents of file src/App.jsx with:

import { Chart } from "regraph";
import data from "./data.json";

function styleNode(text, type) {
  const label = [
    {
      text,
      position: "s",
    },
  ];

  return { label };
}

function styleLink(id1, id2, count) {
  const width = count * 0.4;
  return { id1, id2, width };
}

function convertData() {
  const items = {};
  data.forEach((entry) => {
    const { mechanic, type, count } = entry;
    if (!(mechanic in items)) {
      items[mechanic] = styleNode(mechanic);
    }
    if (!(type in items)) {
      items[type] = styleNode(type);
    }
    items[`${mechanic}-${type}`] = styleLink(mechanic, type, count);
  });
  return items;
}

export default function App() {
  return (
    <div style={{ height: "100vh", width: "100vw" }}>
      <Chart items={convertData(data)} />
    </div>
  );
}

We’ve done enough already to create our first basic graph visualization:

A ReGraph visualization of a basic vehicle insurance fraud dataset ready for styling
The vehicle insurance fraud data ready for styling

Even from this basic view, we can see from the wider links how some mechanics carried out more repairs to certain vehicle parts compared to others. That’s a useful start.

Adding Tailwind CSS to the app

Next we install Tailwind CSS to the app by following the steps in the excellent Tailwind CSS documentation.

First, we install Tailwind and its Vite plugin. In the terminal, we’ll run:

npm install tailwindcss @tailwindcss/vite

Then we’ll update the Vite config vite.config.ts so it uses our newly installed plugin. After the edits, your config should look like this:

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import tailwindcss from "@tailwindcss/vite";

// https://vite.dev/config/
export default defineConfig({
  plugins: [react(), tailwindcss()],
});

As a final step, we will import Tailwind into our index.css at the top:

@import "tailwindcss";

Finally, to restart our app to redisplay our basic insurance fraud visualization, run:

npm run dev

Accessing Tailwind colors from our application

With Tailwind added to our application, we can now access its default theme variables from our code.

To do this, we can use the getComputedStyle browser API to get the value of a theme variable on the document root. For example, to get the red-50 color, we can do:

getComputedStyle(document.documentElement).getPropertyValue(
  "--color-red-50"
)

Now, as modern Tailwind uses the OKLCH color space, we need to convert those color values to either RGB or hex format, which are the formats supported by ReGraph.

To do so, we can use any JavaScript color conversion library. In this guide, we’ll use Culori, so let’s install it. In the terminal run:

npm install culori

To import it for use, import the formatRgb method in our App.jsx:

import { formatRgb } from "culori";

With Culori installed and imported, we can use its formatRgb method to convert our OKLCH color returned by the getComputedStyle function.

With that in mind, let’s create an object that will store all the imported Tailwind values that we want to use in our application. At the top of our App.jsx, under the import statements, add the following colors object:

const colors = {
  "emerald-500": formatRgb(
    getComputedStyle(document.documentElement).getPropertyValue(
      "--color-emerald-500"
    )
  ),
  "blue-500": formatRgb(
    getComputedStyle(document.documentElement).getPropertyValue(
      "--color-blue-500"
    )
  ),
  "gray-700": formatRgb(
    getComputedStyle(document.documentElement).getPropertyValue(
      "--color-gray-700"
    )
  ),
  "gray-300": formatRgb(
    getComputedStyle(document.documentElement).getPropertyValue(
      "--color-gray-300"
    )
  ),
  "gray-50": formatRgb(
    getComputedStyle(document.documentElement).getPropertyValue(
      "--color-gray-50"
    )
  ),
  "yellow-500": formatRgb(
    getComputedStyle(document.documentElement).getPropertyValue(
      "--color-yellow-500"
    )
  ),
  "red-500": formatRgb(
    getComputedStyle(document.documentElement).getPropertyValue(
      "--color-red-500"
    )
  ),
  white: formatRgb(
    getComputedStyle(document.documentElement).getPropertyValue("--color-white")
  ),
  transparent: "rgba(0,0,0,0)",
};

Next we update our styleNode function. We add a new parameter type to it to control the node colors:

  • emerald-500 for mechanics
  • blue-500 for damage types

We update the labels to use gray-700 for the text against a transparent background.

function styleNode(text, type) {
  const color =
    type === "mechanic" ? colors["emerald-500"] : colors["blue-500"];

  const label = [
    {
      text,
      color: colors["gray-700"],
      backgroundColor: colors.transparent,
      position: "s",
    },
  ];

  return { color, label };
}

Update the convertData function for the two call sites of styleNode to pass in the correct node type (mechanic or damage):

function convertData() {
  const items = {};
  data.forEach((entry) => {
    const { mechanic, type, count } = entry;
    if (!(mechanic in items)) {
      items[mechanic] = styleNode(mechanic, "mechanic");
    }
    if (!(type in items)) {
      items[type] = styleNode(type, "damage");
    }
    items[`${mechanic}-${type}`] = styleLink(mechanic, type, count);
  });
  return items;
}

We also update the chart’s background color to gray-50.

export default function App() {
  return (
    <div style={{ height: "100vh", width: "100vw" }}>
      <Chart
        items={convertData(data)}
        options={{ backgroundColor: colors["gray-50"] }}
      />
    </div>
  );
}
Tailwind CSS tutorial: ReGraph chart with nodes using colors from Tailwind CSS
Chart with nodes using colors from Tailwind CSS
Note on alternatives and using the older Tailwind version 3:

If you want to be able to reference Tailwind values directly in your code without the need to import them via getComputedStyles you can use a library such as Tailwind Theme Resolver.

In version 3 of Tailwind, referencing values directly in JavaScript is also possible by using the resolveConfig function that is provided in the library. This option is no longer available in version 4.

Link styling to reveal hidden patterns

With the node colors set, we’ll turn our attention to styling links. Remember, each link represents how often a mechanic claimed to have fixed damage to a specific vehicle part.

Fraud analysts have to make fast decisions about which areas of their investigation to prioritize. To make the most unusual activities stand out, we’ll color the links differently depending on how many times repairs were carried out to that part of any vehicle:

  • One to five times = we’ll make the links grey-500
  • Six to ten times = we’ll make the links yellow-500
  • More than ten times = we’ll make the links red-500

With that in mind, let’s update our styleLink function:

function styleLink(id1, id2, count) {
  const width = count * 0.4;
  let color = colors["gray-300"];

  if (count > 10) {
    color = colors["red-500"];
  } else if (count > 5) {
    color = colors["yellow-500"];
  }

  return { id1, id2, width, color };
}

Now our graph visualization features styled links as well as colored nodes:

Tailwind CSS tutorial: ReGraph chart with link widths and colors reflecting the most important network connections
Link colors and widths help analysts prioritize areas for investigation

We get a clearer view of which mechanics claimed for work on a specific vehicle part more than five times, and one in particular – Fraser’s – who allegedly repaired more than ten driver’s rear doors. Suspicious?

Adding icons to the mix

Familiar icons make nodes instantly recognizable. We’ll use the excellent Font Awesome icon set, version 7, to show mechanics as a wrench icon (fa-wrench) and damaged vehicle parts as a set of gears (fa-gears).

We install Font Awesome icons with:

npm install @fortawesome/fontawesome-free

Then we import it into our app by following ReGraph’s documentation on font icons. At the top import the FontAwesome all.css:

import "@fortawesome/fontawesome-free/css/all.css"

Then, change the Chart’s component options prop to include the newly imported font:

<Chart
  items={convertData(data)}
  options={{
    backgroundColor: colors["gray-50"],
    iconFontFamily: "Font Awesome 7 Free",
  }}
/>

Next, we need to ensure that the fonts are loaded before the Chart component is mounted. To do so, we can use React Suspense and document.fonts.load to load Font Awesome. Let’s import those from React at the top:

import { lazy, Suspense } from "react";

We need to extract the Chart into its own component, called ChartWrapper that we can lazy load. We use the lazy React function to create a FontReadyChart component that will return our ChartWrapper as soon as the fonts have finished loading. Then we add Suspense to the App component. Suspense will then take the lazy-loaded FontReadyChart component:

// New lazy component that load ChartWrapper
const FontReadyChart = lazy(() =>
  Promise.all([document.fonts.load('900 16px "Font Awesome 7 Free"')]).then(
    () => ({
      default: ChartWrapper,
    })
  )
);

// The Chart now sits in its own new component
function ChartWrapper() {
  return (
    <div style={{ height: "100vh", width: "100vw" }}>
      <Chart
        items={convertData(data)}
        options={{
          backgroundColor: colors["gray-50"],
          iconFontFamily: "Font Awesome 7 Free",
        }}
      />
    </div>
  );
}

// The App component now only holds Suspense
export default function App() {
  return (
    <Suspense fallback="Loading fonts...">
      <FontReadyChart />
    </Suspense>
  );
}

Lastly, we update the styleNode function. This sets the correct font icon based on the type of node: fa-wrench for mechanics and fa-gears for damage types.

function styleNode(text, type) {
  const color =
    type === "mechanic" ? colors["emerald-500"] : colors["blue-500"];

  const label = [
    {
      fontIcon: {
        color: colors.white,
        text: type === "mechanic" ? "fas fa-wrench" : "fas fa-gears",
      },
      backgroundColor: colors.transparent,
      fontSize: 30,
    },
    {
      text,
      color: colors["gray-700"],
      backgroundColor: colors.transparent,
      position: "s",
    },
  ];

  return { color, label };
}
Tailwind CSS tutorial: ReGraph chart with nodes represented by font icons: a wrench for mechanics and gears for vehicle damage types
Use real-world representations of items to bring graph visualizations to life

Practical context menus

A powerful way to provide useful details about the chart without overcrowding it is by adding clever interactions. Here, we trigger an onContextMenu event by right-clicking on Fraser’s to reveal exactly how many repairs they’ve claimed for.

Tailwind CSS tutorial: ReGraph chart that reveals a context menu of vehicle repairs when the user clicks on a mechanic node
Menus, annotations and tooltips are just some of the useful devices users rely on to gain deeper insight

For more on this, check out 4 easy styling options for interactive graph visualization.

Easy theming to turn light into dark

If you want graph visualizations styled in dark mode for improved accessibility or better aesthetics, it’s easy to achieve with ReGraph and Tailwind CSS.

Using Tailwind’s ‘dark’ variant and ReGraph’s controlTheme option, you can apply a dark theme with matching navigation and overview window controls.

Attractive dark mode for beautiful, stylish graph visualizations

Get started with ReGraph & Tailwind CSS

I hope you found this ReGraph and Tailwind CSS tutorial useful! We’ve kept things simple here, but the scope and variety of styling options available from both libraries are huge.

If you’re ready to start designing beautiful graph visualization apps, request a free trial.

How can we help you?

Request trial

Ready to start?

Request a free trial

Learn more

Want to learn more?

Explore our resource hub

“case

Looking for success stories?

Browse our case studies

Registered in England and Wales with Company Number 07625370 | VAT Number 113 1740 61
6-8 Hills Road, Cambridge, CB2 1JP. All material © Cambridge Intelligence .
Read our Privacy Policy.