Skip to content

Commit

Permalink
fix(ui): does not render row labels until form state returns (#10002)
Browse files Browse the repository at this point in the history
Extension of #9933. Custom components are returned by form state,
meaning that if we don't wait for form state to return before rendering
row labels, the default row label component will render in briefly
before being swapped by a custom component (if applicable). Using the
new `isLoading` prop on array and block rows, we can conditionally
render them just as we currently do for the row fields themselves.
  • Loading branch information
jacobsfletch authored Dec 16, 2024
1 parent fa49e04 commit ed44ec0
Show file tree
Hide file tree
Showing 6 changed files with 367 additions and 177 deletions.
14 changes: 8 additions & 6 deletions packages/ui/src/fields/Array/ArrayRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,14 @@ export const ArrayRow: React.FC<ArrayRowProps> = ({
}
header={
<div className={`${baseClass}__row-header`}>
<RowLabel
CustomComponent={CustomRowLabel}
label={fallbackLabel}
path={path}
rowNumber={rowIndex}
/>
{isLoading ? null : (
<RowLabel
CustomComponent={CustomRowLabel}
label={fallbackLabel}
path={path}
rowNumber={rowIndex}
/>
)}
{fieldHasErrors && <ErrorPill count={errorCount} i18n={i18n} withMessage />}
</div>
}
Expand Down
32 changes: 17 additions & 15 deletions packages/ui/src/fields/Blocks/BlockRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -140,21 +140,23 @@ export const BlockRow: React.FC<BlocksFieldProps> = ({
: undefined
}
header={
Label || (
<div className={`${baseClass}__block-header`}>
<span className={`${baseClass}__block-number`}>
{String(rowIndex + 1).padStart(2, '0')}
</span>
<Pill
className={`${baseClass}__block-pill ${baseClass}__block-pill-${row.blockType}`}
pillStyle="white"
>
{getTranslation(block.labels.singular, i18n)}
</Pill>
<SectionTitle path={`${path}.blockName`} readOnly={readOnly} />
{fieldHasErrors && <ErrorPill count={errorCount} i18n={i18n} withMessage />}
</div>
)
isLoading
? null
: Label || (
<div className={`${baseClass}__block-header`}>
<span className={`${baseClass}__block-number`}>
{String(rowIndex + 1).padStart(2, '0')}
</span>
<Pill
className={`${baseClass}__block-pill ${baseClass}__block-pill-${row.blockType}`}
pillStyle="white"
>
{getTranslation(block.labels.singular, i18n)}
</Pill>
<SectionTitle path={`${path}.blockName`} readOnly={readOnly} />
{fieldHasErrors && <ErrorPill count={errorCount} i18n={i18n} withMessage />}
</div>
)
}
isCollapsed={row.collapsed}
key={row.id}
Expand Down
1 change: 1 addition & 0 deletions packages/ui/src/forms/RowLabel/Context/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const RowLabelProvider: React.FC<Props<unknown>> = ({ children, path, row
const { getDataByPath, getSiblingData } = useWatchForm()
const collapsibleData = getSiblingData(path)
const arrayData = getDataByPath(path)

const data = arrayData || collapsibleData

return <RowLabel.Provider value={{ data, path, rowNumber }}>{children}</RowLabel.Provider>
Expand Down
4 changes: 3 additions & 1 deletion test/fields/collections/Array/LabelComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import React from 'react'
export const ArrayRowLabel: PayloadClientReactComponent<RowLabelComponent> = () => {
const { data } = useRowLabel<{ title: string }>()
return (
<div style={{ color: 'coral', textTransform: 'uppercase' }}>{data.title || 'Untitled'}</div>
<div id="custom-array-row-label" style={{ color: 'coral', textTransform: 'uppercase' }}>
{data.title || 'Untitled'}
</div>
)
}
14 changes: 14 additions & 0 deletions test/fields/collections/Array/e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,25 @@ describe('Array', () => {
await page.goto(url.create)
await page.locator('#field-rowLabelAsComponent >> .array-field__add-row').click()

// ensure the default label does not blink in before form state returns
const defaultRowLabelWasAttached = await page
.waitForSelector('#field-rowLabelAsComponent .array-field__row-header .row-label', {
state: 'attached',
timeout: 100, // A small timeout to catch any transient rendering
})
.catch(() => false) // If it doesn't appear, this resolves to `false`

expect(defaultRowLabelWasAttached).toBeFalsy()

await expect(page.locator('#field-rowLabelAsComponent #custom-array-row-label')).toBeVisible()

await page.locator('#field-rowLabelAsComponent__0__title').fill(label)
await wait(100)

const customRowLabel = page.locator(
'#rowLabelAsComponent-row-0 >> .array-field__row-header > :text("custom row label")',
)

await expect(customRowLabel).toHaveCSS('text-transform', 'uppercase')
})

Expand Down
Loading

0 comments on commit ed44ec0

Please sign in to comment.