Skip to content

## Bug: ease-btn-disabled hover effects persist for keyboard-focus users #1382

@Pcmhacker-piro

Description

@Pcmhacker-piro

Bug: ease-btn-disabled hover effects persist for keyboard-focus users

Description

The ease-btn-disabled class uses pointer-events: none to prevent mouse interactions, but keyboard users can still tab to the disabled button and trigger :focus-visible hover effects. This creates a confusing experience where a disabled button visually highlights on keyboard focus but cannot be activated.

Steps to Reproduce

  1. Link EaseMotion CSS v1.0.0
  2. Create a disabled button in a form:
    <button class="ease-btn ease-btn-primary ease-btn-disabled" tabindex="0">
      Submit
    </button>
  3. Tab to the button using the keyboard
  4. Observe that hover effects (ease-btn-hover, background change) still apply on focus

Expected Behavior

Disabled buttons should not respond to any interaction state — hover, focus, or active — regardless of input method. They should appear uniformly visually muted.

Actual Behavior

The ease-btn-disabled class applies:

.ease-btn-disabled {
  opacity: 0.6;
  cursor: not-allowed;
  pointer-events: none;
}

pointer-events: none only disables pointer (mouse/touch) input. The button remains focusable via keyboard navigation (Tab key) and :focus-visible styles still apply. On browsers that show a focus ring, the disabled button gets a visible focus outline and any :hover styles (like darkening or glow effects) still activate via :focus-visible, making the button appear interactive even though clicking or pressing Enter does nothing.

Implementation Hints

The issue is in components/buttons.css:

/* Current implementation */
.ease-btn-disabled {
  opacity: 0.6;
  cursor: not-allowed;
  pointer-events: none;
}

The fix needs to prevent keyboard focus and remove hover/focus styles:

/* Fixed implementation */
.ease-btn-disabled,
.ease-btn[disabled] {
  opacity: 0.6;
  cursor: not-allowed;
  pointer-events: none;
  /* Prevent keyboard focus */
  tab-index: -1;
  /* Remove any hover/focus/active visual states */
  box-shadow: none !important;
  transform: none !important;
  /* Prevent screen readers from announcing as interactive */
  aria-disabled: true;
}

/* Also suppress hover styles specifically for disabled state */
.ease-btn-disabled:hover,
.ease-btn-disabled:focus,
.ease-btn-disabled:focus-visible,
.ease-btn-disabled:active {
  opacity: 0.6;
  transform: none !important;
  box-shadow: none !important;
  outline: none !important;
}

/* Ensure no hover effects leak through */
.ease-btn-disabled.ease-btn-hover:hover,
.ease-btn-disabled.ease-hover-glow:hover,
.ease-btn-disabled.ease-hover-lift:hover {
  transform: none !important;
  box-shadow: none !important;
  filter: none !important;
}

Additionally, for proper accessibility, the framework should recommend using the native disabled attribute instead of (or in addition to) the CSS class:

/* Also target the native disabled attribute */
.ease-btn[disabled] {
  opacity: 0.6;
  cursor: not-allowed;
  pointer-events: none;
  tab-index: -1;
}

And update the documentation to recommend:

<button class="ease-btn ease-btn-primary" disabled>Submit</button>

instead of:

<button class="ease-btn ease-btn-primary ease-btn-disabled">Submit</button>

Affected Files

  • components/buttons.css.ease-btn-disabled missing keyboard/tab-index suppression and hover-state overrides
  • docs/index.html — documentation examples should use disabled attribute over .ease-btn-disabled class

Labels

type:bug, level:intermediate, GSSoC-26

Metadata

Metadata

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions