From 7daa71fdc661c6a8c14ac237496b974b298eaf79 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 28 Mar 2026 19:20:55 +0100 Subject: [PATCH] scaffolder: merge description and type into a single value column Combine the description and type columns into a single "Value" column that shows the type, description, and nested content inline. This avoids the broken layout where expanded rows were rendered as siblings below the table, decoupled from their row context. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- plugins/scaffolder/report-alpha.api.md | 1 + plugins/scaffolder/report.api.md | 1 + .../RenderSchema/RenderSchema.test.tsx | 11 +- .../components/RenderSchema/RenderSchema.tsx | 258 ++++++++---------- plugins/scaffolder/src/translation.ts | 1 + 5 files changed, 125 insertions(+), 147 deletions(-) diff --git a/plugins/scaffolder/report-alpha.api.md b/plugins/scaffolder/report-alpha.api.md index 4031f295f1..32a6a98658 100644 --- a/plugins/scaffolder/report-alpha.api.md +++ b/plugins/scaffolder/report-alpha.api.md @@ -806,6 +806,7 @@ export const scaffolderTranslationRef: TranslationRef< readonly 'renderSchema.undefined': 'No schema defined'; readonly 'renderSchema.tableCell.name': 'Name'; readonly 'renderSchema.tableCell.type': 'Type'; + readonly 'renderSchema.tableCell.value': 'Value'; readonly 'renderSchema.tableCell.title': 'Title'; readonly 'renderSchema.tableCell.description': 'Description'; readonly 'templatingExtensions.content.values.title': 'Values'; diff --git a/plugins/scaffolder/report.api.md b/plugins/scaffolder/report.api.md index 545c69f0ff..2101501bff 100644 --- a/plugins/scaffolder/report.api.md +++ b/plugins/scaffolder/report.api.md @@ -708,6 +708,7 @@ export const scaffolderTranslationRef: TranslationRef< readonly 'renderSchema.undefined': 'No schema defined'; readonly 'renderSchema.tableCell.name': 'Name'; readonly 'renderSchema.tableCell.type': 'Type'; + readonly 'renderSchema.tableCell.value': 'Value'; readonly 'renderSchema.tableCell.title': 'Title'; readonly 'renderSchema.tableCell.description': 'Description'; readonly 'templatingExtensions.content.values.title': 'Values'; diff --git a/plugins/scaffolder/src/components/RenderSchema/RenderSchema.test.tsx b/plugins/scaffolder/src/components/RenderSchema/RenderSchema.test.tsx index 0e13858d8c..68615426ea 100644 --- a/plugins/scaffolder/src/components/RenderSchema/RenderSchema.test.tsx +++ b/plugins/scaffolder/src/components/RenderSchema/RenderSchema.test.tsx @@ -146,13 +146,10 @@ describe('JSON schema UI rendering', () => { const allCells = [...headerCells, ...dataCells]; const cellTexts = allCells.map(c => c.textContent); - expect(cellTexts).toEqual( - expect.arrayContaining([ - expect.stringContaining(p), - expect.stringContaining(`the ${pt}`), - expect.stringContaining(String(pt)), - ]), - ); + expect(cellTexts[0]).toContain(p); + const valueCell = cellTexts[1]; + expect(valueCell).toContain(String(pt)); + expect(valueCell).toContain(`the ${pt}`); if (basic.required?.includes(p)) { expect(cellTexts[0]).toContain('*'); diff --git a/plugins/scaffolder/src/components/RenderSchema/RenderSchema.tsx b/plugins/scaffolder/src/components/RenderSchema/RenderSchema.tsx index 5b8a84c49f..4c4c977065 100644 --- a/plugins/scaffolder/src/components/RenderSchema/RenderSchema.tsx +++ b/plugins/scaffolder/src/components/RenderSchema/RenderSchema.tsx @@ -257,19 +257,12 @@ export const RenderSchema = ({ elements = [{ schema }]; columns = [ { - key: 'type', - title: t('renderSchema.tableCell.type'), - render: renderTypeCell, + key: 'value', + title: t('renderSchema.tableCell.value'), + render: renderValueCell, + width: '3fr', }, ]; - if (schema.description) { - columns.unshift({ - key: 'description', - title: t('renderSchema.tableCell.description'), - render: renderDescriptionCell, - width: '3fr', - }); - } } } else if (schema.properties) { columns = [ @@ -279,16 +272,11 @@ export const RenderSchema = ({ render: renderNameCell, }, { - key: 'description', - title: t('renderSchema.tableCell.description'), - render: renderDescriptionCell, + key: 'value', + title: t('renderSchema.tableCell.value'), + render: renderValueCell, width: '3fr', }, - { - key: 'type', - title: t('renderSchema.tableCell.type'), - render: renderTypeCell, - }, ]; elements = Object.entries(schema.properties!).map(([key, v]) => ({ schema: v, @@ -303,89 +291,35 @@ export const RenderSchema = ({ return ( {columns && elements && ( - <> - - - {columns.map((col, index) => ( - - {col.title} - - ))} - - - {elements.map(el => ( - - {col => col.render(el, context)} - - ))} - - - {elements.map(el => { - const id = generateId(el, context); - const info = inspectSchema(el.schema); - const hasDetails = - typeof el.schema !== 'boolean' && - (info.canSubschema || info.hasEnum); - const s = - typeof el.schema !== 'boolean' - ? (el.schema as JSONSchema7) - : undefined; - const isOpen = - hasDetails && s && (!getTypes(s) || isExpanded[id]); - - if (!isOpen) { - return null; - } - - return ( -
+ + {columns.map((col, index) => ( + - {info.canSubschema && ( - - )} - {info.hasEnum && ( - <> - - Valid values: - - - - )} -
- ); - })} - + {col.title} + + ))} + + + {elements.map(el => ( + + {col => col.render(el, context)} + + ))} + + )} {(Object.keys(subschemas) as Array).map(sk => { const subId = `${context.parentId}_${sk}`; @@ -433,6 +367,55 @@ export const RenderSchema = ({ return result ?? No schema defined; }; +function RenderExpansion({ + element, + context, +}: { + element: SchemaRenderElement; + context: SchemaRenderContext; +}) { + const id = generateId(element, context); + const info = inspectSchema(element.schema); + const hasDetails = + typeof element.schema !== 'boolean' && (info.canSubschema || info.hasEnum); + const s = + typeof element.schema !== 'boolean' + ? (element.schema as JSONSchema7) + : undefined; + const [isExpanded] = context.expanded; + const isOpen = hasDetails && s && (!getTypes(s) || isExpanded[id]); + + if (!isOpen) { + return null; + } + + return ( +
+ {info.canSubschema && ( + + )} + {info.hasEnum && ( + <> + + Valid values: + + + + )} +
+ ); +} + function renderNameCell( element: SchemaRenderElement, _context: SchemaRenderContext, @@ -441,17 +424,7 @@ function renderNameCell( return ; } -function renderDescriptionCell(element: SchemaRenderElement) { - return ( - - - - ); -} - -function renderTypeCell( +function renderValueCell( element: SchemaRenderElement, context: SchemaRenderContext, ) { @@ -462,36 +435,41 @@ function renderTypeCell( const [isExpanded, setIsExpanded] = context.expanded; const id = generateId(element, context); const info = inspectSchema(element.schema); + const description = element.schema.description; return ( - - {types?.map((type, index) => - (info.canSubschema || info.hasEnum) && index === 0 ? ( - - ) : ( - - {type} - - ), - )} + + + {types?.map((type, index) => + (info.canSubschema || info.hasEnum) && index === 0 ? ( + + ) : ( + + {type} + + ), + )} + + {description && } + ); diff --git a/plugins/scaffolder/src/translation.ts b/plugins/scaffolder/src/translation.ts index 0b19082d8f..ea934e9ffd 100644 --- a/plugins/scaffolder/src/translation.ts +++ b/plugins/scaffolder/src/translation.ts @@ -203,6 +203,7 @@ export const scaffolderTranslationRef = createTranslationRef({ title: 'Title', description: 'Description', type: 'Type', + value: 'Value', }, undefined: 'No schema defined', },