Skip to content

Conversation

@deepansh946
Copy link
Contributor

@deepansh946 deepansh946 commented Nov 19, 2025

Closes #5614

📝 Description

This PR fixes the implicit isClearable behavior in Input and NumberInput components. Previously, providing an onClear callback would automatically enable the clear button, even when isClearable was not explicitly set. This made the API unpredictable and violated separation of concerns.

⛳️ Current behavior (updates)

Before:

  • isClearable was implicitly enabled when onClear prop was provided
  • Escape key clearing worked when either isClearable was true OR onClear was provided
  • JSDoc comments incorrectly stated: "If isClearable is not explicitly set, the clear button will be shown when this prop is provided."

Example of problematic behavior:

<Input
  label="Username"
  onClear={() => console.log("clear pressed")}
  // isClearable is NOT set, but clear button still appears!
/>

🚀 New behavior

After:

  • isClearable is now controlled only by the explicit prop
  • Escape key clearing only works when isClearable is explicitly true
  • onClear is simply a callback executed when the clear button is clicked (if visible)
  • JSDoc comments updated to reflect the new behavior

Example of new explicit behavior:

<Input
  label="Username"
  onClear={() => console.log("clear pressed")}
  // Clear button will NOT appear unless isClearable={true} is set
/>

<Input
  label="Username"
  isClearable={true}
  onClear={() => console.log("clear pressed")}
  // Clear button WILL appear
/>

💣 Is this a breaking change (Yes/No):

Yes

Impact:

  • Any code that relied on the implicit behavior (providing onClear without isClearable) will no longer show the clear button
  • Developers must now explicitly set isClearable={true} to show the clear button

Migration path:

  1. Find all instances where onClear is provided without isClearable
  2. Add isClearable={true} prop to enable the clear button
  3. If you don't want the clear button but still need the callback, you can keep onClear without isClearable (the callback will still work if triggered programmatically)

Before:

<Input onClear={handleClear} />

After:

<Input isClearable onClear={handleClear} />

Summary by CodeRabbit

  • Refactor

    • Clear button now appears only when explicitly enabled via the isClearable prop; it no longer appears implicitly from an onClear handler.
    • Escape key clearing now only works when isClearable is enabled and the field is not read-only.
  • Tests

    • Updated tests to assert the clear button is absent unless isClearable is set.
  • Chores

    • Minor package version bumps recorded and internal docs clarified.

@changeset-bot
Copy link

changeset-bot bot commented Nov 19, 2025

🦋 Changeset detected

Latest commit: c1a8504

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 5 packages
Name Type
@heroui/number-input Minor
@heroui/select Minor
@heroui/input Minor
@heroui/react Patch
@heroui/autocomplete Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link

vercel bot commented Nov 19, 2025

@deepansh946 is attempting to deploy a commit to the HeroUI Inc Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 19, 2025

Walkthrough

This PR makes isClearable explicit (no longer inferred from onClear) across Input and NumberInput, updates Escape-key clearing to require isClearable (and not read-only), adjusts a textarea test to expect no clear button when only onClear is provided, and updates select JSDoc. A changeset bumps three package versions.

Changes

Cohort / File(s) Summary
Tests
packages/components/input/__tests__/textarea.test.tsx
Updated test to assert the clear button is absent when only onClear is provided (switched from getByRole to queryByRole and updated description).
Input hooks
packages/components/input/src/use-input.ts
isClearable now computed as originalProps.isClearable ?? false (no implicit true when onClear exists); Escape key clearing now requires isClearable and non-readOnly. Minor JSDoc tweak.
NumberInput hooks
packages/components/number-input/src/use-number-input.ts
Same change as Input: isClearable set to originalProps.isClearable ?? false; Escape key clearing gated by isClearable and not readOnly.
Select docs
packages/components/select/src/use-select.ts
Removed one descriptive JSDoc line about onClear (doc-only change).
Changeset
.changeset/seven-monkeys-lay.md
Added changeset noting minor bumps for @heroui/number-input, @heroui/select, @heroui/input and a note: "fix isClearable implicit behaviour".

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Dev as Developer (props)
  participant Hook as useInput / useNumberInput
  participant UI as Component UI
  participant User as End user

  Dev->>Hook: pass props (isClearable?, onClear?, readOnly?)
  Note over Hook: compute isClearable = originalProps.isClearable ?? false
  Hook-->>UI: render (show clear button only if isClearable && !readOnly)
  User->>UI: press Clear button
  UI->>Hook: call onClear (if provided)
  User->>UI: press Escape
  alt isClearable && !readOnly
    UI->>Hook: handle Escape -> call onClear (if provided)
  else
    UI->>UI: ignore Escape for clearing
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Heterogeneous but focused changes across hooks, a test, docs, and a changeset.
  • Areas to pay extra attention:
    • use-input.ts and use-number-input.ts: ensure Escape handling and readOnly interplay is correct and covered by tests.
    • Test update: confirm it accurately reflects runtime behavior and doesn't introduce flakiness.
    • Regression risk where downstream code relied on implicit isClearable behavior.

Possibly related PRs

Suggested reviewers

  • jrgarciadev
  • wingkwong

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix: isClearable handling' clearly and concisely summarizes the main change: fixing the isClearable behavior to be explicit rather than implicit.
Description check ✅ Passed The description follows the template structure completely, includes issue closure, clear before/after examples, marks as breaking change, and provides detailed migration guidance.
Linked Issues check ✅ Passed All requirements from issue #5614 are met: isClearable now controlled by explicit prop only, onClear is callback-only, Escape key behavior updated, JSDoc comments revised, and similar fixes applied across Input, NumberInput, Select, and Textarea components.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing the isClearable implicit behavior across multiple components: Input, NumberInput, Select, and related documentation updates.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7e38529 and c4d5353.

📒 Files selected for processing (1)
  • .changeset/seven-monkeys-lay.md (1 hunks)
🔇 Additional comments (1)
.changeset/seven-monkeys-lay.md (1)

1-7: Changeset format and description look good.

The file follows the standard Changesets format correctly, with proper metadata section and clear description. All three affected packages (Input, NumberInput, Select) are included with "minor" version bumps, which is reasonable for a bug-fix that makes the API more explicit.

Note: This is technically a breaking change for code that relied on the implicit isClearable behavior. Ensure consumers are aware of the migration path documented in the PR objectives (adding isClearable={true} where needed).


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@deepansh946
Copy link
Contributor Author

@wingkwong I have fixed the isClearable implicit issue, please review it.

@vercel
Copy link

vercel bot commented Dec 27, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
heroui Ready Ready Preview, Comment Dec 27, 2025 10:02am
heroui-sb Ready Ready Preview, Comment Dec 27, 2025 10:02am

@pkg-pr-new
Copy link

pkg-pr-new bot commented Dec 27, 2025

Open in StackBlitz

@heroui/accordion

npm i https://pkg.pr.new/@heroui/accordion@5913

@heroui/alert

npm i https://pkg.pr.new/@heroui/alert@5913

@heroui/autocomplete

npm i https://pkg.pr.new/@heroui/autocomplete@5913

@heroui/avatar

npm i https://pkg.pr.new/@heroui/avatar@5913

@heroui/badge

npm i https://pkg.pr.new/@heroui/badge@5913

@heroui/breadcrumbs

npm i https://pkg.pr.new/@heroui/breadcrumbs@5913

@heroui/button

npm i https://pkg.pr.new/@heroui/button@5913

@heroui/calendar

npm i https://pkg.pr.new/@heroui/calendar@5913

@heroui/card

npm i https://pkg.pr.new/@heroui/card@5913

@heroui/checkbox

npm i https://pkg.pr.new/@heroui/checkbox@5913

@heroui/chip

npm i https://pkg.pr.new/@heroui/chip@5913

@heroui/code

npm i https://pkg.pr.new/@heroui/code@5913

@heroui/date-input

npm i https://pkg.pr.new/@heroui/date-input@5913

@heroui/date-picker

npm i https://pkg.pr.new/@heroui/date-picker@5913

@heroui/divider

npm i https://pkg.pr.new/@heroui/divider@5913

@heroui/drawer

npm i https://pkg.pr.new/@heroui/drawer@5913

@heroui/dropdown

npm i https://pkg.pr.new/@heroui/dropdown@5913

@heroui/form

npm i https://pkg.pr.new/@heroui/form@5913

@heroui/image

npm i https://pkg.pr.new/@heroui/image@5913

@heroui/input

npm i https://pkg.pr.new/@heroui/input@5913

@heroui/input-otp

npm i https://pkg.pr.new/@heroui/input-otp@5913

@heroui/kbd

npm i https://pkg.pr.new/@heroui/kbd@5913

@heroui/link

npm i https://pkg.pr.new/@heroui/link@5913

@heroui/listbox

npm i https://pkg.pr.new/@heroui/listbox@5913

@heroui/menu

npm i https://pkg.pr.new/@heroui/menu@5913

@heroui/modal

npm i https://pkg.pr.new/@heroui/modal@5913

@heroui/navbar

npm i https://pkg.pr.new/@heroui/navbar@5913

@heroui/number-input

npm i https://pkg.pr.new/@heroui/number-input@5913

@heroui/pagination

npm i https://pkg.pr.new/@heroui/pagination@5913

@heroui/popover

npm i https://pkg.pr.new/@heroui/popover@5913

@heroui/progress

npm i https://pkg.pr.new/@heroui/progress@5913

@heroui/radio

npm i https://pkg.pr.new/@heroui/radio@5913

@heroui/ripple

npm i https://pkg.pr.new/@heroui/ripple@5913

@heroui/scroll-shadow

npm i https://pkg.pr.new/@heroui/scroll-shadow@5913

@heroui/select

npm i https://pkg.pr.new/@heroui/select@5913

@heroui/skeleton

npm i https://pkg.pr.new/@heroui/skeleton@5913

@heroui/slider

npm i https://pkg.pr.new/@heroui/slider@5913

@heroui/snippet

npm i https://pkg.pr.new/@heroui/snippet@5913

@heroui/spacer

npm i https://pkg.pr.new/@heroui/spacer@5913

@heroui/spinner

npm i https://pkg.pr.new/@heroui/spinner@5913

@heroui/switch

npm i https://pkg.pr.new/@heroui/switch@5913

@heroui/table

npm i https://pkg.pr.new/@heroui/table@5913

@heroui/tabs

npm i https://pkg.pr.new/@heroui/tabs@5913

@heroui/toast

npm i https://pkg.pr.new/@heroui/toast@5913

@heroui/tooltip

npm i https://pkg.pr.new/@heroui/tooltip@5913

@heroui/user

npm i https://pkg.pr.new/@heroui/user@5913

@heroui/react

npm i https://pkg.pr.new/@heroui/react@5913

@heroui/system

npm i https://pkg.pr.new/@heroui/system@5913

@heroui/system-rsc

npm i https://pkg.pr.new/@heroui/system-rsc@5913

@heroui/theme

npm i https://pkg.pr.new/@heroui/theme@5913

@heroui/use-aria-accordion

npm i https://pkg.pr.new/@heroui/use-aria-accordion@5913

@heroui/use-aria-accordion-item

npm i https://pkg.pr.new/@heroui/use-aria-accordion-item@5913

@heroui/use-aria-button

npm i https://pkg.pr.new/@heroui/use-aria-button@5913

@heroui/use-aria-link

npm i https://pkg.pr.new/@heroui/use-aria-link@5913

@heroui/use-aria-modal-overlay

npm i https://pkg.pr.new/@heroui/use-aria-modal-overlay@5913

@heroui/use-aria-multiselect

npm i https://pkg.pr.new/@heroui/use-aria-multiselect@5913

@heroui/use-aria-overlay

npm i https://pkg.pr.new/@heroui/use-aria-overlay@5913

@heroui/use-callback-ref

npm i https://pkg.pr.new/@heroui/use-callback-ref@5913

@heroui/use-clipboard

npm i https://pkg.pr.new/@heroui/use-clipboard@5913

@heroui/use-data-scroll-overflow

npm i https://pkg.pr.new/@heroui/use-data-scroll-overflow@5913

@heroui/use-disclosure

npm i https://pkg.pr.new/@heroui/use-disclosure@5913

@heroui/use-draggable

npm i https://pkg.pr.new/@heroui/use-draggable@5913

@heroui/use-form-reset

npm i https://pkg.pr.new/@heroui/use-form-reset@5913

@heroui/use-image

npm i https://pkg.pr.new/@heroui/use-image@5913

@heroui/use-infinite-scroll

npm i https://pkg.pr.new/@heroui/use-infinite-scroll@5913

@heroui/use-intersection-observer

npm i https://pkg.pr.new/@heroui/use-intersection-observer@5913

@heroui/use-is-mobile

npm i https://pkg.pr.new/@heroui/use-is-mobile@5913

@heroui/use-is-mounted

npm i https://pkg.pr.new/@heroui/use-is-mounted@5913

@heroui/use-measure

npm i https://pkg.pr.new/@heroui/use-measure@5913

@heroui/use-pagination

npm i https://pkg.pr.new/@heroui/use-pagination@5913

@heroui/use-real-shape

npm i https://pkg.pr.new/@heroui/use-real-shape@5913

@heroui/use-ref-state

npm i https://pkg.pr.new/@heroui/use-ref-state@5913

@heroui/use-resize

npm i https://pkg.pr.new/@heroui/use-resize@5913

@heroui/use-safe-layout-effect

npm i https://pkg.pr.new/@heroui/use-safe-layout-effect@5913

@heroui/use-scroll-position

npm i https://pkg.pr.new/@heroui/use-scroll-position@5913

@heroui/use-ssr

npm i https://pkg.pr.new/@heroui/use-ssr@5913

@heroui/use-theme

npm i https://pkg.pr.new/@heroui/use-theme@5913

@heroui/use-update-effect

npm i https://pkg.pr.new/@heroui/use-update-effect@5913

@heroui/use-viewport-size

npm i https://pkg.pr.new/@heroui/use-viewport-size@5913

@heroui/aria-utils

npm i https://pkg.pr.new/@heroui/aria-utils@5913

@heroui/dom-animation

npm i https://pkg.pr.new/@heroui/dom-animation@5913

@heroui/framer-utils

npm i https://pkg.pr.new/@heroui/framer-utils@5913

@heroui/react-rsc-utils

npm i https://pkg.pr.new/@heroui/react-rsc-utils@5913

@heroui/react-utils

npm i https://pkg.pr.new/@heroui/react-utils@5913

@heroui/shared-icons

npm i https://pkg.pr.new/@heroui/shared-icons@5913

@heroui/shared-utils

npm i https://pkg.pr.new/@heroui/shared-utils@5913

@heroui/stories-utils

npm i https://pkg.pr.new/@heroui/stories-utils@5913

@heroui/test-utils

npm i https://pkg.pr.new/@heroui/test-utils@5913

commit: c1a8504

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] - Make isClearable behavior more explicit in Input

2 participants