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

Unexpected undefined error thrown by NextJS14 Middleware

I am integrating the npm package "serverless-mysql" with NextJS to handle user authorization in my database through a middleware. However, I encountered an error when a user tries to log in: Error: TypeError: Cannot read properties of undefined (reading &a ...

Show a collection of elements containing attributes in JSX

I have a React component where I am displaying data from an array called pkgData: <div className="mainApp"> <div className="pkgsList"> {pkgData.map((p) => <h3 key={p.name}>{p.name}</h3> ...

Exploring the functionality of closing Material UI Drawer on escape key in a React 16 app with RTL support

I am currently experimenting with the Material UI Drawer component. I expected it to close when pressing the Esc key or clicking outside of it, but unfortunately, it is not behaving as anticipated. I am utilizing the react testing library for my tests an ...

Step-by-step guide on eliminating the modal post-validation

Newbie in reactjs looking for help with modal validation issue. Goal: Press submit button inside modal, validate, then close the modal. Want to reuse modal for another row. Problem: I'm having trouble making the function work for a new row after ...

Animated CSS sidemenu (utilized as a filtering panel for a table)

Hi there, I'm having some trouble with CSS Animation. I recently started developing websites and am using Bootstrap 4 along with Animate.css for animations. My goal is to have an icon button expand sideways to reveal a div containing select elements f ...

Looking to modify the styling of links in an unordered list?

Let me explain what I attempted to accomplish CSS: li:nth-child(2n) { background-color:gray; } HTML: <ul> <li><a></a></li> <li><a></a></li> <li><a></a></li> ...

Issues with CodeIgniter paths causing disruption to CSS background-image declaration

I've been working on a website with backend for two separate customers, each with their own unique URLs. I encountered an issue with Javascript links (ajax calls using url:) but managed to resolve it by using a global variable: var SiteURL='< ...

Refresh Form Following Submission

When using a react form that triggers a graphql mutation upon button click, the text entered in the form fields remains even after the mutation has been executed. This necessitates manual deletion of text for subsequent mutations to be run. Is there a way ...

Adding text to a horizontal scrolling element causes the parent div to be pushed downwards

Can anyone help me understand why inserting text into one of the divs in a horizontally scrolling div causes the parent div to move downward? Looking for suggestions! @import url('https://fonts.googleapis.com/css?family=Hind:300,400,500,600,700&apo ...

Incorporating Close, Minimize, and Maximize functionalities into a React-powered Electron Application

Struggling with implementing minimize, maximize, and close functionality for a custom title bar in an electron app using React Typescript for the UI. The issue lies within the React component WindowControlButton.tsx, as it should trigger actions to manipu ...

Adjust the content column in the form to be mobile-friendly

Currently, I am coding in PHP and using Bootstrap. In my project, there are two columns - the LEFT column displays text, while the RIGHT column contains a form: Presently, when viewing on desktop, both columns are visible. However, on mobile devices, ...

My custom styles no longer seem to be applying after upgrading Angular Material from version 14 to 15. What could be causing this issue

Having some challenges with the migration from Angular 14 to Angular 15 when it comes to overriding material UI elements and themes. Looking for blog posts or documentation that can provide guidance on how to smoothly transition. Specifically, experiencin ...

What is a more effective method for updating a component by utilizing both state and props for rendering?

I am new to Next.js and ReactJS, and I recently encountered a situation where I needed to create a component that would render different child components within the parent component based on a click event in the DOM element to change its state. My initial ...

What is the procedure for turning off hover color on an href element?

Working on a website that utilizes MUI components, I have incorporated href into the Tab elements within the navigation bar. <Tab label={element} id={index} sx={{display: {xs: 'none', md: 'inherit'}}} href={`#${navElements[element ...

What is the method for performing calculations and retrieving data from an array in this scenario?

The process involves retrieving data from the database and populating an array named rows, which is used to calculate invoiceSubtotal (using the subtotal function), invoiceTaxes, and invoiceTotal. Even though the data is successfully stored in the array, t ...

Tips for receiving notifications when the Collapsible collapses

I'm having trouble figuring out how to receive notifications when the Collapsible is expanded and collapsed. Currently, I am not receiving any type of notification. Any suggestions on how to make this work? Below is my code: --Imported jQuery < ...

Developing a React component for distribution leads to a significantly increased build size compared to initial estimations

After loosely following a guide to create React components for distribution, I was surprised by the size of my webpack production build. The individual file sizes are small, but the final build is much larger than expected. My source js and less files comb ...

Looking for a way to assign customized thumbnails to images in react-responsive-carousel and react-image-magnifiers?

I am currently working on a product viewer using react-responsive-carousel and react-image-magnifiers. Following an example from this GitHub repository, I encountered an issue with mapping custom thumbnails correctly. Although hard-coding the array works f ...

Implementing smooth transitions on iPad screens with responsive text

I am currently working on a personal project that involves creating images with hover transitions. The transition effect works perfectly on all browsers except for iPads. I'm facing an issue where I can't click on the image due to the presence of ...

React navigator appears stuck and unable to navigate between screens

I encounter an issue where my app closes when I press the switch screen button, but there is no error output displayed. I have checked for any version discrepancies and found no problem. The function I implemented for the button is functioning as expected ...