diff --git a/packages/next/src/elements/Nav/index.client.tsx b/packages/next/src/elements/Nav/index.client.tsx
index aeedc49576..1bb703545e 100644
--- a/packages/next/src/elements/Nav/index.client.tsx
+++ b/packages/next/src/elements/Nav/index.client.tsx
@@ -44,23 +44,26 @@ export const DefaultNavClient: React.FC<{
id = `nav-global-${slug}`
}
- const LinkElement = Link || 'a'
const activeCollection =
pathname.startsWith(href) && ['/', undefined].includes(pathname[href.length])
+ const Label = (
+ {getTranslation(label, i18n)}
+ )
+
+ if (activeCollection) {
+ return (
+
+ )
+ }
+
return (
-
- {activeCollection && }
- {getTranslation(label, i18n)}
-
+
+ {Label}
+
)
})}
diff --git a/packages/next/src/elements/Nav/index.scss b/packages/next/src/elements/Nav/index.scss
index 93c03802f9..636b6b103d 100644
--- a/packages/next/src/elements/Nav/index.scss
+++ b/packages/next/src/elements/Nav/index.scss
@@ -93,36 +93,32 @@
}
}
- nav {
- a {
- position: relative;
- padding-block: base(0.125);
- padding-inline-start: 0;
- padding-inline-end: base(1.5);
- display: flex;
- text-decoration: none;
-
- &:focus:not(:focus-visible) {
- box-shadow: none;
- font-weight: 600;
- }
-
- &:hover,
- &:focus-visible {
- text-decoration: underline;
- }
-
- &.active {
- font-weight: normal;
- padding-left: 0;
- font-weight: 600;
- }
- }
- }
-
&__link {
display: flex;
align-items: center;
+ position: relative;
+ padding-block: base(0.125);
+ padding-inline-start: 0;
+ padding-inline-end: base(1.5);
+ text-decoration: none;
+
+ &:focus:not(:focus-visible) {
+ box-shadow: none;
+ font-weight: 600;
+ }
+
+ &.active {
+ font-weight: normal;
+ padding-left: 0;
+ font-weight: 600;
+ }
+ }
+
+ a.nav__link {
+ &:hover,
+ &:focus-visible {
+ text-decoration: underline;
+ }
}
&__link-indicator {
@@ -148,7 +144,7 @@
padding: var(--app-header-height) var(--gutter-h) base(2);
}
- nav a {
+ &__link {
font-size: base(0.875);
line-height: base(1.5);
}
diff --git a/packages/ui/src/elements/AppHeader/index.tsx b/packages/ui/src/elements/AppHeader/index.tsx
index 7307de39a6..da539789b6 100644
--- a/packages/ui/src/elements/AppHeader/index.tsx
+++ b/packages/ui/src/elements/AppHeader/index.tsx
@@ -59,8 +59,6 @@ export function AppHeader({ CustomAvatar, CustomIcon }: Props) {
}
}, [Actions])
- const LinkElement = Link || 'a'
-
const ActionComponents = Actions ? Object.values(Actions) : []
return (
@@ -95,15 +93,15 @@ export function AppHeader({ CustomAvatar, CustomIcon }: Props) {
{localization && (
)}
-
} />
-
+
diff --git a/packages/ui/src/elements/Logout/index.tsx b/packages/ui/src/elements/Logout/index.tsx
index acde86663c..2da58c7322 100644
--- a/packages/ui/src/elements/Logout/index.tsx
+++ b/packages/ui/src/elements/Logout/index.tsx
@@ -28,21 +28,17 @@ export const Logout: React.FC<{
routes: { admin: adminRoute },
} = config
- const props = {
- 'aria-label': t('authentication:logOut'),
- className: `${baseClass}__log-out`,
- prefetch: Link ? false : undefined,
- tabIndex,
- title: t('authentication:logOut'),
- }
-
return (
diff --git a/test/access-control/e2e.spec.ts b/test/access-control/e2e.spec.ts
index 006f94542f..2ef3b566c3 100644
--- a/test/access-control/e2e.spec.ts
+++ b/test/access-control/e2e.spec.ts
@@ -4,6 +4,7 @@ import type { TypeWithID } from 'payload'
import { expect, test } from '@playwright/test'
import { devUser } from 'credentials.js'
import { openDocControls } from 'helpers/e2e/openDocControls.js'
+import { openNav } from 'helpers/e2e/toggleNav.js'
import path from 'path'
import { wait } from 'payload/shared'
import { fileURLToPath } from 'url'
@@ -18,7 +19,6 @@ import {
getRoutes,
initPageConsoleErrorCatch,
login,
- openNav,
saveDocAndAssert,
} from '../helpers.js'
import { AdminUrlUtil } from '../helpers/adminUrlUtil.js'
@@ -312,7 +312,7 @@ describe('Access Control', () => {
test('should not show in nav', async () => {
await page.goto(url.admin)
await openNav(page)
- // await expect(page.locator('.nav >> a:has-text("Restricteds")')).toHaveCount(0)
+
await expect(
page.locator('.nav a', {
hasText: exactText('Restricteds'),
@@ -532,7 +532,6 @@ describe('Access Control', () => {
test('should restrict access based on user settings', async () => {
const url = `${serverURL}/admin/globals/settings`
await page.goto(url)
- await expect.poll(() => page.url(), { timeout: POLL_TOPASS_TIMEOUT }).toContain(url)
await openNav(page)
await expect(page.locator('#nav-global-settings')).toBeVisible()
await expect(page.locator('#nav-global-test')).toBeHidden()
diff --git a/test/access-control/payload-types.ts b/test/access-control/payload-types.ts
index ed98d40347..8be2a00c1e 100644
--- a/test/access-control/payload-types.ts
+++ b/test/access-control/payload-types.ts
@@ -6,11 +6,66 @@
* and re-run `payload generate:types` to regenerate this file.
*/
+/**
+ * Supported timezones in IANA format.
+ *
+ * This interface was referenced by `Config`'s JSON-Schema
+ * via the `definition` "supportedTimezones".
+ */
+export type SupportedTimezones =
+ | 'Pacific/Midway'
+ | 'Pacific/Niue'
+ | 'Pacific/Honolulu'
+ | 'Pacific/Rarotonga'
+ | 'America/Anchorage'
+ | 'Pacific/Gambier'
+ | 'America/Los_Angeles'
+ | 'America/Tijuana'
+ | 'America/Denver'
+ | 'America/Phoenix'
+ | 'America/Chicago'
+ | 'America/Guatemala'
+ | 'America/New_York'
+ | 'America/Bogota'
+ | 'America/Caracas'
+ | 'America/Santiago'
+ | 'America/Buenos_Aires'
+ | 'America/Sao_Paulo'
+ | 'Atlantic/South_Georgia'
+ | 'Atlantic/Azores'
+ | 'Atlantic/Cape_Verde'
+ | 'Europe/London'
+ | 'Europe/Berlin'
+ | 'Africa/Lagos'
+ | 'Europe/Athens'
+ | 'Africa/Cairo'
+ | 'Europe/Moscow'
+ | 'Asia/Riyadh'
+ | 'Asia/Dubai'
+ | 'Asia/Baku'
+ | 'Asia/Karachi'
+ | 'Asia/Tashkent'
+ | 'Asia/Calcutta'
+ | 'Asia/Dhaka'
+ | 'Asia/Almaty'
+ | 'Asia/Jakarta'
+ | 'Asia/Bangkok'
+ | 'Asia/Shanghai'
+ | 'Asia/Singapore'
+ | 'Asia/Tokyo'
+ | 'Asia/Seoul'
+ | 'Australia/Sydney'
+ | 'Pacific/Guam'
+ | 'Pacific/Noumea'
+ | 'Pacific/Auckland'
+ | 'Pacific/Fiji';
+
export interface Config {
auth: {
users: UserAuthOperations;
'public-users': PublicUserAuthOperations;
};
+ blocks: {};
collections: {
users: User;
'public-users': PublicUser;
diff --git a/test/admin/e2e/document-view/e2e.spec.ts b/test/admin/e2e/document-view/e2e.spec.ts
index 08dd762143..6dcdeeb123 100644
--- a/test/admin/e2e/document-view/e2e.spec.ts
+++ b/test/admin/e2e/document-view/e2e.spec.ts
@@ -11,7 +11,6 @@ import {
ensureCompilationIsDone,
exactText,
initPageConsoleErrorCatch,
- openNav,
saveDocAndAssert,
} from '../../../helpers.js'
import { AdminUrlUtil } from '../../../helpers/adminUrlUtil.js'
@@ -46,6 +45,7 @@ const description = 'Description'
let payload: PayloadTestSDK
import { navigateToDoc } from 'helpers/e2e/navigateToDoc.js'
+import { openNav } from 'helpers/e2e/toggleNav.js'
import path from 'path'
import { fileURLToPath } from 'url'
diff --git a/test/admin/e2e/general/e2e.spec.ts b/test/admin/e2e/general/e2e.spec.ts
index 44139d1927..6c84a828c8 100644
--- a/test/admin/e2e/general/e2e.spec.ts
+++ b/test/admin/e2e/general/e2e.spec.ts
@@ -9,7 +9,6 @@ import {
exactText,
getRoutes,
initPageConsoleErrorCatch,
- openNav,
saveDocAndAssert,
saveDocHotkeyAndAssert,
// throttleTest,
@@ -51,6 +50,7 @@ let payload: PayloadTestSDK
import { navigateToDoc } from 'helpers/e2e/navigateToDoc.js'
import { openDocControls } from 'helpers/e2e/openDocControls.js'
+import { openNav } from 'helpers/e2e/toggleNav.js'
import path from 'path'
import { fileURLToPath } from 'url'
@@ -406,6 +406,15 @@ describe('General', () => {
await expect(link).toBeHidden()
})
+ test('should disable active nav item', async () => {
+ await page.goto(postsUrl.list)
+ await openNav(page)
+ const activeItem = page.locator('.nav .nav__link.active')
+ await expect(activeItem).toBeVisible()
+ const tagName = await activeItem.evaluate((el) => el.tagName.toLowerCase())
+ expect(tagName).toBe('div')
+ })
+
test('breadcrumbs — should navigate from list to dashboard', async () => {
await page.goto(postsUrl.list)
await page.locator(`.step-nav a[href="${adminRoutes.routes.admin}"]`).click()
diff --git a/test/helpers.ts b/test/helpers.ts
index 3ee90344e2..4510cc3820 100644
--- a/test/helpers.ts
+++ b/test/helpers.ts
@@ -255,18 +255,6 @@ export async function saveDocAndAssert(
}
}
-export async function openNav(page: Page): Promise {
- // check to see if the nav is already open and if not, open it
- // use the `--nav-open` modifier class to check if the nav is open
- // this will prevent clicking nav links that are bleeding off the screen
- if (await page.locator('.template-default.template-default--nav-open').isVisible()) {
- return
- }
- // playwright: get first element with .nav-toggler which is VISIBLE (not hidden), could be 2 elements with .nav-toggler on mobile and desktop but only one is visible
- await page.locator('.nav-toggler >> visible=true').click()
- await expect(page.locator('.template-default.template-default--nav-open')).toBeVisible()
-}
-
export async function openDocDrawer(page: Page, selector: string): Promise {
await wait(500) // wait for parent form state to initialize
await page.locator(selector).click()
diff --git a/test/helpers/e2e/toggleNav.ts b/test/helpers/e2e/toggleNav.ts
new file mode 100644
index 0000000000..88108d5a98
--- /dev/null
+++ b/test/helpers/e2e/toggleNav.ts
@@ -0,0 +1,21 @@
+import type { Page } from '@playwright/test'
+
+import { expect } from '@playwright/test'
+import { wait } from 'payload/shared'
+
+export async function openNav(page: Page): Promise {
+ // wait for the preferences/media queries to either open or close the nav
+ // TODO: remove this in the future when nav state can be initialized properly
+ await wait(250)
+
+ // check to see if the nav is already open and if not, open it
+ // use the `--nav-open` modifier class to check if the nav is open
+ // this will prevent clicking nav links that are bleeding off the screen
+ if (await page.locator('.template-default.template-default--nav-open').isVisible()) {
+ return
+ }
+
+ // playwright: get first element with .nav-toggler which is VISIBLE (not hidden), could be 2 elements with .nav-toggler on mobile and desktop but only one is visible
+ await page.locator('.nav-toggler >> visible=true').click()
+ await expect(page.locator('.template-default.template-default--nav-open')).toBeVisible()
+}
diff --git a/tsconfig.base.json b/tsconfig.base.json
index fed3e543da..a12b54a3a6 100644
--- a/tsconfig.base.json
+++ b/tsconfig.base.json
@@ -31,7 +31,7 @@
}
],
"paths": {
- "@payload-config": ["./test/fields-relationship/config.ts"],
+ "@payload-config": ["./test/access-control/config.ts"],
"@payloadcms/live-preview": ["./packages/live-preview/src"],
"@payloadcms/live-preview-react": ["./packages/live-preview-react/src/index.ts"],
"@payloadcms/live-preview-vue": ["./packages/live-preview-vue/src/index.ts"],