Skip to content

Commit 1d751d8

Browse files
Copilothotlong
andcommitted
refactor: address code review feedback - rename overscan to batchSize, extract VS_REVEAL_DELAY constant, use granular useMemo deps
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 6181108 commit 1d751d8

4 files changed

Lines changed: 38 additions & 8 deletions

File tree

ROADMAP.md

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1414,7 +1414,34 @@ All 313 `@object-ui/fields` tests pass.
14141414

14151415
---
14161416

1417-
### DetailView Rendering Optimization (March 2026)
1417+
### DetailView/RecordDetailView SDUI Optimization (March 2026)
1418+
1419+
> Type-aware rendering, responsive layout, virtual scrolling, metadata-driven highlights, performance optimization, and activity panel collapse-when-empty.
1420+
1421+
**HeaderHighlight (`@object-ui/plugin-detail`):**
1422+
- [x] Use `getCellRenderer` for type-aware display (currency → `$250,000.00`, select → Badge, etc.) instead of raw `String(value)`
1423+
- [x] Add `objectSchema` prop for field metadata enrichment (type, options, currency, precision, format)
1424+
1425+
**autoLayout (`@object-ui/plugin-detail`):**
1426+
- [x] `inferDetailColumns` accepts optional `containerWidth` for responsive column capping (`<640px→1col`, `<900px→max 2col`)
1427+
- [x] `applyDetailAutoLayout` passes through `containerWidth` parameter
1428+
1429+
**RecordChatterPanel (`@object-ui/plugin-detail`):**
1430+
- [x] `collapseWhenEmpty` prop: auto-collapse panel when no feed items exist
1431+
- [x] Pass `collapseWhenEmpty` through to embedded `RecordActivityTimeline`
1432+
1433+
**DetailSection (`@object-ui/plugin-detail`):**
1434+
- [x] `virtualScroll` config (`VirtualScrollOptions`): progressive batch rendering for sections with many fields
1435+
- [x] Export `VirtualScrollOptions` type from package index
1436+
1437+
**RecordDetailView (`apps/console`):**
1438+
- [x] Wrap `detailSchema` construction with `useMemo` (deps: `objectDef`, `pureRecordId`, `related`, `childRelatedData`, `actionRefreshKey`)
1439+
- [x] Remove hardcoded `HIGHLIGHT_FIELD_NAMES`; read exclusively from `objectDef.views.detail.highlightFields` (no fallback)
1440+
- [x] Enable `collapseWhenEmpty` + `collapsible: true` on `RecordChatterPanel`
1441+
1442+
**Tests:** 125 plugin-detail tests passing (17 new) covering HeaderHighlight type-aware rendering, autoLayout responsive columns, RecordChatterPanel collapseWhenEmpty, DetailSection virtualScroll.
1443+
1444+
---
14181445

14191446
> Platform-level DetailView enhancements: auto-grouping from form sections, empty value hiding, smart header with primaryField/summaryFields, responsive breakpoint fix, and activity timeline collapse.
14201447

apps/console/src/components/RecordDetailView.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,8 @@ export function RecordDetailView({ dataSource, objects, onEdit }: RecordDetailVi
432432
actions: recordHeaderActions,
433433
} as any],
434434
}),
435-
}), [objectDef, pureRecordId, related, childRelatedData, actionRefreshKey]);
435+
// eslint-disable-next-line react-hooks/exhaustive-deps
436+
}), [objectDef.name, pureRecordId, childRelatedData, actionRefreshKey]);
436437

437438
return (
438439
<div className="h-full bg-background overflow-hidden flex flex-col relative">

packages/plugin-detail/src/DetailSection.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ export interface VirtualScrollOptions {
5858
enabled?: boolean;
5959
/** Height of each field row in px (default: 60) */
6060
itemHeight?: number;
61-
/** Number of extra items to render above/below the visible area (default: 3) */
62-
overscan?: number;
61+
/** Number of fields to render in the initial batch before revealing all (default: 20) */
62+
batchSize?: number;
6363
}
6464

6565
export interface DetailSectionProps {
@@ -228,7 +228,9 @@ export const DetailSection: React.FC<DetailSectionProps> = ({
228228

229229
// Virtual scroll: progressive batch rendering for large field sets
230230
const vsEnabled = virtualScroll?.enabled === true;
231-
const vsBatchSize = virtualScroll?.overscan ?? 20;
231+
const vsBatchSize = virtualScroll?.batchSize ?? 20;
232+
/** Delay (ms) before revealing remaining fields after the initial batch */
233+
const VS_REVEAL_DELAY = 100;
232234

233235
React.useEffect(() => {
234236
if (!vsEnabled) {
@@ -241,7 +243,7 @@ export const DetailSection: React.FC<DetailSectionProps> = ({
241243
return;
242244
}
243245
setVisibleCount(vsBatchSize);
244-
const timer = setTimeout(() => setVisibleCount(undefined), 100);
246+
const timer = setTimeout(() => setVisibleCount(undefined), VS_REVEAL_DELAY);
245247
return () => clearTimeout(timer);
246248
// eslint-disable-next-line react-hooks/exhaustive-deps
247249
}, [vsEnabled, layoutFields.length, vsBatchSize]);

packages/plugin-detail/src/__tests__/DetailSection.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,7 @@ describe('DetailSection', () => {
405405
<DetailSection
406406
section={section}
407407
data={{}}
408-
virtualScroll={{ enabled: true, overscan: 10 }}
408+
virtualScroll={{ enabled: true, batchSize: 10 }}
409409
/>
410410
);
411411
const grid = container.querySelector('.grid');
@@ -445,7 +445,7 @@ describe('DetailSection', () => {
445445
<DetailSection
446446
section={section}
447447
data={{}}
448-
virtualScroll={{ enabled: true, overscan: 20 }}
448+
virtualScroll={{ enabled: true, batchSize: 20 }}
449449
/>
450450
);
451451
const grid = container.querySelector('.grid');

0 commit comments

Comments
 (0)