Mastering the utilization of React props within a Tailwind component

Looking to implement a straightforward button component in a Next App using Tailwind CSS, where I can pass values such as background color, text color, etc. through props and use them to render different types of buttons within my application.

Take a look at the available color options:

export type ColorOptions =
  | "light"
  | "primary"
  | "secondary"
  | "terciary"
  | "details";

Here is the code for my customized button component:

import { ButtonHTMLAttributes } from "react";
import { ColorOptions, FontOptions } from "@/app/@types/theme";

type ButtonNativeProps = ButtonHTMLAttributes<HTMLButtonElement>;

type ButtonProps = ButtonNativeProps & {
  children: React.ReactNode;
  onClick: () => void;
  color?: ColorOptions;
  background?: ColorOptions;
  font?: FontOptions;
  fontSize?: string;
  icon?: React.ReactNode;
  styleProps?: string;
};

export default function Button({
  children,
  onClick,
  color = "light",
  background = "terciary",

// Rest of the component code goes here...

And this is my tailwind.config.js:

/** @type {import('tailwindcss').Config} */
module.exports = {

// Custom theme configurations...

Initially, everything seems to be working fine as you can see in this initial result.

However, upon specifying a value in the button component like so, the expected result disappears:

<Button background="details" onClick={() => {}} />

The desired background color is not applied.

Even though the class is correctly defined in the HTML element according to the browser's elements tree, the colors are not being displayed properly.

Answer №1

According to the documentation:

The key point to note about how Tailwind extracts class names is that it will solely recognize classes that are present as complete unbroken strings in your source files.

If you combine partial class names using string interpolation or concatenation, Tailwind won't detect them and consequently won't generate the associated CSS:

Avoid creating dynamic class names

<div class="text-{{ error ? 'red' : 'green' }}-600"></div>

In the given example, the strings text-red-600 and text-green-600 aren't valid, so Tailwind won't produce those classes. Always ensure that any class names used are complete:

Stick to full class names always

<div class="{{ error ? 'text-red-600' : 'text-green-600' }}"></div>

You might consider:

  • Employing complete class names in the props, for instance:
    export default function Button({
      children,
      onClick,
      color = "text-light-100",
      background = "bg-terciary-100 hover:bg-terciary-75",
      font = "font-main",
      fontSize = "text-xl",
      icon,
      styleProps,
      ...props
    }: ButtonProps) {
      return (
        <button
          onClick={onClick}
          className={`${font} ${background} ${color} ${fontSize} flex flex-row px-6 py-3 rounded-small font-bold tracking-wide transition animation ${styleProps}`}
    
  • Utilizing class maps:
    const COLOR = {
      light: 'text-light-100',
      …
    };
    
    const BACKGROUND = {
      terciary: 'bg-terciary-100 hover:bg-terciary-75',
      …
    };
    
    const FONT = {
      main: 'font-main',
      …
    };
    
    const FONT_SIZE = {
      xl: 'text-xl',
      …
    };
    
    export default function Button({
      children,
      onClick,
      color = "light",
      background = "terciary",
      font = "main",
      fontSize = "xl",
      icon,
      styleProps,
      ...props
    }: ButtonProps) {
      return (
        <button
          onClick={onClick}
          className={`${FONT[font]} ${BACKGROUND[background]} ${COLOR[color]} ${FONT_SIZE[fontSize]} flex flex-row px-6 py-3 rounded-small font-bold tracking-wide transition animation ${styleProps}`}
    
  • Using safelist in your Tailwind configuration:
    /** @type {import('tailwindcss').Config} */
    module.exports = {
      …
      safelist: [
        { pattern: /^(bg|text)-.+-100$/ },
        { pattern: /^bg-.+-75$/, variants: ['hover'] },
        { pattern: /^font-(title|main|code|sans|sans-serif|mono)$/ },
        { pattern: /^text-(xs|sm|base|lg|[0-9]?xl)$/ },
      ],
    }
    

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Executing functions in real-time using React Native

I'm fairly new to Object-Oriented Programming (OOP) and my understanding of promises, asynchronous/synchronous function execution is quite basic. Any guidance or help from your end would be greatly appreciated! Let's take a look at an example fr ...

When using React.js Material UI's CardActionArea with a flex display, the children elements may not automatically use the full width as expected

Getting straight to the point - I recently experimented with changing the display style property from block to flex, along with setting flexDirection: 'column' for the CardActionArea component. The main goal was to ensure that CardContent maintai ...

CSS Flexibility in Action

Presently, my tab bar has a fixed look as shown here: https://codepen.io/cdemez/pen/WNrQpWp Including properties like width: 400px; etc... Upon inspecting the code, you'll notice that all the dimensions are static :-( Consequently, I am encountering ...

The environmental variables stored in the .env file are showing up as undefined in Next.js 13

I am having trouble accessing the environment variables stored in my .env.local file within the utils folder located in the root directory. When I try to console log them, they show as undefined. console.log({ clientId: process.env.GOOGLE_ID, clien ...

What is the best way to create a nested item in the database?

Encountering various difficulties while attempting to create a new user with a nested related table in my database setup: model User { id Int @id @default(autoincrement()) username String @unique ...

The Material UI library is signaling that there is an unidentified property called `selectable` being used with the <table> tag

Whenever I try to add the selectable attribute to the Table component in Material-UI using React JS, I encounter an error. Despite checking that selectable is indeed included in TableProps, the issue persists. List of Dependencies : "material-ui": "1.0.0 ...

Retrieve an SVG file from the internet and incorporate it as a <svg /> element within a React component in a Next.js project

I have a situation where I am trying to style .svg files within an API being used by a NEXT.js application. Currently, the files are loaded using <img src="https://api.com/image.svg" />, but this method does not allow for styles to be appl ...

What is the best way to apply CSS styles to a child div element in Next.js?

I'm currently working on enhancing the menu bar for a website project. Utilizing nextjs for my application I am aiming to customize the look of the anchor tag, however, encountering some issues with it not rendering correctly. Here is a snippet of ...

Firefox not displaying caret in Bootstrap dropdown

I am trying to display a caret on the right side of a bootstrap dropdown button inside a button-group. Here is the code snippet I am using: <div class="span3 well"> <div class="btn-group btn-block"> <a class="btn btn-primary dro ...

What is the best way to include CSS styles in a React app with Webpack?

Having an issue with my React app. Upon successfully compiling Webpack and serving the content, no styles are displayed within the app. This is the current content of my webpack.config.js file: const path = require('path'); const BUILD_DIR = pat ...

The form creation and modification rendering feature in API Platform Admin isn't functioning properly

I'm facing an issue in my admin panel where the API functions correctly for posting and getting data. However, when I try to create or update objects using the admin panel, I encounter a blank form. You can view the screen here. Additionally, there i ...

Tips for correctly loading all elements on an HTML page before making CSS modifications

This question has been asked several times in the past. I am asking because when I used the on ready callback in jQuery, it did not change the placeholder text of my element "search_input". $( document ).ready(function() { $("#search_input").attr(' ...

How can I ensure that Redux-saga waits for API calls to resolve instead of returning promises continuously? Is there a way to make "yield call" wait for API calls to complete?

Where I'm initiating the API request: function fetchCharacter(value){ return axios.get(`https://www.breakingbadapi.com/api/characters?name=${value}`) .then(res=>{ console.log(res.data) }) .cat ...

Prisma is continuously spitting out data beyond my jurisdiction

I'm currently working on a project that involves postgreSQL and Prisma. While debugging in getServerSideProps(), I noticed that Prisma is automatically console.logging long strings like the following: prisma:query SELECT "public"."TaskC ...

What are the TypeScript types needed for a React component that accepts an array of objects as a prop?

I am currently working on a React component that includes a prop named propWhichIsArray. This prop is expected to be an array of objects. Each object in the array will contain properties such as id (an ID) and text (a string). How do I properly define this ...

I am experiencing difficulty getting my CSS styles to apply to my application that is being rendered using zappa, express, and node.js

Here is a link to my code: http://pastebin.com/jcLRCrQr Although everything else seems to be working fine - CSS sheets loading correctly, JavaScript files functioning properly - I am facing an issue where the styles are not being applied. An odd thing I ...

Creating a CSS animation to repeat at regular intervals of time

Currently, I am animating an SVG element like this: .r1 { transform-box: fill-box; transform-origin: 50% 50%; animation-name: simpleRotation,xRotation; animation-delay: 0s, 2s; animation-duration: 2s; animation-iterat ...

Guide to implementing tooltips for disabled <li> elements in AngularJS

I have a list of items that are displayed using the following code: <li class="dropdown-item" data-toggle="tooltip" uib-tooltip="tooltip goes here" data-placement="left" data-ng-repeat="result in items.results.contextValues.rows " ...

The type '{}' cannot be assigned to type 'IntrinsicAttributes & FieldsProp'. This error message is unclear and difficult to understand

"The error message "Type '{}' is not assignable to type 'IntrinsicAttributes & FieldsProp'.ts(2322)" is difficult to understand. When I encountered this typeerror" import { useState } from "react"; import { Card } fr ...

Adjusting the state prevents the input fields from being updated

Encountering a problem where setting the const buyFormData results in updating the array but causing the rest of the code (which updates the Input Fields) to stop functioning. No javascript error is showing, the code just hangs there. In my child component ...