Skip to content

fix(hover-card): keep open while trigger remains focused - #3227

Open
aose-yuu wants to merge 2 commits into
chakra-ui:mainfrom
aose-yuu:fix/hover-card-pointer-leave-with-focus
Open

fix(hover-card): keep open while trigger remains focused#3227
aose-yuu wants to merge 2 commits into
chakra-ui:mainfrom
aose-yuu:fix/hover-card-pointer-leave-with-focus

Conversation

@aose-yuu

Copy link
Copy Markdown
Contributor

Closes #3224

📝 Description

Keep a hover card open when the pointer leaves a trigger that still has keyboard focus.

⛳️ Current behavior (updates)

Moving the pointer away starts closing the hover card even when its trigger remains focused.

🚀 New behavior

Pointer leave no longer closes the hover card while the trigger is focused. Pointer state is cleared so the card still closes when focus later leaves the trigger, and an end-to-end test covers both parts of the interaction.

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

No.

📝 Additional Information

#3209 changes the same pointer-leave transition, so this branch may need a small rebase if that PR lands first.

@vercel

vercel Bot commented Jul 25, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
zag-nextjs Ready Ready Preview Aug 2, 2026 5:37pm
zag-solid Ready Ready Preview Aug 2, 2026 5:37pm
zag-svelte Ready Ready Preview Aug 2, 2026 5:37pm
zag-vue Ready Ready Preview Aug 2, 2026 5:37pm
zag-website Ready Ready Preview Aug 2, 2026 5:37pm

Request Review

@changeset-bot

changeset-bot Bot commented Jul 25, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 18af8fb

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

This PR includes changesets to release 86 packages
Name Type
@zag-js/hover-card Patch
@zag-js/anatomy-icons Patch
@zag-js/anatomy Patch
@zag-js/core Patch
@zag-js/docs Patch
@zag-js/preact Patch
@zag-js/react Patch
@zag-js/solid Patch
@zag-js/svelte Patch
@zag-js/vanilla Patch
@zag-js/vue Patch
@zag-js/accordion Patch
@zag-js/angle-slider Patch
@zag-js/async-list Patch
@zag-js/avatar Patch
@zag-js/carousel Patch
@zag-js/cascade-select Patch
@zag-js/checkbox Patch
@zag-js/clipboard Patch
@zag-js/collapsible Patch
@zag-js/color-picker Patch
@zag-js/combobox Patch
@zag-js/date-input Patch
@zag-js/date-picker Patch
@zag-js/dialog Patch
@zag-js/drawer Patch
@zag-js/editable Patch
@zag-js/file-upload Patch
@zag-js/floating-panel Patch
@zag-js/image-cropper Patch
@zag-js/listbox Patch
@zag-js/marquee Patch
@zag-js/menu Patch
@zag-js/navigation-menu Patch
@zag-js/number-input Patch
@zag-js/pagination Patch
@zag-js/password-input Patch
@zag-js/pin-input Patch
@zag-js/popover Patch
@zag-js/presence Patch
@zag-js/progress Patch
@zag-js/qr-code Patch
@zag-js/radio-group Patch
@zag-js/rating-group Patch
@zag-js/scroll-area Patch
@zag-js/select Patch
@zag-js/signature-pad Patch
@zag-js/slider Patch
@zag-js/splitter Patch
@zag-js/steps Patch
@zag-js/switch Patch
@zag-js/tabs Patch
@zag-js/tags-input Patch
@zag-js/timer Patch
@zag-js/toast Patch
@zag-js/toc Patch
@zag-js/toggle-group Patch
@zag-js/toggle Patch
@zag-js/tooltip Patch
@zag-js/tour Patch
@zag-js/tree-view Patch
@zag-js/store Patch
@zag-js/types Patch
@zag-js/aria-hidden Patch
@zag-js/auto-resize Patch
@zag-js/collection Patch
@zag-js/color-utils Patch
@zag-js/utils Patch
@zag-js/date-utils Patch
@zag-js/dismissable Patch
@zag-js/dom-query Patch
@zag-js/file-utils Patch
@zag-js/focus-trap Patch
@zag-js/focus-visible Patch
@zag-js/highlight-word Patch
@zag-js/hotkeys Patch
@zag-js/i18n-utils Patch
@zag-js/interact-outside Patch
@zag-js/json-tree-utils Patch
@zag-js/live-region Patch
@zag-js/popper Patch
@zag-js/rect-utils Patch
@zag-js/remove-scroll Patch
@zag-js/scroll-snap Patch
@zag-js/stringify-state Patch
svelte-kit-starter 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

@kalisaNkevin

Copy link
Copy Markdown
Member

Nice fix, and pretty minimal. The clever bit is it doesn't need a new closing path — clearing isPointer on the focused-trigger POINTER_LEAVE is enough, because the open state's existing TRIGGER_BLUR handler already checks not(isPointer) to decide whether to close. So once focus actually leaves the trigger later, that existing logic just takes over and closes it normally. No new states, no extra bookkeeping.

I also checked how this holds up for the multi-trigger setup, since the guard reads context.get("triggerValue") to resolve the active trigger rather than just checking "is anything focused" — so it should only suppress closing for the specific trigger currently driving the open card, not any trigger on the page. That looks right by inspection, though there's no test covering the multi-trigger + focus combo specifically (hover-card-multiple-trigger.e2e.ts wasn't touched), so worth a manual sanity check there.

Changeset and e2e test are both present and read fine. Same CI situation as the last three though — one workflow run, action_required, so nothing's actually been verified yet until a maintainer approves it.

@aose-yuu

aose-yuu commented Aug 2, 2026

Copy link
Copy Markdown
Contributor Author

I added coverage for this in 18af8fb.

The new test focuses the second trigger, moves the pointer away, and checks that the card stays open.
It also checks that the card closes once the trigger loses focus.

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.

HoverCard closes on pointer leave while the trigger remains focused

2 participants