ui icon indicating copy to clipboard operation
ui copied to clipboard

[bug]: Cursor pointer not working when hovering on button in Tailwind v4

Open aow3xm opened this issue 10 months ago • 24 comments

Describe the bug

Description

When I hover over a button, the cursor does not change to a pointer as expected. This issue occurs in my Next.js 15 project using ShadCN v4. I also checked the https://v4.shadcn.com/#button, and the same issue is present there. The cursor does not display as a pointer when hovering over buttons.

Affected component/components

Button

How to reproduce

  1. Set up a Next.js 15 project.
  2. Install and configure ShadCN v4.
  3. Add a button component using ShadCN's button implementation.
  4. Hover over the button.
  5. Observe that the cursor does not change to a pointer.

Codesandbox/StackBlitz link

https://codesandbox.io/p/devbox/8jqnnq

Logs


System Info

1. Framework: Next.js 15
2. ShadCn: v4
3. Browser: Tested on Chrome, Edge
4. OS: Windows 11

Before submitting

  • [x] I've made research efforts and searched the documentation
  • [x] I've searched for existing issues

aow3xm avatar Mar 03 '25 18:03 aow3xm

This is expected, as mentioned on the v4 page:

Buttons now use the default cursor.

samialdury avatar Mar 03 '25 22:03 samialdury

I would like to know more about this decision process, is it no longer cool to have cursor: pointer on button nowadays, or what? Am I missing something here? Does this conform to some HTML spec? If anyone has more information on this please let me know.

shahriar-shojib avatar Mar 04 '25 08:03 shahriar-shojib

https://ux.stackexchange.com/questions/105024/why-dont-button-html-elements-have-a-css-cursor-pointer-by-default

Jungzl avatar Mar 04 '25 09:03 Jungzl

They just removed cursor pointer of button by default in Tailwind v4, so I had to add custom CSS to globals.css

@layer base {
  button, [role="button"] {
    cursor: pointer;
  }
}

aow3xm avatar Mar 04 '25 10:03 aow3xm

@aow3xm thanks for sharing that snippet. I would add this to ensure you don't get pointers on disabled buttons:

@layer base {
  button:not([disabled]),
  [role="button"]:not([disabled]) {
    cursor: pointer;
  }
}

Koda-Pig avatar Mar 04 '25 15:03 Koda-Pig

This is a really strange behavior. I expect my users to see they are hovering a button with their cursor changing. It's the most common practice, and even when browsing shadcn documentation, buttons are still showing this cursor pointer :(

EnzoPV25 avatar Mar 06 '25 13:03 EnzoPV25

https://ux.stackexchange.com/questions/105024/why-dont-button-html-elements-have-a-css-cursor-pointer-by-default

Thank's for this, very instructive.

However I truly think that having an option to keep the old behavior would be really nice since most of huge website are using pointer cursor on buttons (github, facebook, microsoft, stackoverflow, ....).

EnzoPV25 avatar Mar 06 '25 15:03 EnzoPV25

Try explaining this to 99% of product managers, QA, any non techs or just run with the above mentioned hack with targeting all buttons. I wish this decision was up for community discussion because I do consider this to be a breaking change.

shahriar-shojib avatar Mar 06 '25 16:03 shahriar-shojib

It'd be great if we call this out on the component examples or have them follow the default behavior. I was wondering why my local install was not matching the examples/docs until I stumbled on this

gordysc avatar Mar 07 '25 12:03 gordysc

fucking retards!

ergors avatar Mar 09 '25 17:03 ergors

I don't understand, this should be reopen

nshen avatar Mar 11 '25 05:03 nshen

Strange behavior.

@aow3xm thanks for sharing that snippet. I would add this to ensure you don't get pointers on disabled buttons:

@layer base { button:not([disabled]), [role="button"]:not([disabled]) { cursor: pointer; } }

Thanks for the snippet.

SylvainCostes avatar Mar 14 '25 11:03 SylvainCostes

Button with Link variant also has a default pointer. That one could at least have a pointer cursor.

mburakeker avatar Mar 16 '25 15:03 mburakeker

This threw me for a loop lol. I wonder why tailwind decided to make this default. Very strange. It also makes is more difficult a user to see when a button is disabled, notably, with the secondary variant on the shadcn button.

ethandpowers avatar Mar 18 '25 17:03 ethandpowers

@aow3xm thanks for sharing that snippet. I would add this to ensure you don't get pointers on disabled buttons:

@layer base { button:not([disabled]), [role="button"]:not([disabled]) { cursor: pointer; } }

savior!

bvsvntv avatar Mar 20 '25 06:03 bvsvntv

Try explaining this to 99% of product managers, QA, any non techs or just run with the above mentioned hack with targeting all buttons. I wish this decision was up for community discussion because I do consider this to be a breaking change.

I tried telling my lead designer that they changed the pointer behavior cuz of the ux and he laughed saying how is the user supposed to know it's a button? especially with ghost and sometimes the outline variants.

Elhamullah-Hossaini avatar Apr 07 '25 11:04 Elhamullah-Hossaini

Currently, I find that button.tsx in shade/cn doesn't have cursor-pointer attribute.

In the existing tailwind v3, there was a button cursor attribute globally, but in v4, the disappearance from the global attribute seems to be the cause.

So I solved it used that code in tailwind v3.

@layer base {
  [role="button"],
  button {
    cursor: pointer;
  }

  :disabled {
    cursor: default;
  }
}

I think cursor attribute should be added to shad/cn's default global setting!!

Turtle-Hwan avatar Apr 08 '25 07:04 Turtle-Hwan

Closing this issue since it's not really a bug is nice, but still, where should we debate about this weird behavior then ? Is there a feed somewhere ?

EnzoPV25 avatar Apr 15 '25 07:04 EnzoPV25

You should not close since even shadcn said he is thinking on this.

Image

bernaferrari avatar Apr 22 '25 17:04 bernaferrari

Yes reopening. I'm working on this.

shadcn avatar Apr 22 '25 17:04 shadcn

I trust @shadcn

yhoungdev avatar Apr 22 '25 18:04 yhoungdev

Don't talk about "standards". Standards are dead, but people are alive. Removing the default cursor pointer of a button is simply the opposite of heaven.

UI design is diverse. It is not necessarily a button if there is a circular or square background with a few words on it. It can also be a key point or content that needs to be highlighted, or even just a "design".

Removing the cursor pointer of the button not only violates the most basic user experience principles, but also attempts to change people's long-standing habits. What's funny is that this modification is just to meet a standard from N years ago?

f3liiix avatar Apr 23 '25 01:04 f3liiix

I was browsing around to understand this and even in the Tailwind pr #8962 asking to not use cursor: pointer on buttons the example they give in Linear apparently no longer itself uses default for buttons but back to pointer

The ship has sailed for defaults, users now expect buttons to have a pointer not just links

MAiKo26 avatar Apr 23 '25 09:04 MAiKo26

I don't know what kind of devil opened Tailwind, but cursor:pointer for buttons is currently literally everywhere and clients expect it too. Referring to standards from 15 years ago is so strange, especially since the authors of Tailwind seem to be people who base their decisions on research rather than personal preferences.

Anyway, thank you @shadcn for keeping your finger on the pulse and thinking logically. I appreciate it.

hubciorz avatar Apr 26 '25 20:04 hubciorz

@aow3xm thanks for sharing that snippet. I would add this to ensure you don't get pointers on disabled buttons:

@layer base { button:not([disabled]), [role="button"]:not([disabled]) { cursor: pointer; } }

Thanks for sharing this 👍 - Out of curiosity - why is this your approach instead of just adding the Tailwind class to the Button component?

Image

garlic-brewlabs avatar Apr 29 '25 12:04 garlic-brewlabs

I want to add my 2 cents to this: To me it feels incredibly irritating if I don't get feedback when hovering over an element. If it looks like a button and behaves like a button it should also quack like a button - the cursor staying the same to me always feels like as if website has locked up.

Janrupf avatar Apr 30 '25 08:04 Janrupf

Yes reopening. I'm working on this.

Thanks @shadcn. Do you plan on making all clickable elements in shadcn ui curosor:pointer? I hope so!

I understand the affordances and the standards history. But the vast majority of computer users believe:

if something is clickable, I see that hand pointing cursor".

So the UX should align with that. Imo we shouldn't rashly meet standards at the cost of a good UX.

AshConnolly avatar May 03 '25 14:05 AshConnolly

Hi ! Any update on this @shadcn ? :-)

EnzoPV25 avatar Jun 04 '25 09:06 EnzoPV25

Classic case of bureaucracy over common sense.

kubk avatar Jul 14 '25 05:07 kubk

@aow3xm thanks for sharing that snippet. I would add this to ensure you don't get pointers on disabled buttons:

@layer base { button:not([disabled]), [role="button"]:not([disabled]) { cursor: pointer; } }

Thanks for this.

lambegraham avatar Jul 31 '25 23:07 lambegraham