Repository navigation
fix(plugin-detail): record:details read mode shows a textarea value with its line breaks (objectui#11577) - #11602
Merged
objectstack-fleet[bot] merged 3 commits intoOct 4, 2026
Conversation
… TextAreaField's read display (objectui#11577) Read mode resolved `textarea` through `getCellRenderer`, which maps it to `TextCellRenderer`, the grid's one-line truncating cell, so a multi-line note read as one paragraph on the record page. The details row now routes `textarea` to `TextAreaField`'s own `readonly` branch, the read half of what `InlineFieldInput` does for edit mode (objectui#11562). The grid's mapping is unchanged. Claude-Session: https://claude.ai/code/session_01FjqrwXPfSMkSfkKYDSRkN2 Co-authored-by: Claude <noreply@anthropic.com>
…objectui#11577) Claude-Session: https://claude.ai/code/session_01FjqrwXPfSMkSfkKYDSRkN2 Co-authored-by: Claude <noreply@anthropic.com>
… pin (objectui#11577) Claude-Session: https://claude.ai/code/session_01FjqrwXPfSMkSfkKYDSRkN2 Co-authored-by: Claude <noreply@anthropic.com>
Contributor
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
objectstack-fleet
Bot
deleted the
claude/issue-11577-textarea-read-breaks
branch
October 4, 2026 09:30
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #11577
Clause-②: no
What changed
record:detailsread mode now draws atextareavalue through the fields package's own read display: thereadonlybranch ofTextAreaField, the display the record form shows a read-only textarea with. This is the read-mode half of objectui#11562, which routed edit mode to the same widget's editor.DetailSectionis the one read path therecord:detailsbody draws a value through. A row whose resolved renderer type istextareanow rendersTextAreaFieldwithreadonly, ahead of thegetCellRendererlookup. Every other type keeps its cell renderer, unchanged.String(coerceToSafeValue(value)), the exact textTextCellRendererdrew. A string passes byte for byte; a non-string value reads as it did before instead of reaching React as an object.whitespace-pre-wrapcopy inplugin-detail: the widget owns its read display.TextAreaFieldis already exported from@object-ui/fieldsand already imported by this package (the inline editor), so no package index export moves andTextAreaField.tsxis untouched.textareatoTextCellRenderer. That is the grid cell, where one line is the intended shape, so grids are unchanged.Why
The read row resolved
textareathroughgetCellRenderer, whose standard table maps it toTextCellRenderer: a one-linetruncatecell (white-spacenowrapplus an ellipsis). A stored note with a blank line and a trailing newline read as one line on the record page, while the record form's read-only field and, since objectui#11562, the inline editor both kept the breaks.Evidence
Real browser, Chromium
The console dev server served a scratch page (untracked, deleted after the run) that mounts the real
RecordDetailViewwith a stub data source. Objectshowcase_taskdeclaresnotesandshort_noteastextareaandremarkastext;notesandremarkhold the same multi-line value. Read: the value cell'sinnerText, and the computedwhite-spaceof the element that draws it. The before leg is the ablation below (the old read path), served by the same dev server. Desktop (1280 px) and mobile (375 px) read identically.textarea, multi-line"Call back Monday. Budget approved, needs legal review.",nowrap"Call back Monday.\n\nBudget approved, needs legal review.\n",pre-wraptextarea, one line"Call back Monday.",nowrap"Call back Monday.",pre-wraptext, multi-line (control)"Call back Monday. Budget approved, needs legal review.",nowrapThe before reading of Notes is the card's reported reading, character for character.
Pins
packages/plugin-detail/src/renderers/__tests__/record-details.textareaReadDisplay-11577.test.tsxmounts the realRecordDetailsRendererwith bare field names, so each row's type is the one the bound object declares, read through a data-source double as a running app reads it. Desktop and mobile each:TextAreaFieldrenders read-only for that value, on its own;truncate,whitespace-nowraporwhitespace-normal;Plus two controls:
textstill rendersTextCellRenderer's markup for a multi-line value, andemailstill rendersEmailCellRenderer's (which also shows the declared types reached the rows).897bd53: 8 passed (8).node ../objectstack/scripts/ablation-replace.mjs, wrapped in a shell trap that restores fromHEAD): anchorif (resolvedType === 'textarea') {replaced by a type no field has, anchor count 1 to 0, bloba9dc7b51to3699ca2e. Result: 4 failed, 4 passed. The four reds are the two multi-line pins on desktop and on mobile; the single-line control and thetextandemailcontrols stay green. Restore: bloba9dc7b51equalsHEAD's,git diff HEADempty.2e818d0, before the single-line control was narrowed to assert text only, read 6 failed, 2 passed.Gates
Local runs, all at
897bd53(the final commit) unless named. Verify-lock runs give theirVERDICTline.pnpm exec vitest run --maxWorkers=2 packages/plugin-detail/(whole package, atf535ade;DetailSection.tsxis byte-identical since): Test Files 234 passed, 1 skipped (235); Tests 2321 passed, 8 skipped (2329);VERDICT command-exit 0.@object-ui/plugin-detailor the detail renderers and by source-text read ofplugin-detailpaths: Test Files 73 passed (73); Tests 2726 passed (2726);VERDICT command-exit 0.pnpm --workspace-concurrency=2 --filter "@object-ui/plugin-detail^..." build: exit 0.pnpm --filter @object-ui/plugin-detail type-check(tsc --noEmit && tsc -p tsconfig.test.json): exit 0. The test project lists the new pin (--listFiles, 1 hit) and compiles at897bd53.check:control-bytes,check:new-line-citations(0 new citations),check:changeset-claims,check:pending-changeset-literals,check:phantom-deps,check:self-import,check:unreferenced-sources,check:handler-key-reads,check:test-path-roots,check:vi-mock-override-shape,check:vi-mock-specifiers,check:vi-mock-inherit,check:i18n-keys, andscripts/check-changeset-presence.mjs(2 source files of 1 released package changed, 1 changeset declared),check-changeset-fixed,check-changeset-no-major,check-type-check-coverage.eslint.config.js: the package has no config of its own, and itseslint .resolves the root one. The file count is 2, read from--format json. Both files report 0 errors. The test file has 0 warnings.DetailSection.tsxhas 12 warnings, all on lines outside this diff's hunks. Invariance: the config enables no type-aware linting (zero hits forprojectService,parserOptionsorTypeChecked), so this diff cannot move a verdict on an untouched file. The repo-widepnpm lintbelongs to CI.Acceptance notes
TextAreaField's read block carriestext-sm, so on the mobile grouped-inset row atextareavalue draws attext-smwhere the row's span sets 15 px. Left as is: changing it means editingTextAreaFieldbeyond reaching its read branch, or a per-surface class, which is the second copy the ruling refuses. Observation only.textareacell renderer (registerFieldRendererwith'textarea') would no longer reach this row, because the routing comes beforegetCellRenderer. Measured producers: zero.git grepfor that call withtextareareturns 0 hits; the same search forlookupreturns 2.HeaderHighlight,record:highlights) still draws atextareavalue throughTextCellRenderer, as one line with an ellipsis. Not this card's surface (the card namesrecord:details), and the strip is a compact chip band. Observation, not filed.content/docsor the package README describes how the details body reads atextarea, so no docs change is needed.Not touched
TextAreaField.tsx, the@object-ui/fieldsand@object-ui/plugin-detailpackage indexes, the grid's cell-renderer table, and themarkdown/htmlread paths.Implemented by the dispatched dev run in session
https://claude.ai/code/session_01FjqrwXPfSMkSfkKYDSRkN2, on claim branchclaude/issue-11577-textarea-read-breaks.Generated by Claude Code