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

Break apart the string and transform each element in the array into a number or string using a more specific type inference

I am currently working on a function that has the ability to split a string using a specified separator and then convert the values in the resulting array to either strings or numbers based on the value of the convertTo property. Even when I call this fun ...

Tips for maintaining the 'client use' code snippet at the beginning of your Vs Code script

In my quest to utilize the NextJs app directory, I've come across a dilemma. To implement client-side components, it mandates the usage of 'use client' at the beginning of the file. However, Vs Code has a tendency to relocate this statement ...

Inquiry regarding the implementation of DTO within a service layer parameter

I have a query regarding the choice of service layer to use. // 1 export class SomeService{ async create(dto:CreateSomeDto) {} } or // 2 export class SomeService{ async create(title: string, content: string) {} } It appears that most individuals opt ...

Achieving the functionality of making only one list item in the navbar bolded upon being clicked using React and Typescript logic

Currently, in my navigation bar, I am attempting to make only the active or clicked list item appear bold when clicked. At the moment, I can successfully achieve this effect; however, when I click on other list items, they also become bolded, while the ori ...

Diverse Selection of Font Awesome Icons

In my React project with TypeScript, I have a header component that accepts an Icon name as prop and then renders it. I am trying to figure out the best way to ensure that the icon prop type matches one of the existing FontAwesome Icons. import { FontAwe ...

MUI Gradient Tracked Button

Take a look at this Codepen example I created. It showcases a hover effect where the gradient follows the mouse cursor. In order to achieve this effect, I have defined two CSS variables - --x and --y, to keep track of the mouse position on the button. The ...

Exploring the capabilities of UIGrid in conjunction with TypeScript DefinitelyTyped has been a

I've noticed that the latest release of UI Grid (RC3) has undergone significant architectural changes compared to nggrid. I am encountering some problems with the definitelytyped files for nggrid because they are from a different version. Will there ...

Arranging Alphanumeric Characters in Angular in Ascending Order

I am trying to sort a list of characters first, followed by alphanumeric values. Here is what I have: [Austria , Germany , 123aed , 234eds] This is my current sorting attempt: obj.sort((a,b) => { if ( (isNaN(a.text) && isNaN(b.text)) || ...

Issue with Angular filtering when utilizing pipe and mapping the response

Code snippet from shop.service.ts getProducts(brandId?: number, typeId?: number) { let params = new HttpParams(); if (brandId){ params = params.append('brandId', brandId.toString()); } if (typeId){ params = params.append('typeId', ...

I'm encountering an issue with this error message: "Warning: Each item in a list must be assigned a unique 'key' prop."

I encountered an error message... Warning: Each child in a list should have a unique "key" prop. I'm puzzled about this because I believe I have assigned a unique key for my map. All the resources I've checked regarding this warning are relat ...

What is the best way to link this to a function in AngularIO's Observable::subscribe method?

Many examples use the Observable.subscribe() function in AngularIO. However, I have only seen anonymous functions being used like this: bar().subscribe(data => this.data = data, ...); When I try to use a function from the same class like this: update ...

Tips for passing parameters from an anchor click event in TypeScript

Is it possible to send parameters to a click event from an anchor element, or should we not pass params at all? Here is the function I am using: const slideShow = (e: React.MouseEvent<HTMLAnchorElement> | undefined): void => { console.lo ...

Challenges Arising from Adding Extra Information to User Session with NextAuth in Next.js

I've encountered an issue while trying to include extra data in the user session of a Next.js application using NextAuth. My goal is to append data retrieved from an API to the session, but I'm facing unexpected challenges. Below is the relevant ...

Issue: Module './App' not found in webpackSolution: Check if the module path is

I've decided to switch my .js files to .tsx in order to start using TypeScript. To incorporate TypeScript, I used the following command: yarn add typescript @types/node @types/react @types/react-dom @types/jest and began converting first index.tsx fo ...

The comparison between using Reflect.decorate and manual decorating in TypeScript

Here are two different decorators that I am using: import "reflect-metadata"; const enum MetadataTypes { Type = "design:type", Paramtypes = "design:paramtypes", ReturnType = "design:returntype" } function DecoratorA(target: any, key: string): void ...

Strategies for modifying the bound value in Angular with an observable object

I am attempting to convert the offset value for a time object in the URI, which is stored in an observable object. The issue I am encountering is: ERROR Error: NG0100: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checke ...

Using GraphQL in React to access a specific field

Here is the code snippet I am working with: interface MutationProps { username: string; Mutation: any; } export const UseCustomMutation: React.FC<MutationProps> | any = (username: any, Mutation: DocumentNode ) => { const [functi ...

Submit information by utilizing' content-type': 'application/x-www-form-urlencoded' and 'key': 'key'

Attempting to send data to the server with a content-type of 'application/xwww-form-urlencode' is resulting in a failure due to the content type being changed to application/json. var headers= { 'content-type': 'applica ...

Using a static value in the comparator is necessary for Array.find to function properly in Typescript

Looking to retrieve an item from an array: const device = this.selectedDevtype.devices.find(item => console.log(this.deviceID); return item.device_id === this.deviceID; }); console.log(device); When this.deviceID is logged, it shows "4", but t ...

How can we set up the Typescript Compiler to recognize typings and modules effectively?

I have been working on a TypeScript project with the following structure: <work folder>/Scripts/ (project root) +-- App +--- subfolder1 +--- subfolder2 +-- typings After openi ...