diff --git a/packages/ui/src/fields/Array/index.tsx b/packages/ui/src/fields/Array/index.tsx
index 848971467..0358f459a 100644
--- a/packages/ui/src/fields/Array/index.tsx
+++ b/packages/ui/src/fields/Array/index.tsx
@@ -6,7 +6,7 @@ import type {
} from 'payload'
import { getTranslation } from '@payloadcms/translations'
-import React, { Fragment, useCallback } from 'react'
+import React, { Fragment, useCallback, useMemo } from 'react'
import { toast } from 'sonner'
import type { ClipboardPasteData } from '../../elements/ClipboardAction/types.js'
@@ -36,6 +36,7 @@ import { useDocumentInfo } from '../../providers/DocumentInfo/index.js'
import { useLocale } from '../../providers/Locale/index.js'
import { useTranslation } from '../../providers/Translation/index.js'
import { scrollToID } from '../../utilities/scrollToID.js'
+import { mergeFieldStyles } from '../mergeFieldStyles.js'
import { fieldBaseClass } from '../shared/index.js'
import { ArrayRow } from './ArrayRow.js'
import './index.scss'
@@ -44,6 +45,7 @@ const baseClass = 'array-field'
export const ArrayFieldComponent: ArrayFieldClientComponent = (props) => {
const {
+ field,
field: {
name,
type,
@@ -299,6 +301,8 @@ export const ArrayFieldComponent: ArrayFieldClientComponent = (props) => {
const showRequired = (readOnly || disabled) && rows.length === 0
const showMinRows = (rows.length && rows.length < minRows) || (required && rows.length === 0)
+ const styles = useMemo(() => mergeFieldStyles(field), [field])
+
return (
{
.filter(Boolean)
.join(' ')}
id={`field-${path.replace(/\./g, '__')}`}
+ style={styles}
>
{showError && (
{
getComputedStyle(el).getPropertyValue('--field-width').trim(),
)
- expect(leftVar).toBe('50%')
- expect(rightVar).toBe('50%')
+ await expect(() => {
+ expect(leftVar).toBe('50%')
+ expect(rightVar).toBe('50%')
+ }).toPass()
+
+ // Also assert inline style contains the var (robust to other inline styles)
+ await expect(left).toHaveAttribute('style', /--field-width:\s*50%/)
+ await expect(right).toHaveAttribute('style', /--field-width:\s*50%/)
+
+ // 2) Layout reflects the widths (same row, equal widths)
+ const leftBox = await left.boundingBox()
+ const rightBox = await right.boundingBox()
+
+ await expect(() => {
+ // Same row
+ expect(Math.round(leftBox.y)).toEqual(Math.round(rightBox.y))
+ // Equal width (tolerate sub-pixel differences)
+ expect(Math.round(leftBox.width)).toEqual(Math.round(rightBox.width))
+ }).toPass()
+ })
+
+ test('should respect admin.width for array fields inside a row', async () => {
+ await page.goto(url.create)
+
+ // Target the Array field wrappers
+ const left = page.locator('#field-arrayLeftColumn')
+ const right = page.locator('#field-arrayRightColumn')
+
+ await expect(left).toBeVisible()
+ await expect(right).toBeVisible()
+
+ // 1) CSS variable is applied (via mergeFieldStyles)
+ const leftVar = await left.evaluate((el) =>
+ getComputedStyle(el).getPropertyValue('--field-width').trim(),
+ )
+ const rightVar = await right.evaluate((el) =>
+ getComputedStyle(el).getPropertyValue('--field-width').trim(),
+ )
+
+ await expect(() => {
+ expect(leftVar).toBe('50%')
+ expect(rightVar).toBe('50%')
+ }).toPass()
// Also assert inline style contains the var (robust to other inline styles)
await expect(left).toHaveAttribute('style', /--field-width:\s*50%/)
diff --git a/test/fields/collections/Row/index.ts b/test/fields/collections/Row/index.ts
index c25d47089..1142a68af 100644
--- a/test/fields/collections/Row/index.ts
+++ b/test/fields/collections/Row/index.ts
@@ -178,6 +178,37 @@ const RowFields: CollectionConfig = {
},
],
},
+ {
+ type: 'row',
+ fields: [
+ {
+ name: 'arrayLeftColumn',
+ type: 'array',
+ admin: {
+ width: '50%',
+ },
+ fields: [
+ {
+ name: 'leftArrayChild',
+ type: 'text',
+ },
+ ],
+ },
+ {
+ name: 'arrayRightColumn',
+ type: 'array',
+ fields: [
+ {
+ name: 'rightArrayChild',
+ type: 'text',
+ },
+ ],
+ admin: {
+ width: '50%',
+ },
+ },
+ ],
+ },
],
}
diff --git a/test/fields/payload-types.ts b/test/fields/payload-types.ts
index 6de3e8529..50b383869 100644
--- a/test/fields/payload-types.ts
+++ b/test/fields/payload-types.ts
@@ -1194,6 +1194,18 @@ export interface RowField {
blockType: 'rightTextBlock';
}[]
| null;
+ arrayLeftColumn?:
+ | {
+ leftArrayChild?: string | null;
+ id?: string | null;
+ }[]
+ | null;
+ arrayRightColumn?:
+ | {
+ rightArrayChild?: string | null;
+ id?: string | null;
+ }[]
+ | null;
updatedAt: string;
createdAt: string;
}
@@ -2904,6 +2916,18 @@ export interface RowFieldsSelect {
blockName?: T;
};
};
+ arrayLeftColumn?:
+ | T
+ | {
+ leftArrayChild?: T;
+ id?: T;
+ };
+ arrayRightColumn?:
+ | T
+ | {
+ rightArrayChild?: T;
+ id?: T;
+ };
updatedAt?: T;
createdAt?: T;
}