diff --git a/packages/next/src/views/Versions/cells/CreatedAt/index.tsx b/packages/next/src/views/Versions/cells/CreatedAt/index.tsx
index 0b5e6bc941..9bee7ca9c5 100644
--- a/packages/next/src/views/Versions/cells/CreatedAt/index.tsx
+++ b/packages/next/src/views/Versions/cells/CreatedAt/index.tsx
@@ -1,11 +1,8 @@
'use client'
-import { useConfig, useTranslation } from '@payloadcms/ui'
+import { Link, useConfig, useTranslation } from '@payloadcms/ui'
import { formatAdminURL, formatDate } from '@payloadcms/ui/shared'
-import LinkImport from 'next/link.js'
import React from 'react'
-const Link = (LinkImport.default || LinkImport) as unknown as typeof LinkImport.default
-
type CreatedAtCellProps = {
collectionSlug?: string
docID?: number | string
diff --git a/packages/plugin-search/src/Search/ui/LinkToDoc/index.client.tsx b/packages/plugin-search/src/Search/ui/LinkToDoc/index.client.tsx
index 39dd16ad8e..b3960fd24f 100644
--- a/packages/plugin-search/src/Search/ui/LinkToDoc/index.client.tsx
+++ b/packages/plugin-search/src/Search/ui/LinkToDoc/index.client.tsx
@@ -1,12 +1,9 @@
'use client'
-import { CopyToClipboard, useConfig, useField } from '@payloadcms/ui'
+import { CopyToClipboard, Link, useConfig, useField } from '@payloadcms/ui'
import { formatAdminURL } from '@payloadcms/ui/shared'
-import LinkImport from 'next/link.js'
import React from 'react'
-const Link = (LinkImport.default || LinkImport) as unknown as typeof LinkImport.default
-
export const LinkToDocClient: React.FC = () => {
const { config } = useConfig()
diff --git a/packages/richtext-lexical/src/cell/rscEntry.tsx b/packages/richtext-lexical/src/cell/rscEntry.tsx
index 11790ada18..7ecec35bee 100644
--- a/packages/richtext-lexical/src/cell/rscEntry.tsx
+++ b/packages/richtext-lexical/src/cell/rscEntry.tsx
@@ -2,15 +2,13 @@ import type { SerializedLexicalNode } from 'lexical'
import type { Payload } from 'payload'
import { getTranslation, type I18nClient } from '@payloadcms/translations'
+import { Link } from '@payloadcms/ui'
import { formatAdminURL } from '@payloadcms/ui/shared'
-import LinkImport from 'next/link.js'
import React from 'react'
import type { SanitizedServerEditorConfig } from '../lexical/config/types.js'
import type { LexicalFieldAdminProps, LexicalRichTextCellProps } from '../types.js'
-const Link = (LinkImport.default || LinkImport) as unknown as typeof LinkImport.default
-
function recurseEditorState(
editorState: SerializedLexicalNode[],
textContent: React.ReactNode[],
diff --git a/packages/richtext-slate/src/cell/rscEntry.tsx b/packages/richtext-slate/src/cell/rscEntry.tsx
index 26e52614d0..3bc44aff75 100644
--- a/packages/richtext-slate/src/cell/rscEntry.tsx
+++ b/packages/richtext-slate/src/cell/rscEntry.tsx
@@ -1,12 +1,10 @@
import type { DefaultServerCellComponentProps, Payload } from 'payload'
import { getTranslation, type I18nClient } from '@payloadcms/translations'
+import { Link } from '@payloadcms/ui'
import { formatAdminURL } from '@payloadcms/ui/shared'
-import LinkImport from 'next/link.js'
import React from 'react'
-const Link = (LinkImport.default || LinkImport) as unknown as typeof LinkImport.default
-
export const RscEntrySlateCell: React.FC<
{
i18n: I18nClient
diff --git a/packages/ui/src/elements/AppHeader/index.tsx b/packages/ui/src/elements/AppHeader/index.tsx
index e92f90e1da..65f272bc70 100644
--- a/packages/ui/src/elements/AppHeader/index.tsx
+++ b/packages/ui/src/elements/AppHeader/index.tsx
@@ -1,5 +1,4 @@
'use client'
-import LinkWithDefault from 'next/link.js'
import React, { useEffect, useRef, useState } from 'react'
import { Account } from '../../graphics/Account/index.js'
@@ -8,13 +7,14 @@ import { useConfig } from '../../providers/Config/index.js'
import { useTranslation } from '../../providers/Translation/index.js'
import { formatAdminURL } from '../../utilities/formatAdminURL.js'
import { Hamburger } from '../Hamburger/index.js'
+import { Link } from '../Link/index.js'
import { Localizer } from '../Localizer/index.js'
import { LocalizerLabel } from '../Localizer/LocalizerLabel/index.js'
import { useNav } from '../Nav/context.js'
import { NavToggler } from '../Nav/NavToggler/index.js'
import { RenderCustomComponent } from '../RenderCustomComponent/index.js'
-import { StepNav } from '../StepNav/index.js'
import './index.scss'
+import { StepNav } from '../StepNav/index.js'
const baseClass = 'app-header'
@@ -59,8 +59,6 @@ export function AppHeader({ CustomAvatar, CustomIcon }: Props) {
}
}, [Actions])
- const Link = LinkWithDefault.default
-
const LinkElement = Link || 'a'
const ActionComponents = Actions ? Object.values(Actions) : []
diff --git a/packages/ui/src/elements/Banner/index.tsx b/packages/ui/src/elements/Banner/index.tsx
index d694aeff2e..9d991344c7 100644
--- a/packages/ui/src/elements/Banner/index.tsx
+++ b/packages/ui/src/elements/Banner/index.tsx
@@ -1,12 +1,10 @@
'use client'
import type { MouseEvent } from 'react'
-import LinkImport from 'next/link.js' // TODO: abstract this out to support all routers
import React from 'react'
import './index.scss'
-
-const Link = (LinkImport.default || LinkImport) as unknown as typeof LinkImport.default
+import { Link } from '../Link/index.js'
const baseClass = 'banner'
diff --git a/packages/ui/src/elements/BulkUpload/EditForm/index.tsx b/packages/ui/src/elements/BulkUpload/EditForm/index.tsx
index 1a95d3ae6b..3cc517d09e 100644
--- a/packages/ui/src/elements/BulkUpload/EditForm/index.tsx
+++ b/packages/ui/src/elements/BulkUpload/EditForm/index.tsx
@@ -13,6 +13,7 @@ import { useDocumentEvents } from '../../../providers/DocumentEvents/index.js'
import { useDocumentInfo } from '../../../providers/DocumentInfo/index.js'
import { useEditDepth } from '../../../providers/EditDepth/index.js'
import { OperationProvider } from '../../../providers/Operation/index.js'
+import { useRouteTransition } from '../../../providers/RouteTransition/index.js'
import { useServerFunctions } from '../../../providers/ServerFunctions/index.js'
import { useUploadEdits } from '../../../providers/UploadEdits/index.js'
import { abortAndIgnore, handleAbortRef } from '../../../utilities/abortAndIgnore.js'
@@ -62,6 +63,7 @@ export function EditForm({ submitted }: EditFormProps) {
const params = useSearchParams()
const { reportUpdate } = useDocumentEvents()
const { resetUploadEdits } = useUploadEdits()
+ const { startRouteTransition } = useRouteTransition()
const locale = params.get('locale')
@@ -89,7 +91,8 @@ export function EditForm({ submitted }: EditFormProps) {
adminRoute,
path: `/collections/${collectionSlug}/${json?.doc?.id}${locale ? `?locale=${locale}` : ''}`,
})
- router.push(redirectRoute)
+
+ startRouteTransition(() => router.push(redirectRoute))
} else {
resetUploadEdits()
}
@@ -104,6 +107,7 @@ export function EditForm({ submitted }: EditFormProps) {
reportUpdate,
resetUploadEdits,
router,
+ startRouteTransition,
],
)
diff --git a/packages/ui/src/elements/CopyLocaleData/index.tsx b/packages/ui/src/elements/CopyLocaleData/index.tsx
index 995a0bb5d7..1057fbbade 100644
--- a/packages/ui/src/elements/CopyLocaleData/index.tsx
+++ b/packages/ui/src/elements/CopyLocaleData/index.tsx
@@ -12,13 +12,14 @@ import { useFormModified } from '../../forms/Form/context.js'
import { useConfig } from '../../providers/Config/index.js'
import { useDocumentInfo } from '../../providers/DocumentInfo/index.js'
import { useLocale } from '../../providers/Locale/index.js'
+import { useRouteTransition } from '../../providers/RouteTransition/index.js'
import { useServerFunctions } from '../../providers/ServerFunctions/index.js'
import { useTranslation } from '../../providers/Translation/index.js'
import { DrawerHeader } from '../BulkUpload/Header/index.js'
import { Button } from '../Button/index.js'
import { Drawer } from '../Drawer/index.js'
-import './index.scss'
import { PopupList } from '../Popup/index.js'
+import './index.scss'
const baseClass = 'copy-locale-data'
@@ -38,6 +39,7 @@ export const CopyLocaleData: React.FC = () => {
const { toggleModal } = useModal()
const { copyDataFromLocale } = useServerFunctions()
const router = useRouter()
+ const { startRouteTransition } = useRouteTransition()
const localeOptions =
(localization &&
@@ -77,9 +79,13 @@ export const CopyLocaleData: React.FC = () => {
})
setCopying(false)
- router.push(
- `${serverURL}${admin}/${collectionSlug ? `collections/${collectionSlug}/${id}` : `globals/${globalSlug}`}?locale=${to}`,
+
+ startRouteTransition(() =>
+ router.push(
+ `${serverURL}${admin}/${collectionSlug ? `collections/${collectionSlug}/${id}` : `globals/${globalSlug}`}?locale=${to}`,
+ ),
)
+
toggleModal(drawerSlug)
} catch (error) {
toast.error(error.message)
@@ -95,6 +101,7 @@ export const CopyLocaleData: React.FC = () => {
router,
serverURL,
admin,
+ startRouteTransition,
],
)
diff --git a/packages/ui/src/elements/DeleteDocument/index.tsx b/packages/ui/src/elements/DeleteDocument/index.tsx
index 2fe965a31c..9d13461881 100644
--- a/packages/ui/src/elements/DeleteDocument/index.tsx
+++ b/packages/ui/src/elements/DeleteDocument/index.tsx
@@ -1,5 +1,5 @@
'use client'
-import type { ClientCollectionConfig, SanitizedCollectionConfig } from 'payload'
+import type { SanitizedCollectionConfig } from 'payload'
import { Modal, useModal } from '@faceless-ui/modal'
import { getTranslation } from '@payloadcms/translations'
@@ -13,6 +13,7 @@ import { useForm } from '../../forms/Form/context.js'
import { useConfig } from '../../providers/Config/index.js'
import { useDocumentInfo } from '../../providers/DocumentInfo/index.js'
import { useEditDepth } from '../../providers/EditDepth/index.js'
+import { useRouteTransition } from '../../providers/RouteTransition/index.js'
import { useTranslation } from '../../providers/Translation/index.js'
import { requests } from '../../utilities/api.js'
import { formatAdminURL } from '../../utilities/formatAdminURL.js'
@@ -63,6 +64,7 @@ export const DeleteDocument: React.FC
= (props) => {
const { i18n, t } = useTranslation()
const { title } = useDocumentInfo()
const editDepth = useEditDepth()
+ const { startRouteTransition } = useRouteTransition()
const titleToRender = titleFromProps || title || id
@@ -105,11 +107,13 @@ export const DeleteDocument: React.FC = (props) => {
)
if (redirectAfterDelete) {
- return router.push(
- formatAdminURL({
- adminRoute,
- path: `/collections/${collectionSlug}`,
- }),
+ return startRouteTransition(() =>
+ router.push(
+ formatAdminURL({
+ adminRoute,
+ path: `/collections/${collectionSlug}`,
+ }),
+ ),
)
}
@@ -155,6 +159,7 @@ export const DeleteDocument: React.FC = (props) => {
redirectAfterDelete,
onDelete,
collectionConfig,
+ startRouteTransition,
])
if (id) {
diff --git a/packages/ui/src/elements/DeleteMany/index.tsx b/packages/ui/src/elements/DeleteMany/index.tsx
index c37d905508..0407a429be 100644
--- a/packages/ui/src/elements/DeleteMany/index.tsx
+++ b/packages/ui/src/elements/DeleteMany/index.tsx
@@ -16,8 +16,8 @@ import { useTranslation } from '../../providers/Translation/index.js'
import { requests } from '../../utilities/api.js'
import { mergeListSearchAndWhere } from '../../utilities/mergeListSearchAndWhere.js'
import { Button } from '../Button/index.js'
-import './index.scss'
import { Pill } from '../Pill/index.js'
+import './index.scss'
const baseClass = 'delete-documents'
diff --git a/packages/ui/src/elements/DocumentLocked/index.tsx b/packages/ui/src/elements/DocumentLocked/index.tsx
index fcd7a59fec..eb6677632c 100644
--- a/packages/ui/src/elements/DocumentLocked/index.tsx
+++ b/packages/ui/src/elements/DocumentLocked/index.tsx
@@ -3,6 +3,7 @@ import type { ClientUser } from 'payload'
import React, { useEffect } from 'react'
+import { useRouteTransition } from '../../providers/RouteTransition/index.js'
import { useTranslation } from '../../providers/Translation/index.js'
import { isClientUserObject } from '../../utilities/isClientUserObject.js'
import { Button } from '../Button/index.js'
@@ -37,6 +38,7 @@ export const DocumentLocked: React.FC<{
}> = ({ handleGoBack, isActive, onReadOnly, onTakeOver, updatedAt, user }) => {
const { closeModal, openModal } = useModal()
const { t } = useTranslation()
+ const { startRouteTransition } = useRouteTransition()
useEffect(() => {
if (isActive) {
@@ -47,7 +49,13 @@ export const DocumentLocked: React.FC<{
}, [isActive, openModal, closeModal])
return (
-
+ {
+ startRouteTransition(() => handleGoBack())
+ }}
+ slug={modalSlug}
+ >
{t('general:documentLocked')}
@@ -65,7 +73,9 @@ export const DocumentLocked: React.FC<{