diff --git a/.changeset/curvy-eels-tap.md b/.changeset/curvy-eels-tap.md
new file mode 100644
index 0000000000..8da319b07f
--- /dev/null
+++ b/.changeset/curvy-eels-tap.md
@@ -0,0 +1,5 @@
+---
+"@nextui-org/system": patch
+---
+
+Fix missing `useHref` logic (#2934)
diff --git a/apps/docs/content/docs/guide/routing.mdx b/apps/docs/content/docs/guide/routing.mdx
index 8f818ce3a2..88875c18bc 100644
--- a/apps/docs/content/docs/guide/routing.mdx
+++ b/apps/docs/content/docs/guide/routing.mdx
@@ -17,7 +17,7 @@ component configures all NextUI components within it to navigate using the clien
Set this up once in the root of your app, and any NextUI component with the href prop will automatically navigate
using your router.
-### NextUIProvider Setup
+## NextUIProvider Setup
The `NextUIProvider` accepts a prop called `navigate`. This should be set to a function received from your
router for performing a client side navigation programmatically. The following example shows the general
@@ -43,9 +43,9 @@ function App() {
-### Next.js
+## Next.js
-#### App Router
+### App Router
Go to your `app/providers.tsx` or `app/providers.jsx` (create it if it doesn't exist) and add the
`useRouter` hook from `next/navigation`, it returns a router object that can be used to perform navigation.
@@ -95,15 +95,49 @@ export default function RootLayout({children}: { children: React.ReactNode }) {
> **Note**: Skip this step if you already set up the `NextUIProvider` in your app.
+#### Add useHref (Optional)
+
+If you are using the Next.js [basePath](https://nextjs.org/docs/app/api-reference/next-config-js/basePath) setting, you'll need to configure an environment variable to access it.
+
+```js
+// next.config.js
+const basePath = '...';
+const nextConfig = {
+ basePath,
+ env: {
+ BASE_PATH: basePath
+ }
+};
+```
+Then, provide a custom `useHref` function to prepend it to the href for all links.
+
+```tsx {9,12}
+// app/providers.tsx
+'use client'
+
+import {NextUIProvider} from '@nextui-org/react';
+import {useRouter} from 'next/navigation'
+
+export function Providers({children}: { children: React.ReactNode }) {
+ const router = useRouter();
+ const useHref = (href: string) => process.env.BASE_PATH + href;
+
+ return (
+
+ {children}
+
+ )
+}
+```
+
-#### Pages Router
+### Pages Router
Go to pages`/_app.js` or `pages/_app.tsx` (create it if it doesn't exist) and add the`useRouter` hook
from `next/router`, it returns a router object that can be used to perform navigation.
-
-```tsx {7}
+```tsx {7,10}
// pages/_app.tsx
import type { AppProps } from 'next/app';
import {NextUIProvider} from '@nextui-org/react';
@@ -122,23 +156,47 @@ function MyApp({ Component, pageProps }: AppProps) {
export default MyApp;
```
-### React Router
+When using the [basePath](https://nextjs.org/docs/app/api-reference/next-config-js/basePath) configuration option, provide a `useHref` option to the router passed to Provider to prepend it to links automatically.
+
+```tsx {8,11}
+// pages/_app.tsx
+import type { AppProps } from 'next/app';
+import {NextUIProvider} from '@nextui-org/react';
+import {useRouter} from 'next/router';
+
+function MyApp({ Component, pageProps }: AppProps) {
+ const router = useRouter();
+ const useHref = (href: string) => router.basePath + href;
+
+ return (
+
+
+
+ )
+}
+
+export default MyApp;
+```
+
+## React Router
-The `useNavigate` hook from `react-router-dom` returns a `navigate` function that can be used to perform navigation.
+The `useNavigate` hook from `react-router-dom` returns a `navigate` function that can be used to perform navigation.
+
+The `useHref` hook can also be provided if you're using React Router's `basename` option. Ensure that the component that calls useNavigate and renders Provider is inside the router component (e.g. `BrowserRouter`) so that it has access to React Router's internal context. The React Router `` element should also be defined inside `` so that links inside the rendered routes have access to the router.
Go to the `App` file commonly called `App.jsx` or `App.tsx`, add the `useNavigate` hook and pass the
`navigate` function to the `NextUIProvider`:
```jsx {6,9}
// App.tsx or App.jsx
-import {BrowserRouter, useNavigate} from 'react-router-dom';
+import {BrowserRouter, useNavigate, useHref} from 'react-router-dom';
import {NextUIProvider} from '@nextui-org/react';
function App() {
const navigate = useNavigate();
return (
-
+
{/* Your app here... */}
} />
@@ -164,17 +222,16 @@ component (e.g. `BrowserRouter`) so that it has access to React Router's interna
element should also be defined inside `NextUIProvider` so that links inside the rendered routes have access
to the router.
+## Remix
-### Remix
-
-Remix uses React Router under the hood, so the same `useNavigate` hook described above also works in Remix
+Remix uses React Router under the hood, so the same `useNavigate` and `useHref` hook described above also works in Remix
apps. `NextUIProvider` should be rendered at the `root` of each page that includes NextUI components, or in
`app/root.tsx` to add it to all pages. See the [Remix docs](https://remix.run/docs/en/main/file-conventions/root)
for more details.
```jsx {14}
// app/root.tsx
-import {useNavigate, Outlet} from '@remix-run/react';
+import {useNavigate, useHref, Outlet} from '@remix-run/react';
import {NextUIProvider} from '@nextui-org/react';
export default function App() {
@@ -186,7 +243,7 @@ export default function App() {
{/* ... */}
-
+
{/* ... */}
@@ -196,8 +253,7 @@ export default function App() {
}
```
-
-### TanStack
+## TanStack
To use [TanStack Router](https://tanstack.com/router/latest) with NextUI, render NextUI's RouterProvider inside your root route. Use `router.navigate` in the `navigate` prop, and `router.buildLocation` in the `useHref` prop.
@@ -219,8 +275,7 @@ function RootRoute() {
}
```
-
-### Usage examples
+## Usage examples
Now that you have set up the `NextUIProvider` in your app, you can use the `href` prop in the `Tabs`,
`Listbox` and `Dropdown` items to navigate between pages.
diff --git a/packages/core/system/src/provider.tsx b/packages/core/system/src/provider.tsx
index 4d92569476..1c10249c7b 100644
--- a/packages/core/system/src/provider.tsx
+++ b/packages/core/system/src/provider.tsx
@@ -1,5 +1,6 @@
import type {ModalProviderProps} from "@react-aria/overlays";
import type {ProviderContextProps} from "./provider-context";
+import type {Href} from "@react-types/shared";
import {I18nProvider, I18nProviderProps} from "@react-aria/i18n";
import {RouterProvider} from "@react-aria/utils";
@@ -31,11 +32,20 @@ export interface NextUIProviderProps
* Link, Menu, Tabs, Table, etc.
*/
navigate?: (path: string) => void;
+ /**
+ * Convert an `href` provided to a link component to a native `href`
+ * For example, a router might accept hrefs relative to a base path,
+ * or offer additional custom ways of specifying link destinations.
+ * The original href specified on the link is passed to the navigate function of the RouterProvider,
+ * and useHref is used to generate the full native href to put on the actual DOM element.
+ */
+ useHref?: (href: Href) => string;
}
export const NextUIProvider: React.FC = ({
children,
navigate,
+ useHref,
disableAnimation = false,
disableRipple = false,
skipFramerMotionAnimations = disableAnimation,
@@ -50,7 +60,11 @@ export const NextUIProvider: React.FC = ({
let contents = children;
if (navigate) {
- contents = {contents};
+ contents = (
+
+ {contents}
+
+ );
}
const context = useMemo(() => {