Found while measuring objectui#5415 (record-grid row heights); a different defect class, filed separately and not fixed there.
Measured
Real browser (Chromium, apps/console vite dev, ObjectGrid with inline data and a mock getObjectSchema). One row, one column, the stored value is the showcase seed's own richtext specimen (examples/app-showcase/src/data/seed/index.ts, f_richtext):
value stored: p-wrapped Rich + strong-wrapped text
| column field type |
cell textContent |
cell inner HTML |
richtext |
"" (empty) |
div.prose … empty |
html |
Rich text |
div.prose containing the real p / strong markup |
markdown (control, markdown-shaped input **bold** and _em_) |
bold and em |
rendered markup |
So a populated richtext field shows the user nothing at all in a grid cell. Neighbouring html — same stored bytes, different declared type — renders it correctly, which is what rules out "the value never arrived".
Mechanism
packages/fields/src/index.tsx, getCellRenderer's standard map:
markdown: MarkdownCellRenderer,
html: HtmlCellRenderer,
richtext: MarkdownCellRenderer, <-- here
richtext stores HTML (that is what RichTextField writes, and what the showcase seed carries), but it is dispatched to the markdown renderer, which hands the string to the sanitizing GFM pipeline (MarkdownContent). Raw HTML is dropped there, and since the value is entirely HTML, everything is dropped and the cell renders empty. The title attribute on the shared cell wrapper still carries the raw string, so the value is reachable on hover — which is why this reads as a styling nit rather than data loss until you look at the cell body.
HtmlCellRenderer already exists two functions below and handles exactly this shape (it sanitizes with sanitizeHtml and keeps the markup).
Why it matters
Failure direction is the bad one: no error, no fallback, no console warning — a populated field reads as an empty field. Anyone auditing data through a grid concludes the records are blank.
Note
Do not "fix" this by making the markdown pipeline pass raw HTML through — that would change every markdown cell's trust boundary. The question is which renderer richtext should map to, and that is a one-line decision in the map above (plus whatever the read side of the detail page does with the same type — not checked here).
Repro harness was untracked and removed; it is ~40 lines of ObjectGrid with data: { provider: 'value', items } plus a getObjectSchema stub, following the existing apps/console/src/dev/DevRowActions.tsx pattern.
Found while measuring objectui#5415 (record-grid row heights); a different defect class, filed separately and not fixed there.
Measured
Real browser (Chromium,
apps/consolevite dev,ObjectGridwith inline data and a mockgetObjectSchema). One row, one column, the stored value is the showcase seed's own richtext specimen (examples/app-showcase/src/data/seed/index.ts,f_richtext):value stored:
p-wrappedRich+strong-wrappedtexttextContentrichtext""(empty)div.prose… emptyhtmlRich textdiv.prosecontaining the realp/strongmarkupmarkdown(control, markdown-shaped input**bold** and _em_)bold and emSo a populated
richtextfield shows the user nothing at all in a grid cell. Neighbouringhtml— same stored bytes, different declared type — renders it correctly, which is what rules out "the value never arrived".Mechanism
packages/fields/src/index.tsx,getCellRenderer's standard map:richtextstores HTML (that is whatRichTextFieldwrites, and what the showcase seed carries), but it is dispatched to the markdown renderer, which hands the string to the sanitizing GFM pipeline (MarkdownContent). Raw HTML is dropped there, and since the value is entirely HTML, everything is dropped and the cell renders empty. Thetitleattribute on the shared cell wrapper still carries the raw string, so the value is reachable on hover — which is why this reads as a styling nit rather than data loss until you look at the cell body.HtmlCellRendereralready exists two functions below and handles exactly this shape (it sanitizes withsanitizeHtmland keeps the markup).Why it matters
Failure direction is the bad one: no error, no fallback, no console warning — a populated field reads as an empty field. Anyone auditing data through a grid concludes the records are blank.
Note
Do not "fix" this by making the markdown pipeline pass raw HTML through — that would change every
markdowncell's trust boundary. The question is which rendererrichtextshould map to, and that is a one-line decision in the map above (plus whatever the read side of the detail page does with the same type — not checked here).Repro harness was untracked and removed; it is ~40 lines of
ObjectGridwithdata: { provider: 'value', items }plus agetObjectSchemastub, following the existingapps/console/src/dev/DevRowActions.tsxpattern.