Skip to content

Conversation

@hasegawa-101
Copy link
Contributor

@hasegawa-101 hasegawa-101 commented Nov 24, 2025

📝 Description

This PR fixes a bug in the Link component where the useHref function provided by the HeroUIProvider was not being correctly applied.

##⛳️ Current behavior (updates)
Currently, in the useLink hook, the props objects are merged in an incorrect order. Specifically, otherProps (containing the original href) is merged after linkProps (containing the href transformed by useHref). This causes the transformed href to be overridden by the original one, resulting in the useHref functionality not working as expected.

##🚀 New behavior
The order of arguments in the mergeProps function within the useLink hook (packages/components/link/src/use-link.ts) has been corrected. By merging linkProps last, we ensure that the correctly transformed href from the useHref function takes precedence and is applied to the final rendered tag. This resolves the bug and makes the Link component respect the useHref prop from the provider.

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

No

📝 Additional Information

Summary by CodeRabbit

  • Bug Fixes

    • Fixed an issue where provider-supplied href transformations were not consistently applied to links.
  • Tests

    • Added a test confirming provider-based href transformation is applied correctly.
  • Chores

    • Added a patch-release changeset entry for the link package documenting the fix.

✏️ Tip: You can customize this high-level summary in your review settings.

@changeset-bot
Copy link

changeset-bot bot commented Nov 24, 2025

🦋 Changeset detected

Latest commit: 3f8e426

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

This PR includes changesets to release 2 packages
Name Type
@heroui/link Patch
@heroui/react 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 24, 2025

@hasegawa-101 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 24, 2025

Walkthrough

Reorders prop merge in link logic so provider-generated href is preserved, adds a test that exercises HeroUIProvider's useHref, and adds a patch changeset for @heroui/link. No public API changes.

Changes

Cohort / File(s) Summary
Tests
packages/components/link/__tests__/link.test.tsx
Import HeroUIProvider and add test "should apply useHref from provider" that renders Link inside HeroUIProvider with a useHref function and asserts the rendered href is transformed.
Core fix
packages/components/link/src/use-link.ts
Reordered mergeProps call so linkProps (which contains the provider-transformed href) are not overwritten by later props: changed argument order to preserve linkProps.href.
Release metadata
.changeset/quick-pants-kick.md
Add a patch changeset for @heroui/link describing the fix for useHref not being applied (refs issue #5925).

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

  • Review focus:
    • Confirm mergeProps reorder doesn't unintentionally change merging of other keys (events, refs, accessibility props).
    • Validate the new test correctly exercises provider wiring and edge cases (absolute URLs, undefined useHref).
    • Ensure changeset metadata matches package/version intentions.

Suggested reviewers

  • jrgarciadev

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title directly and clearly summarizes the main fix: resolving the useHref functionality issue in the Link component.
Description check ✅ Passed The description covers all required sections: issue reference, current behavior explanation, new behavior details, breaking change status, and follows the template structure comprehensively.
Linked Issues check ✅ Passed The PR changes directly address all three linked issues by reordering mergeProps arguments so linkProps (with useHref-transformed href) is merged last, preventing otherProps from overwriting it.
Out of Scope Changes check ✅ Passed All changes are scoped to fixing the identified bug: test additions for useHref functionality, mergeProps argument reordering in useLink, and a changeset entry documenting the patch.
✨ 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 80e4209 and 3f8e426.

📒 Files selected for processing (1)
  • .changeset/quick-pants-kick.md (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • .changeset/quick-pants-kick.md
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: TypeScript
  • GitHub Check: Continuous Release
  • GitHub Check: Build

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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 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 8b2ec9f and 9312f8c.

📒 Files selected for processing (2)
  • packages/components/link/__tests__/link.test.tsx (2 hunks)
  • packages/components/link/src/use-link.ts (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Prettier
  • GitHub Check: Continuous Release
  • GitHub Check: ESLint
  • GitHub Check: TypeScript
  • GitHub Check: Build
  • GitHub Check: Tests
🔇 Additional comments (2)
packages/components/link/__tests__/link.test.tsx (1)

6-6: LGTM!

The import of HeroUIProvider is correct and necessary for testing provider-driven useHref behavior.

packages/components/link/src/use-link.ts (1)

113-113: The merge order change is correct and poses no risk to isExternal behavior.

React Aria's useLinkProps does not auto-set rel or target attributes, so linkProps returned from useAriaLink will not contain these properties. When isExternal is true, rel and target are set on otherProps (lines 91-94), and with the new merge order where otherProps precedes linkProps, the isExternal values will apply correctly since linkProps has no conflicting properties. The existing test confirms this behavior continues to work as expected.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Nov 24, 2025

Open in StackBlitz

@heroui/accordion

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

@heroui/alert

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

@heroui/autocomplete

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

@heroui/avatar

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

@heroui/badge

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

@heroui/breadcrumbs

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

@heroui/button

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

@heroui/calendar

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

@heroui/card

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

@heroui/checkbox

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

@heroui/chip

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

@heroui/code

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

@heroui/date-input

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

@heroui/date-picker

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

@heroui/divider

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

@heroui/drawer

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

@heroui/dropdown

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

@heroui/form

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

@heroui/image

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

@heroui/input

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

@heroui/input-otp

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

@heroui/kbd

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

@heroui/link

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

@heroui/listbox

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

@heroui/menu

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

@heroui/modal

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

@heroui/navbar

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

@heroui/number-input

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

@heroui/pagination

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

@heroui/popover

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

@heroui/progress

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

@heroui/radio

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

@heroui/ripple

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

@heroui/scroll-shadow

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

@heroui/select

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

@heroui/skeleton

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

@heroui/slider

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

@heroui/snippet

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

@heroui/spacer

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

@heroui/spinner

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

@heroui/switch

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

@heroui/table

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

@heroui/tabs

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

@heroui/toast

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

@heroui/tooltip

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

@heroui/user

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

@heroui/react

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

@heroui/system

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

@heroui/system-rsc

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

@heroui/theme

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

@heroui/use-aria-accordion

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

@heroui/use-aria-accordion-item

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

@heroui/use-aria-button

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

@heroui/use-aria-link

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

@heroui/use-aria-modal-overlay

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

@heroui/use-aria-multiselect

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

@heroui/use-aria-overlay

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

@heroui/use-callback-ref

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

@heroui/use-clipboard

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

@heroui/use-data-scroll-overflow

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

@heroui/use-disclosure

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

@heroui/use-draggable

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

@heroui/use-form-reset

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

@heroui/use-image

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

@heroui/use-infinite-scroll

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

@heroui/use-intersection-observer

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

@heroui/use-is-mobile

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

@heroui/use-is-mounted

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

@heroui/use-measure

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

@heroui/use-pagination

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

@heroui/use-real-shape

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

@heroui/use-ref-state

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

@heroui/use-resize

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

@heroui/use-safe-layout-effect

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

@heroui/use-scroll-position

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

@heroui/use-ssr

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

@heroui/use-theme

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

@heroui/use-update-effect

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

@heroui/use-viewport-size

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

@heroui/aria-utils

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

@heroui/dom-animation

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

@heroui/framer-utils

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

@heroui/react-rsc-utils

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

@heroui/react-utils

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

@heroui/shared-icons

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

@heroui/shared-utils

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

@heroui/stories-utils

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

@heroui/test-utils

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

commit: 3f8e426

@wingkwong wingkwong self-assigned this Nov 24, 2025
@wingkwong wingkwong added this to the v2.8.6 milestone Nov 24, 2025
@vercel
Copy link

vercel bot commented Nov 24, 2025

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

Project Deployment Preview Comments Updated (UTC)
heroui Ready Ready Preview Comment Nov 28, 2025 10:28am
heroui-sb Ready Ready Preview Comment Nov 28, 2025 10:28am

Copy link
Member

@wingkwong wingkwong left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using this PR build https://pkg.pr.new/@heroui/react@5933 on the reproducible environment seems not able to produce correct result. Could you please take a look again?

@hasegawa-101
Copy link
Contributor Author

@wingkwong pushed the fix! Please check it again when you have a moment.

@hasegawa-101 hasegawa-101 changed the title fix(link): correct props merge order in use-link to apply useHref fix(link): resolve issue where useHref is not working correctly Nov 24, 2025
@wingkwong
Copy link
Member

@hasegawa-101 are you using this example to test? I downloaded it to my local and tried with "@heroui/react": "https://pkg.pr.new/@heroui/react@5933". The issue is still reproducible.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 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 819781e and 81e5f7b.

📒 Files selected for processing (1)
  • packages/hooks/use-aria-link/src/index.ts (2 hunks)
🧰 Additional context used
🪛 Biome (2.1.2)
packages/hooks/use-aria-link/src/index.ts

[error] 71-71: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: TypeScript
  • GitHub Check: Continuous Release
  • GitHub Check: ESLint
  • GitHub Check: Build
🔇 Additional comments (2)
packages/hooks/use-aria-link/src/index.ts (2)

83-83: Change is consistent with the href preprocessing approach.

Using processedHref instead of props.href in handleLinkClick is logically consistent with the approach taken on lines 71-72. This ensures the click handler operates on the transformed href value.

However, this depends on the critical issue on line 71 being resolved first.


71-72: Verify fix effectiveness and completeness of PR changes.

The available information indicates potential issues with this fix:

  1. Tester reported issue still reproducible: According to PR comments, @wingkwong confirmed the issue persists after these changes, suggesting the fix is incomplete or ineffective.

  2. Conditional hook violation on line 71: The code router.useHref ? router.useHref(props.href) violates React hooks rules. Hooks must be called unconditionally in every render, but this conditionally calls router.useHref() only if it exists. This pattern will cause the Rules of Hooks to fail if router.useHref availability changes between renders.

  3. Unclear scope of PR changes: The PR objectives mention the root cause is incorrect mergeProps order in packages/components/link/src/use-link.ts, but we cannot confirm whether that file was actually modified in this PR or whether both files needed changes.

Before approving, manually confirm:

  • Whether packages/components/link/src/use-link.ts was modified and what the original mergeProps order was
  • Whether both files require changes or if one fix alone is sufficient
  • Whether the conditional hook pattern on line 71 should be refactored to avoid violating React hooks rules
  • Whether the reported issue can be reproduced after these changes

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/components/link/__tests__/link.test.tsx (1)

89-100: Good test coverage for the useHref fix.

The test correctly validates that the provider's useHref function transforms the href attribute. The use of getAttribute("href") appropriately checks the attribute value rather than the resolved URL.

Consider optionally enhancing this test to also verify that click navigation uses the transformed href (i.e., that the mocked navigate function receives "/example/test" when the link is clicked), which would provide more comprehensive coverage of the fix described in line 82 of packages/hooks/use-aria-link/src/index.ts.

Example enhancement:

  it("should apply useHref from provider", () => {
    const useHref = (href: string) => `/example${href}`;
+   const navigate = jest.fn();

    const {getByRole} = render(
-     <HeroUIProvider navigate={jest.fn()} useHref={useHref}>
+     <HeroUIProvider navigate={navigate} useHref={useHref}>
        <Link href="/test">Test Link</Link>
      </HeroUIProvider>,
    );
    const link = getByRole("link");

    expect(link.getAttribute("href")).toBe("/example/test");
+
+   // Optionally verify click navigation uses transformed href
+   // await user.click(link);
+   // expect(navigate).toHaveBeenCalledWith(expect.stringContaining("/example/test"));
  });
📜 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 de053f8 and 19cc9a3.

📒 Files selected for processing (2)
  • packages/components/link/__tests__/link.test.tsx (2 hunks)
  • packages/hooks/use-aria-link/src/index.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/components/link/__tests__/link.test.tsx (2)
packages/components/link/src/index.ts (1)
  • Link (13-13)
packages/core/theme/src/components/link.ts (1)
  • link (111-111)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: TypeScript
  • GitHub Check: Build
  • GitHub Check: ESLint
  • GitHub Check: Continuous Release
🔇 Additional comments (2)
packages/hooks/use-aria-link/src/index.ts (1)

82-82: LGTM! Click handler now uses the provider-transformed href.

The change ensures that the click handler uses routerLinkProps.href (which includes any transformation from the provider's useHref) instead of the original props.href. This aligns the navigation behavior with the rendered anchor href, fixing the issue where the provider's useHref was not being respected during link clicks.

packages/components/link/__tests__/link.test.tsx (1)

6-6: Import is appropriate for testing provider functionality.

The HeroUIProvider import is necessary for the new test case that validates the useHref transformation from the provider.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/core/system/src/provider-context.ts (1)

94-97: Minor typo in the JSDoc comment.

The comment contains "href" with backticks and spaces. It should likely be either href (code format) or "href" (plain text) for consistency.

  /**
-  * Convert a ` href ` provided to a link component to a native `href`.
+  * Convert an `href` provided to a link component to a native `href`.
   */
  useHref?: (href: Href) => string;
📜 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 19cc9a3 and 2c1f49a.

📒 Files selected for processing (3)
  • packages/components/link/src/use-link.ts (2 hunks)
  • packages/core/system/src/provider-context.ts (2 hunks)
  • packages/core/system/src/provider.tsx (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/components/link/src/use-link.ts (2)
packages/core/system/src/index.ts (1)
  • mapPropsVariants (24-24)
packages/core/theme/src/components/link.ts (1)
  • link (111-111)
🪛 Biome (2.1.2)
packages/components/link/src/use-link.ts

[error] 49-49: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: TypeScript
  • GitHub Check: Continuous Release
  • GitHub Check: Build
🔇 Additional comments (6)
packages/components/link/src/use-link.ts (4)

47-50: LGTM! Proper early href transformation.

The logic correctly applies the provider's useHref transformation when available, with appropriate null checks for both the function and the href prop. This ensures the transformed href flows through the rest of the hook.


52-52: LGTM! Using resolved props for variant mapping.

Correctly uses resolvedProps to ensure variant mapping is based on the transformed href rather than the original.


117-117: LGTM! Correct merge order preserves transformed href.

This is the key fix: by placing linkProps last in the merge, the href processed by React Aria (which includes the provider's useHref transformation) now takes precedence over otherProps, preventing the original href from overriding the transformed value. This directly addresses the root cause described in the PR objectives.


47-50: Dismiss static analysis false positive.

The Biome warning about "hook being called conditionally" is a false positive. The code is calling globalContext.useHref(...), which is a regular function property, not a React hook. The conditional check globalContext?.useHref && originalProps.href is simply null-safety for calling the function, which is perfectly valid. The linter is misidentifying this as a hook call due to the "use" prefix in the name.

packages/core/system/src/provider.tsx (2)

42-49: LGTM! Clear documentation for useHref prop.

The JSDoc clearly explains the purpose of useHref and how it complements the navigate function, providing good context for users of the provider.


56-56: LGTM! Complete wiring of useHref through provider.

The implementation correctly:

  • Destructures useHref from props (line 56)
  • Passes it to React Aria's RouterProvider (line 74)
  • Includes it in the provider context value (line 93)
  • Adds it to the memoization dependency array (line 104)

This properly propagates useHref to all consumers, enabling the fix in use-link.ts.

Also applies to: 74-74, 93-93, 104-104

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 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 2c1f49a and 94c3a1a.

📒 Files selected for processing (1)
  • packages/components/link/__tests__/link.test.tsx (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: TypeScript
  • GitHub Check: Continuous Release
  • GitHub Check: Build

@wingkwong
Copy link
Member

@hasegawa-101 lemme know once it is ready for review again. make sure you've tested it on that example first.

@hasegawa-101
Copy link
Contributor Author

@wingkwong Thanks. I've verified it in the codesandobox environment. Please review it again 🙏

https://codesandbox.io/p/github/hasegawa-101/sparkling-frog/main

@wingkwong
Copy link
Member

@hasegawa-101 the sandbox is not running

image

@hasegawa-101
Copy link
Contributor Author

@wingkwong
Sorry for the back and forth. Could you please check it here?
https://stackblitz.com/~/github.com/hasegawa-101/sparkling-frog

2025-11-25.16.15.27.mov

@hasegawa-101
Copy link
Contributor Author

hasegawa-101 commented Nov 25, 2025

@wingkwong

Thanks for the feedback. I've reviewed the react-spectrum implementation as suggested.

You are correct that useLinkProps handles href transformation via useHref. However, there is an important structural dependency regarding HeroUIProvider.

Currently, HeroUIProvider allows setting useHref without navigate. In that case, RouterProvider is not rendered, so the transformation logic is not applied. The resolvedProps logic was added specifically to support this scenario where a user provides only useHref without navigate.

If we aim to align with the react-spectrum implementation, I believe we would need to require navigate to be set whenever useHref is used, rather than allowing useHref to be set independently.

I'd love to hear your thoughts on this 🙏

@wingkwong
Copy link
Member

@hasegawa-101 thanks for the findings. Lemme take a look when I got more time later.

@wingkwong wingkwong self-requested a review November 25, 2025 16:32
@wingkwong
Copy link
Member

I also checked their implementation and compared ours. The expected behaviour is that navigate is required in order to use RouterProvider and useHref is optional along with it, meaning we cannot purely use useHref alone without navigate. So the existing design is correct.

However, from those 2 linked issues, they also include navigate and useHref. In such case it should work without this PR changes. May need to investigate why here. In case you need a faster communication or discussion, free feel to DM me at discord (same user ID).

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

Labels

None yet

Projects

None yet

2 participants