From b3d7d340b14f8770670ea6153ff5afaa94a441db Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 24 Oct 2026 08:19:20 +0000 Subject: [PATCH 1/2] spec(ui): record:details hideEmpty describe states the ruled read-only fold for false Co-authored-by: Claude Claude-Session: https://claude.ai/code/session_01PC4NPXPgPmpDRG9DdDnyXT --- packages/spec/src/ui/component.zod.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/spec/src/ui/component.zod.ts b/packages/spec/src/ui/component.zod.ts index 2d039146d85..7ddfd71998d 100644 --- a/packages/spec/src/ui/component.zod.ts +++ b/packages/spec/src/ui/component.zod.ts @@ -1436,8 +1436,19 @@ export const RecordDetailsProps = strictObject({ * asked for the default". Defaults in the describe() texts are MEASURED on * the renderer (read points recorded in `liveness/page.json`, row * `regions`), not transcribed from a TS interface. + * + * What `hideEmpty: false` renders was re-ruled (ruling C on + * objectstack-ai/objectui#13386, maintainer 2026-10-23): in read-only mode + * an all-empty section renders its heading plus ONE fold row — the same + * fold a partly-filled section uses — instead of a column of empty rows; + * edit mode is unchanged and renders every row, editable. No key, shape or + * default changed, and the describe() states the ruled rendering, which + * objectui's `DetailSection` follows. The key governs only the ALL-empty + * case: a partly-filled section's empty rows follow the renderer's own + * fold (objectui#7129 Q2-C) in either polarity, so the old lead "hide this + * section's empty fields" no longer told the two values apart. */ - hideEmpty: z.boolean().optional().describe('Hide this section\'s empty fields (renderer default: on — and a section whose fields are ALL empty then renders nothing at all: no heading, no skeleton). Set `false` to render empty rows, keeping the section\'s label skeleton on an all-empty record (e.g. a brand-new one).'), + hideEmpty: z.boolean().optional().describe('Whether this section disappears when ALL its fields are empty (renderer default: on — it then renders nothing at all: no heading, no skeleton). Set `false` to keep it on an all-empty record (e.g. a brand-new one): in read-only mode it renders its heading plus one fold row that counts the empty fields and reveals them on request — the same fold a partly-filled section uses; in edit mode it renders every field as an editable row.'), /** Collapsible card. Initial state is expanded; the toggle is the heading. */ collapsible: z.boolean().optional().describe('Render this section as a collapsible card — the heading becomes a chevron toggle, initially expanded (renderer default: off).'), /** Card chrome; the renderer derives it from the presence of a title. */ From 0e6e092fedf775f3db43c4a7a3313880182c6c8f Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 24 Oct 2026 08:23:39 +0000 Subject: [PATCH 2/2] spec(ui): regenerate the ui component reference and add the hideEmpty changeset Co-authored-by: Claude Claude-Session: https://claude.ai/code/session_01PC4NPXPgPmpDRG9DdDnyXT --- .changeset/25511-hide-empty-describe.md | 17 +++++++++++++++++ content/docs/references/ui/component.mdx | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 .changeset/25511-hide-empty-describe.md diff --git a/.changeset/25511-hide-empty-describe.md b/.changeset/25511-hide-empty-describe.md new file mode 100644 index 00000000000..a4648f0199c --- /dev/null +++ b/.changeset/25511-hide-empty-describe.md @@ -0,0 +1,17 @@ +--- +'@objectstack/spec': minor +--- + +spec(ui): `record:details` section `hideEmpty: false` — in read-only mode an all-empty section renders its heading plus one fold row, and the `describe()` text says so + +Clause-②: no +Metadata-protocol: semantic + +The meaning of `hideEmpty: false` on a `record:details` section changes for a section whose fields are ALL empty (for example on a brand-new record): + +- **Read-only mode:** the section renders its heading plus one fold row that counts the empty fields and reveals them on request — the same fold a partly-filled section already uses. It no longer renders a column of empty rows. +- **Edit mode:** unchanged. Every field renders as an editable row. + +Nothing else changes. No key is added, removed or renamed; the shape and the default are the same. Leaving `hideEmpty` out (or writing `true`) still means an all-empty section renders nothing at all: no heading, no skeleton. A partly-filled section's empty rows are not governed by this key, in either value. Authored metadata needs no change: a section that writes `hideEmpty: false` to keep its heading on an empty record keeps it. + +The `describe()` text, which the reference docs and the JSON Schema read, now states this. Its lead changes from "Hide this section's empty fields" to "Whether this section disappears when ALL its fields are empty", because under the new reading both values hide an all-empty section's empty rows in read-only mode and the old lead no longer told them apart. The renderer change is in objectui's record detail section. diff --git a/content/docs/references/ui/component.mdx b/content/docs/references/ui/component.mdx index d69833958ae..0b629cd2a3f 100644 --- a/content/docs/references/ui/component.mdx +++ b/content/docs/references/ui/component.mdx @@ -1697,7 +1697,7 @@ View filter rule | **columns** | `integer` | optional | Field-grid columns for this section (1-4). Omitted → the renderer derives the width. | | **group** | `string` | optional | Field group key (snake_case) whose members and presentation this section inherits, from the object's `fieldGroups` (ADR-0085 §5 `deriveFieldGroupLayout`). Mutually exclusive with `fields`, and with every key the group itself declares (`name`, `label`, `icon`, `description`, `collapsible`, `defaultCollapsed`). Must name a declared group — checked by reference diagnostics. | | **fields** | `string[]` | optional | Field names rendered in this section, in order. Omit only when `group` supplies the members instead. | -| **hideEmpty** | `boolean` | optional | Hide this section's empty fields (renderer default: on — and a section whose fields are ALL empty then renders nothing at all: no heading, no skeleton). Set `false` to render empty rows, keeping the section's label skeleton on an all-empty record (e.g. a brand-new one). | +| **hideEmpty** | `boolean` | optional | Whether this section disappears when ALL its fields are empty (renderer default: on — it then renders nothing at all: no heading, no skeleton). Set `false` to keep it on an all-empty record (e.g. a brand-new one): in read-only mode it renders its heading plus one fold row that counts the empty fields and reveals them on request — the same fold a partly-filled section uses; in edit mode it renders every field as an editable row. | | **collapsible** | `boolean` | optional | Render this section as a collapsible card — the heading becomes a chevron toggle, initially expanded (renderer default: off). | | **showBorder** | `boolean` | optional | Draw this section's card chrome (renderer default: derived — on for a titled section, off for an untitled one). Set `false` for a borderless titled section, or `true` for a bordered untitled one. | | **defaultCollapsed** | `boolean` | optional | Start a `collapsible: true` section collapsed (renderer default: expanded). Consulted only when `collapsible` is on — a non-collapsible section never reads its collapse state. |