Skip to content

Fix Markdown list content wrapping - #1197

Merged
Alexandre Zollinger Chohfi (azchohfi) merged 2 commits into
microsoft:mainfrom
bkudiess:bkudiess-reactor-markdown-wrapping
Sep 11, 2026
Merged

Alexandre Zollinger Chohfi (azchohfi) merged 2 commits into
microsoft:mainfrom
bkudiess:bkudiess-reactor-markdown-wrapping

Conversation

@bkudiess

Copy link
Copy Markdown
Contributor

Summary

Fix long Markdown list items clipping even though their full text is present and wrapping is enabled. The previous horizontal StackPanel measured content with infinite width; the default list row now uses native Auto/Star Grid columns so the marker keeps its natural width and content receives the finite remainder.

Preserve marker formatting, the four-DIP gap, top alignment, block contents, selection, and the post-construction ListItem hook. Keep the single row implicit to avoid triggering the existing layout-footgun heuristic for valid multi-block list content. No parser changes, hardcoded content widths, custom panels, or app-specific workarounds.

Linked issue / spec

Related to openclaw/openclaw-windows-node#1362. Consumer package adoption and workaround removal are separate from this upstream fix.

Test plan

  • Reproduced the original failure in Reactor's native selftest host. Replacing the fixed row with the original HStack makes the final wrapping oracles fail (89 failed assertions across eight wrapping cases).
  • Added native coverage for plain/bold bullets, ordered markers starting at 9, loose and nested lists, code blocks, task lists, unified rich text, and short intrinsic-width lists. Checked complete native text, final-character geometry, marker placement, and 686 -> 320 -> 686 resizing.
  • Compared explicit Auto and implicit single rows in native default/unified documents: desired sizes, arranged bounds, and final-character rectangles match.
  • Added callback-wrapper and diagnostic regression tests; the latter fail with the explicit Auto row and verify that subsequent real layout offenders still warn. Strengthened the complex-document table assertion so list-item Grids cannot satisfy it.
  • Focused Markdown and layout-diagnostic unit suites: 192 passed, 0 failed, 0 skipped.
  • Complete unit suite: 13,901 passed, 0 failed, 64 declared skips.
  • Native Markdown corpus: 36 fixtures, 399 checks, 0 failures, 0 fixture skips.
  • Separate dotnet restore Reactor.slnx, followed by dotnet build Reactor.slnx --no-restore -c Release -p:SkipSignaturesGen=true: succeeded with 0 errors and 2 WIN2D0001 AnyCPU warnings in Devtools/Chat.UI. Debug native/unit builds also succeeded.
  • Regenerated only the affected guide topic through mur docs compile --topic text-and-media --ci with build/capture/AI/diagram/reference steps disabled; no lint findings or unrelated snippet changes.
  • Packaged/MSIX, NativeAOT, screenshot, and input-driven E2E runs were not performed locally.

Risk / breaking changes

MarkdownOptions.ListItem retains its Element -> Element signature and invocation order, but its default concrete input changes from StackElement to GridElement. Callbacks that explicitly cast the old default must adapt. This is documented in the XML comments, guide, and changelog.

The fix requires a finite available width from the outer host; it does not promise wrapping inside an unbounded horizontal host. No diagnostics algorithm changes or new public API signatures are introduced.

Use native Auto/Star Grid rows to constrain list content while preserving markers and callbacks. Add native layout and diagnostic regressions, and document the default callback shape change.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The focused layout change is correct, documented, and comprehensively covered across element-shape, diagnostic, and native rendering tests.

Pull request overview

Fixes Markdown list-item clipping by replacing horizontal stacks with finite-width Auto/Star grids.

Changes:

  • Updates default list-row layout while preserving markers, spacing, alignment, and callbacks.
  • Adds extensive unit and native layout regression coverage.
  • Updates generated documentation and changelog guidance.
File summaries
File Description
src/Reactor.Advanced/Markdown/MarkdownBuilder.cs Implements Auto/Star list rows.
tests/Reactor.Tests/MarkdownBuilderTests.cs Verifies list structure and callbacks.
tests/Reactor.Tests/MarkdownUnifiedRichTextTests.cs Verifies unified list structure.
tests/Reactor.Tests/LayoutFootgunDetectorTests.cs Guards implicit-row diagnostics behavior.
tests/Reactor.AppTests.Host/SelfTest/Fixtures/MarkdownListLayoutFixtures.cs Exercises native wrapping and resizing.
tests/Reactor.AppTests.Host/SelfTest/SelfTestFixtureRegistry.cs Registers new selftests.
tests/Reactor.AppTests.Host/SelfTest/Fixtures/MarkdownFixtures.cs Updates native structural assertions.
docs/_pipeline/templates/text-and-media.md.dt Updates source documentation.
docs/guide/text-and-media.md Regenerates the affected guide.
CHANGELOG.md Documents the fix and callback compatibility impact.
Review details
  • Files reviewed: 10/10 changed files
  • Comments generated: 0
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Compare RowMeasureEquivalence layout snapshots within a 0.5 DIP tolerance instead of exact floating-point equality, so two independent mounts cannot diverge on sub-pixel rounding across DPI or font fallback. Mutation-checked: pointing the comparison at a mismatched baseline reddens the checks.

State the list-row comment as the design intent the tests establish (the Star column supplies the finite remaining width) rather than asserting StackPanel measure behaviour no in-repo test covers.

Assert that the Markdown rows keep implicit rows, since that is what the adjacent no-warning assertion depends on: the footgun detector only warns on an explicit Auto track.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 27eebfaf-4856-44c4-9af5-e9bf1123a12c
@azchohfi
Alexandre Zollinger Chohfi (azchohfi) merged commit 323b7d7 into microsoft:main Sep 11, 2026
27 of 28 checks passed
Alexandre Zollinger Chohfi (azchohfi) added a commit that referenced this pull request Sep 11, 2026
Cut `## [Unreleased]` to `## [0.1.0-preview.15] — 2026-09-11`, open a fresh
`Unreleased` block with all six Keep-a-Changelog buckets, bump the single
source-of-truth `<ReactorPublicVersion>` in the root `Directory.Build.props`,
and recompile the guide so the `{{reactorVersion}}` token matches.

Changelog coverage audit over the 21 commits since `v0.1.0-preview.14`: no
entries were missing. Every commit that touched shipped product source
(`src/Reactor*`, `tools/Templates`, `Directory.Build.props`) already carried a
changelog entry — #1191, #1194, #1195, #1196, #1197 — and the probe was
positive-controlled by re-running it without the changelog filter, which
matched all five. The 15 commits without an entry are dependency bumps
(10 Dependabot npm bumps under `tests/` and `samples/`, one `@types/node`
devDependency under `src/vscode-reactor`, and two `Directory.Packages.props`
commits that are CLI/test-only and net-zero on `GitHub.Copilot.SDK`), CI
infrastructure (#1178, which regenerated only a sourcemap, not `extension.js`),
test-harness lint and lockfile work (#1176, #1169), and a sample Node server
fix (#1175) — none of which reaches a published package.

The two `Fixed`-bucket product changes were adjudicated against the previous
tag rather than by issue filing date, to confirm they had genuinely shipped
broken rather than being introduced and fixed inside this window:

  * #1197 — `v0.1.0-preview.14:src/Reactor.Advanced/Markdown/MarkdownBuilder.cs`
    contains the `HStack(4, ...)` list row, so the infinite-width measure shipped.
  * #1195 — `v0.1.0-preview.14:src/Reactor.Analyzers/ModifierTable.cs` contains
    both the `["Stretch"]` and `["IsHitTestVisible"]` exclusions, and
    `v0.1.0-preview.14:src/Reactor/Core/ElementPool.cs` contains the
    `if (fe is Control tabStopControl)` gate, so both shipped.

Docs regeneration produced exactly 12 `{{reactorVersion}}` substitutions across
8 guide pages and no other churn.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants