Skip to content

Commit 9f462b0

Browse files
Copilothotlong
andcommitted
fix: align ConfigPanel UI with spec — rowHeight 5 values, add clickIntoRecordDetails toggle
- NamedListView/ObjectGridSchema rowHeight: add 'short' and 'extra_tall' to align with ListViewSchema spec - Zod schema: update rowHeight enum to include all 5 spec values - ROW_HEIGHT_OPTIONS: add 'short' (gap-px) and 'extra_tall' (gap-1.5) entries - Add clickIntoRecordDetails toggle to userActions section (NamedListView spec field) - Update ViewConfigPanel test for 5 row height buttons - Add 5 spec-alignment tests (ROW_HEIGHT_OPTIONS coverage, NamedListView field coverage) - Update ROADMAP.md Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 3a916d0 commit 9f462b0

7 files changed

Lines changed: 88 additions & 12 deletions

File tree

ROADMAP.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,8 @@ ObjectUI is a universal Server-Driven UI (SDUI) engine built on React + Tailwind
205205
-`ListViewSchema` Zod schema extended with all new properties
206206
- ✅ ViewConfigPanel aligned to full `ListViewSchema` spec: navigation mode, selection, pagination, export sub-config, searchable/filterable/hidden fields, resizable, density mode, row/bulk actions, sharing, addRecord sub-editor, conditional formatting, quick filters, showRecordCount, allowPrinting, virtualScroll, empty state, ARIA accessibility
207207
- ✅ Semantic fix: `editRecordsInline``inlineEdit` field name alignment (i18n keys, data-testid, component label all unified to `inlineEdit`)
208-
- ✅ Semantic fix: `rowHeight` values aligned to spec (`compact`/`medium`/`tall`)
208+
- ✅ Semantic fix: `rowHeight` values aligned to full spec — all 5 RowHeight enum values (`compact`/`short`/`medium`/`tall`/`extra_tall`) now supported in NamedListView, ObjectGridSchema, ListViewSchema, Zod schema, and UI
209+
-`clickIntoRecordDetails` toggle added to UserActions section (NamedListView spec field — previously only implicit via navigation mode)
209210
- ✅ i18n keys verified complete for en/zh and all 10 locale files
210211
- ✅ Console ObjectView fullSchema propagates all 18 new spec properties
211212
- ✅ PluginObjectView renderListView schema propagates all 18 new spec properties

apps/console/src/__tests__/ViewConfigPanel.test.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2227,7 +2227,7 @@ describe('ViewConfigPanel', () => {
22272227
expect(screen.getByTestId('bulk-actions-selector')).toBeInTheDocument();
22282228
});
22292229

2230-
it('renders row height buttons with spec-aligned values (compact/medium/tall)', () => {
2230+
it('renders row height buttons with all 5 spec-aligned values', () => {
22312231
const onViewUpdate = vi.fn();
22322232
render(
22332233
<ViewConfigPanel
@@ -2240,11 +2240,10 @@ describe('ViewConfigPanel', () => {
22402240
);
22412241

22422242
expect(screen.getByTestId('row-height-compact')).toBeInTheDocument();
2243+
expect(screen.getByTestId('row-height-short')).toBeInTheDocument();
22432244
expect(screen.getByTestId('row-height-medium')).toBeInTheDocument();
22442245
expect(screen.getByTestId('row-height-tall')).toBeInTheDocument();
2245-
// Old values should not exist
2246-
expect(screen.queryByTestId('row-height-short')).not.toBeInTheDocument();
2247-
expect(screen.queryByTestId('row-height-extraTall')).not.toBeInTheDocument();
2246+
expect(screen.getByTestId('row-height-extra_tall')).toBeInTheDocument();
22482247

22492248
// Click compact and verify update
22502249
fireEvent.click(screen.getByTestId('row-height-compact'));

apps/console/src/__tests__/view-config-schema.test.tsx

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import {
4343
toSortItems,
4444
SPEC_TO_BUILDER_OP,
4545
BUILDER_TO_SPEC_OP,
46+
ROW_HEIGHT_OPTIONS,
4647
} from '../utils/view-config-utils';
4748

4849
import { buildViewConfigSchema } from '../utils/view-config-schema';
@@ -439,6 +440,7 @@ describe('buildViewConfigSchema', () => {
439440
const schema = buildSchema();
440441
const section = schema.sections.find(s => s.key === 'userActions')!;
441442
const fieldKeys = section.fields.map(f => f.key);
443+
expect(fieldKeys).toContain('clickIntoRecordDetails');
442444
expect(fieldKeys).toContain('inlineEdit');
443445
expect(fieldKeys).toContain('addDeleteRecordsInline');
444446
expect(fieldKeys).toContain('_rowActions');
@@ -525,3 +527,67 @@ describe('buildViewConfigSchema', () => {
525527
}
526528
});
527529
});
530+
531+
// ═══════════════════════════════════════════════════════════════════════════
532+
// 3. Spec-alignment validation
533+
// ═══════════════════════════════════════════════════════════════════════════
534+
535+
describe('spec alignment', () => {
536+
// ── ROW_HEIGHT_OPTIONS matches spec RowHeight enum ───────────────────
537+
describe('ROW_HEIGHT_OPTIONS', () => {
538+
it('contains all 5 spec RowHeight values', () => {
539+
const values = ROW_HEIGHT_OPTIONS.map(o => o.value);
540+
expect(values).toEqual(['compact', 'short', 'medium', 'tall', 'extra_tall']);
541+
});
542+
543+
it('each option has a gapClass', () => {
544+
for (const opt of ROW_HEIGHT_OPTIONS) {
545+
expect(opt.gapClass).toBeDefined();
546+
expect(typeof opt.gapClass).toBe('string');
547+
}
548+
});
549+
});
550+
551+
// ── NamedListView field coverage ────────────────────────────────────
552+
describe('NamedListView spec field coverage', () => {
553+
function buildSchema() {
554+
return buildViewConfigSchema({
555+
t: mockT,
556+
fieldOptions: mockFieldOptions,
557+
objectDef: mockObjectDef,
558+
updateField: mockUpdateField,
559+
filterGroupValue: mockFilterGroup,
560+
sortItemsValue: mockSortItems,
561+
});
562+
}
563+
564+
function allFieldKeys() {
565+
const schema = buildSchema();
566+
return schema.sections.flatMap(s => s.fields.map(f => f.key));
567+
}
568+
569+
it('covers clickIntoRecordDetails from NamedListView spec', () => {
570+
expect(allFieldKeys()).toContain('clickIntoRecordDetails');
571+
});
572+
573+
it('covers all NamedListView toolbar toggles', () => {
574+
const keys = allFieldKeys();
575+
const toolbarFields = [
576+
'showSearch', 'showFilters', 'showSort',
577+
'showHideFields', 'showGroup', 'showColor', 'showDensity',
578+
];
579+
for (const field of toolbarFields) {
580+
expect(keys).toContain(field);
581+
}
582+
});
583+
584+
it('covers all NamedListView boolean toggles in userActions', () => {
585+
const schema = buildSchema();
586+
const section = schema.sections.find(s => s.key === 'userActions')!;
587+
const keys = section.fields.map(f => f.key);
588+
expect(keys).toContain('clickIntoRecordDetails');
589+
expect(keys).toContain('inlineEdit');
590+
expect(keys).toContain('addDeleteRecordsInline');
591+
});
592+
});
593+
});

apps/console/src/utils/view-config-schema.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1214,6 +1214,7 @@ function buildUserActionsSection(
12141214
title: t('console.objectView.userActions'),
12151215
collapsible: true,
12161216
fields: [
1217+
buildSwitchField('clickIntoRecordDetails', t('console.objectView.clickIntoRecordDetails'), 'toggle-clickIntoRecordDetails', true),
12171218
buildSwitchField('inlineEdit', t('console.objectView.inlineEdit'), 'toggle-inlineEdit', true),
12181219
buildSwitchField('addDeleteRecordsInline', t('console.objectView.addDeleteRecordsInline'), 'toggle-addDeleteRecordsInline', true),
12191220
// Row actions

apps/console/src/utils/view-config-utils.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,11 +186,16 @@ export const VIEW_TYPE_LABELS: Record<string, string> = {
186186
/** All available view type keys */
187187
export const VIEW_TYPE_OPTIONS = Object.keys(VIEW_TYPE_LABELS);
188188

189-
/** Row height options with Tailwind gap classes for visual icons */
189+
/**
190+
* Row height options with Tailwind gap classes for visual icons.
191+
* Aligned with @objectstack/spec RowHeight enum — all 5 values.
192+
*/
190193
export const ROW_HEIGHT_OPTIONS: Array<{ value: string; gapClass: string }> = [
191194
{ value: 'compact', gapClass: 'gap-0' },
195+
{ value: 'short', gapClass: 'gap-px' },
192196
{ value: 'medium', gapClass: 'gap-0.5' },
193197
{ value: 'tall', gapClass: 'gap-1' },
198+
{ value: 'extra_tall', gapClass: 'gap-1.5' },
194199
];
195200

196201
// ---------------------------------------------------------------------------

packages/types/src/objectql.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -416,11 +416,12 @@ export interface ObjectGridSchema extends BaseSchema {
416416
frozenColumns?: number;
417417

418418
/**
419-
* Row height preset for the grid
420-
* Controls the density of grid rows
419+
* Row height preset for the grid.
420+
* Controls the density of grid rows.
421+
* Aligned with @objectstack/spec RowHeight enum.
421422
* @default 'medium'
422423
*/
423-
rowHeight?: 'compact' | 'medium' | 'tall';
424+
rowHeight?: 'compact' | 'short' | 'medium' | 'tall' | 'extra_tall';
424425

425426
/**
426427
* Export options configuration for exporting grid data.
@@ -1082,8 +1083,11 @@ export interface NamedListView {
10821083
/** Density mode for controlling row/item spacing */
10831084
densityMode?: 'compact' | 'comfortable' | 'spacious';
10841085

1085-
/** Row height for list/grid view rows */
1086-
rowHeight?: 'compact' | 'medium' | 'tall';
1086+
/**
1087+
* Row height for list/grid view rows.
1088+
* Aligned with @objectstack/spec RowHeight enum.
1089+
*/
1090+
rowHeight?: 'compact' | 'short' | 'medium' | 'tall' | 'extra_tall';
10871091

10881092
/** Fields to hide from the current view */
10891093
hiddenFields?: string[];

packages/types/src/zod/objectql.zod.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ export const ListViewSchema = BaseSchema.extend({
287287
filterableFields: z.array(z.string()).optional().describe('Filterable fields'),
288288
resizable: z.boolean().optional().describe('Allow column resizing'),
289289
densityMode: z.enum(['compact', 'comfortable', 'spacious']).optional().describe('Density mode'),
290-
rowHeight: z.enum(['compact', 'medium', 'tall']).optional().describe('Row height'),
290+
rowHeight: z.enum(['compact', 'short', 'medium', 'tall', 'extra_tall']).optional().describe('Row height'),
291291
hiddenFields: z.array(z.string()).optional().describe('Hidden fields'),
292292
exportOptions: z.object({
293293
formats: z.array(z.enum(['csv', 'xlsx', 'json', 'pdf'])).optional(),

0 commit comments

Comments
 (0)