fix(ui): admin description not being respected on tabs and padding issues with tab descriptions (#10710)
- Fixes collection and tab descriptions not having a bottom padding: - Deprecates `description` on tabs config in favour of `admin.description` but supports both - Adds test to make sure `admin.description` renders with static string and function too for tabs
This commit is contained in:
@@ -307,6 +307,30 @@ export const createClientField = ({
|
||||
typeof tabProp === 'function'
|
||||
) {
|
||||
clientTab[key] = tabProp({ t: i18n.t })
|
||||
} else if (key === 'admin') {
|
||||
clientTab.admin = {} as AdminClient
|
||||
|
||||
for (const adminKey in tab.admin) {
|
||||
if (serverOnlyFieldAdminProperties.includes(adminKey as any)) {
|
||||
continue
|
||||
}
|
||||
|
||||
switch (adminKey) {
|
||||
case 'description':
|
||||
if ('description' in tab.admin) {
|
||||
if (typeof tab.admin?.description === 'function') {
|
||||
clientTab.admin.description = tab.admin.description({ t: i18n.t })
|
||||
} else {
|
||||
clientTab.admin.description = tab.admin.description
|
||||
}
|
||||
}
|
||||
|
||||
break
|
||||
|
||||
default:
|
||||
clientField.admin[adminKey] = tab.admin[adminKey]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
clientTab[key] = tabProp
|
||||
}
|
||||
|
||||
@@ -716,6 +716,10 @@ export type CollapsibleFieldClient = {
|
||||
Pick<CollapsibleField, 'type'>
|
||||
|
||||
type TabBase = {
|
||||
/**
|
||||
* @deprecated
|
||||
* Use `admin.description` instead. This will be removed in a future major version.
|
||||
*/
|
||||
description?: LabelFunction | StaticDescription
|
||||
fields: Field[]
|
||||
interfaceName?: string
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
@import '../../scss/styles.scss';
|
||||
|
||||
@layer payload-default {
|
||||
.view-description {
|
||||
margin-block-end: calc(var(--base));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ const TabsFieldComponent: TabsFieldClientComponent = (props) => {
|
||||
|
||||
const activeTabConfig = tabs[activeTabIndex]
|
||||
|
||||
const activeTabDescription = activeTabConfig.description
|
||||
const activeTabDescription = activeTabConfig.admin?.description ?? activeTabConfig.description
|
||||
|
||||
const activeTabStaticDescription =
|
||||
typeof activeTabDescription === 'function'
|
||||
@@ -257,7 +257,9 @@ function ActiveTabContent({
|
||||
>
|
||||
<RenderCustomComponent
|
||||
CustomComponent={Description}
|
||||
Fallback={<FieldDescription description={description} path={path} />}
|
||||
Fallback={
|
||||
<FieldDescription description={description} marginPlacement="bottom" path={path} />
|
||||
}
|
||||
/>
|
||||
{BeforeInput}
|
||||
<RenderFields
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { CollectionConfig } from 'payload'
|
||||
|
||||
import { slateEditor } from '@payloadcms/richtext-slate'
|
||||
|
||||
import { slugPluralLabel, slugSingularLabel } from '../shared.js'
|
||||
import { customTabAdminDescription, slugPluralLabel, slugSingularLabel } from '../shared.js'
|
||||
import { postsCollectionSlug, uploadCollectionSlug } from '../slugs.js'
|
||||
|
||||
export const Posts: CollectionConfig = {
|
||||
@@ -104,6 +104,16 @@ export const Posts: CollectionConfig = {
|
||||
},
|
||||
],
|
||||
label: 'Tab 1',
|
||||
admin: {
|
||||
description: customTabAdminDescription,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Tab 2',
|
||||
fields: [],
|
||||
admin: {
|
||||
description: () => `t:${customTabAdminDescription}`,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -24,6 +24,7 @@ import {
|
||||
customTabLabel,
|
||||
customTabViewPath,
|
||||
customTabViewTitle,
|
||||
customTabAdminDescription,
|
||||
} from '../../shared.js'
|
||||
import {
|
||||
customFieldsSlug,
|
||||
@@ -378,6 +379,31 @@ describe('Document View', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('descriptions', () => {
|
||||
test('should render tab admin description', async () => {
|
||||
await page.goto(postsUrl.create)
|
||||
await page.waitForURL(postsUrl.create)
|
||||
|
||||
const tabsContent = page.locator('.tabs-field__content-wrap')
|
||||
await expect(tabsContent.locator('.field-description')).toHaveText(customTabAdminDescription)
|
||||
})
|
||||
|
||||
test('should render tab admin description as a translation function', async () => {
|
||||
await page.goto(postsUrl.create)
|
||||
await page.waitForURL(postsUrl.create)
|
||||
|
||||
const secondTab = page.locator('.tabs-field__tab-button').nth(1)
|
||||
secondTab.click()
|
||||
|
||||
wait(500)
|
||||
|
||||
const tabsContent = page.locator('.tabs-field__content-wrap')
|
||||
await expect(
|
||||
tabsContent.locator('.field-description', { hasText: `t:${customTabAdminDescription}` }),
|
||||
).toBeVisible()
|
||||
})
|
||||
})
|
||||
|
||||
describe('custom fields', () => {
|
||||
test('should render custom field component', async () => {
|
||||
await page.goto(customFieldsURL.create)
|
||||
|
||||
@@ -44,6 +44,8 @@ export const customDefaultTabMetaTitle = 'Custom Default Tab Meta Title'
|
||||
|
||||
export const customVersionsTabMetaTitle = 'Custom Versions Tab Meta Title'
|
||||
|
||||
export const customTabAdminDescription = 'Custom Tab Admin Description'
|
||||
|
||||
export const customViewMetaTitle = 'Custom Tab Meta Title'
|
||||
|
||||
export const customNestedTabViewTitle = 'Custom Nested Tab View'
|
||||
|
||||
Reference in New Issue
Block a user