Creating custom disabled button styles using TailwindUI in a NextJS application

I had a NextJS application that utilized Atomic CSS and featured a button which becomes disabled if a form is left unfilled:

      <Button
        className="primary"
        onClick={handleCreateCommunity}
        disabled={!phone || !communityName}
      >
        Create
      </Button>

Now, I am looking to switch to using the new TailwindUI primary button style:

.primary-btn {
    @apply inline-flex items-center px-6 py-3 border border-transparent text-base font-medium rounded-md shadow-sm text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500;
}

However, I am facing an issue with applying the disabled state. Do I need to create another component like .btn-disabled? If so, how can I then apply that style when the form remains incomplete?

--

UPDATE:

Here is what my index.css file currently looks like:

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

@layer components {
    .primary-btn {
        @apply inline-flex items-center px-6 py-3 border border-transparent text-base font-medium rounded-md shadow-sm text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 disabled:bg-gray-300;
    }
 }

Answer №1

It is important to define specific styles for the disabled state, just like you would with the focus state.

Note: Your use of directives seems to be missing based on your feedback. These directives are crucial as they can override default tailwind styles during compilation, preventing duplication and clearing out unused custom styles at build time.

Make sure to import custom styles after applying them to the appropriate layer. In this case, it should come after @tailwind components.

@tailwind components;

@layer components {
 .primary-btn {
  @apply disabled:bg-blue-300;
 }
}

Answer №2

If you're interested in transitioning easily from `atomic-css` to `tailwind-css`, I recommend utilizing the `button` component provided by `tailwind-css`.

Here's a basic pattern to achieve your desired outcome:

<button
  type="button"
  className=" /* add class attributes */
               disabled: /* add disabled class attributes*/ "
  disabled={/* logic for enabling or disabling */}
>

So, your final code would look something like this:

<button
  type="button"
  className=" inline-flex items-center px-6 py-3 border border-transparent text-base font-medium rounded-md shadow-sm text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 disabled:bg-gray-300"
  onClick={handleCreateCommunity}
  disabled={!phone || !communityName} // your disable logic here
>
  Primary
</button>

Output :

When disabled is false :

https://i.stack.imgur.com/6s3y7s.png

When disabled is true

https://i.stack.imgur.com/kDXMts.png

Note: If you prefer defining class attributes in a CSS file, you can accomplish that by including styles in the index.css file under `@layer components`.

@layer components {
  .primary-btn {
    @apply m-5 inline-flex items-center px-6 py-3 border border-transparent text-base font-medium rounded-md shadow-sm text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 disabled:bg-gray-300;
  }
}

Then, the button's className simplifies to just `primary-btn`

<button
      type="button"
      className="primary-btn"
      disabled={false} // your disable logic goes here
    >
      Primary
 </button>

Answer №3

Perhaps you'll find this approach helpful. Instead of using separate styles for a disabled button, I opt to apply styles directly to my button element as shown below:

<button
    class="disabled:bg-gray-600 bg-green-600 hover:bg-green-700"
    onClick={handleCreateCommunity}
    disabled={!phone || !communityName}
  >
    Create
  </button>

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

Looking to reallocate information, paginate, and sort each time a new row is added to the mat-table

In my application, I have a customized <mat-table> with an implemented addRow() function that adds a new row to the table using default values based on the data type. The challenge I'm facing is that each time a new row is added, I find myself ...

Error: inability to execute performanceMeasurement.startMeasurement due to its absence in the function definition

An error occurred when attempting to login using @azure/msal-react in Next 13. Upon checking the error log, it was found that the error originated from the core library @azure/msal-react. Even after trying with a login popup, the error persisted. In my co ...

Issue encountered while trying to insert a new row into the mat-table

I need help with inserting a new row in mat-table using a button. I wrote a function for this, but when I click the button, I encounter an error CalculatoryBookingsComponent.html:62 ERROR Error: Cannot find control with path: 'rows -> 0'. Addi ...

Having trouble with your start script crashing during your first Next.js project deployment on Heroku?

Seeking guidance as a beginner? My first next.js project works fine locally with no warnings and deploys successfully on Heroku. However, when I view the app, I encounter an error page prompting me to check my logs. I followed a tutorial posted here. You ...

The error message "better-sqlite3 TypeError: o.default is not a constructor" indicates that

As part of my vscode extension development in typescript, webpack, and better-sqlite3, I am attempting to create a database within the C:\Users\userName\AppData\Roaming\Code\User\globalStorage\ folder. However, when ...

Accessing JSON data from a database using Angular

Wondering if there is a way to effectively access and manipulate JSON data stored in a database using Angular. While researching online, I keep coming across methods for reading JSON files from the Asset Folder, which does not align with what I need. What ...

In order to showcase the data from the second JSON by using the unique identifier

SCENARIO: I currently have two JSON files named contacts and workers: contacts [ { "name": "Jhon Doe", "gender": "Male", "workers": [ "e39f9302-77b3-4c52-a858-adb67651ce86", "38688c41-8fda-41d7-b0f5-c37dce3f5374" ] }, { "name": "Peter ...

How can we use getStaticProps() in Next.js to update intermittent modifications?

Imagine this situation: I'm integrating some static pages into Next.js, so utilizing getStaticProps() seems like a good approach. However, an admin user may need to update the content of these pages from an admin console in the future, but not very f ...

Encountering the error message "Required property 'src' is missing in image" while using Next.js image functionality

Oh no! There seems to be an issue: The image is missing the required "src" property. Make sure you include the "src" in the props when using the next/image component. Received: {"width":48,"height":48} I'm having trouble underst ...

Inject props into a Component nested within a Higher-Order-Component (HOC)

In attempting to grasp the concept of creating a React Higher Order Component from this particular article, I find myself struggling to fully understand and utilize this HOC. interface PopupOnHoverPropType { hoverDisplay: string; } const WithPopupOnHov ...

Using next.js with GraphQL resulted in the following error: "Invariant Violation: Unable to locate the "client" in the context or passed in as an option..."

I've searched extensively online, but I can't find a solution to my problem. Here is the error message I'm encountering: Invariant Violation: Could not find "client" in the context or passed in as an option. Wrap the root component in an ...

How can one retrieve data from two distinct API routes within a Next.js application?

Currently, I am working with Next.js and facing a challenge in fetching data from two different API routes simultaneously. My intention is to retrieve this data within the getServerSideProps function. The first dataset that I require can be found at the e ...

Is there a way to make Typescript accept dot notation?

Is there a way to suppress the compile time error in Typescript when using dot notation to access a property that the compiler doesn't know about? Even though using bracket notation works, dot notation would be much more readable in my specific case. ...

Do not apply tailwindcss styles to Material-UI

I've been struggling to apply styling from tailwindcss to my MUI button. My setup includes babel and webpack, with the npm run dev script as "webpack --mode development --watch". tailwind.css module.exports = { content: ["./src/**/*.{js, jsx, t ...

Steps to import an external script into a NextJS application and access it from the main bundle

I have encountered an issue while working with the mercadopago library. I need to load the mercadopago script file and create an instance of the MercadoPago object. However, nextJS loads the main bundle before including the mercadopago file, resulting in a ...

Typescript: Declaring object properties with interfaces

Looking for a solution to create the childTitle property in fooDetail interface by combining two properties from fooParent interface. export interface fooParent { appId: string, appName: string } export interface fooDetail { childTitle: fooParent. ...

What is preventing me from accessing a JSON file on Vercel while utilizing Next.js SSR?

I am currently working on a basic Next.js project with three main files. My goal is to populate the index page with data from a JSON file. Interestingly, when I deploy the project to Vercel using getStaticProps, everything functions correctly. However, up ...

Using NextJS with Storybook: The Issue with Optional Chaining

https://i.stack.imgur.com/lY2F1.png rehype-ignore - index.js contains the following code snippet: import { visit } from 'unist-util-visit'; const rehypeIgnore = (options = {}) => { const { openDelimiter = 'rehype:ignore:start', ...

Validating image uploads using Yup and Formik in a standalone module

I am facing an issue in my Next.js application where I am attempting to validate the upload of an image using Formik and Yup by passing a method called handleOnImageChange in the component. However, I am struggling to make it work this way. I have also tri ...

Issue: Module 'stylelint' not found in Angular Project

I've been attempting to execute this command to validate all of the .scss files (and even tried with .css files) and I keep encountering this error. $ stylelint "apps/**/*.scss" It worked once before but not anymore, even after restarting my compute ...