From 58e1cf143dd7ac59dfe08fcaa0fae94c9d81b049 Mon Sep 17 00:00:00 2001 From: zignd Date: Sat, 10 Oct 2026 19:41:54 -0300 Subject: [PATCH] docs: finding clipped and overflowing text; agent text for the layout loop Refs #14. --- docs/agents.md | 4 ++++ docs/layout-and-sizing.md | 23 +++++++++++++++++++++++ docs/llms-full.txt | 4 ++++ tools/Forma.Xaml.Tool/AgentKit.cs | 4 ++++ 4 files changed, 35 insertions(+) diff --git a/docs/agents.md b/docs/agents.md index 7f7f9fe2..65b9482d 100644 --- a/docs/agents.md +++ b/docs/agents.md @@ -53,6 +53,7 @@ animation targets one `#id`. In a shared `.fcss` the id must belong to the root | Check a view or stylesheet | `forma-xaml validate [--format human|json|sarif] ` | | Format | `forma-xaml format [--check] ` | | Render one view | `forma-xaml preview View.fhtml -o out.png [--state hover] [--lang ja] [--scale 130] [--size 1280x720]` | +| Find clipped or overflowing text | `forma-xaml validate --layout View.fhtml [--lang ja] [--scale 130] [--size 1280x720]`; in a test `UIContext.FindLayoutProblems` and `UiMatrix.Run`; in the live app a game MCP `ui_layout_problems` when the game provides it | | Reference docs | `forma-xaml docs --out docs` (regenerates); `forma-xaml docs --out docs --check` (drift) | | Find controls in the live app | game MCP `game_ui` `ui-query button=` | | Why is a rule (not) applied | game MCP `game_ui` `ui-inspect button=` | @@ -63,6 +64,9 @@ animation targets one `#id`. In a shared `.fcss` the id must belong to the root Preview renders with the application, so give it a long timeout (3 minutes) and read the PNG afterwards. A view with no scene in the project's preview host cannot be previewed; preview the nearest screen and say so. +After any layout change, run the layout check for every language and UI scale the game ships, plus the pseudo-locale +(`PseudoLocalizer`), and fix the layout; do not shorten text to pass. + The `forma-xaml mcp` server exposes `validate`, `format`, `preview` and the generated docs to any MCP client. # Troubleshooting diff --git a/docs/layout-and-sizing.md b/docs/layout-and-sizing.md index 3fc22692..3be4c8b1 100644 --- a/docs/layout-and-sizing.md +++ b/docs/layout-and-sizing.md @@ -57,6 +57,29 @@ is still zero adopts that logical viewport. Set `UIContext.DisplayScale` to phys logical UI coordinate; the default is `1`. Forma maps pointer input back to logical coordinates, scales drawing, invalidates scale-sensitive layout, and refreshes device-scoped glyph resources. +## Finding clipped and overflowing text + +Text that is clipped or pushed outside its box depends on the language, the UI scale and the window size together, so it is +caught by a test, not by eye. + +- `Label.TextFit` says whether a label's text fits the box layout gave it: `Fits`, `Wrapped`, trimmed with an ellipsis, or `Clipped`, with the + measured and available sizes and the overflow. Read it after layout. +- `UIContext.FindLayoutProblems(root)` walks a laid-out view and returns each `LayoutProblem`: text clipped or wrapped past its + box, a control past its parent, past an ancestor that clips it, or past the viewport. Each item carries the control, its name and + classes, the overflow in pixels and a message. `LayoutProblemOptions` selects the kinds, the tolerance and whether scrolling + containers are ignored. +- `PseudoLocalizer` makes every string longer, accented and wrapped in markers (and can mirror it for right to left) without a real + translation, so a layout that only fits the source language fails in a test first. Placeholders such as `{0}` survive. +- `UiMatrix.Run` (in `Forma.Testing`) lays every view out for every locale, UI scale and viewport and runs a check, with + `UiMatrix.LayoutProblems()` as the ready-made check. A failure names the view, locale, scale and viewport. +- `DynamicTextCoverage.FindMissingGlyphs` lists the characters of a set of strings that no face of a font stack covers. +- `forma-xaml validate --layout View.fhtml [--lang l] [--scale n] [--size WxH]` validates the markup and then runs the project's + `layoutHost` (named in `forma-preview.json`), which lays the view out with the application's types and prints the findings. A + game can expose the same findings from its MCP server as `ui_layout_problems`. + +The loop for a layout change: edit, `forma-xaml validate`, run the layout check for the languages and scales you ship (and the +pseudo-locale), fix the layout, not the text. + ## Common mistakes - Do not use `Size` as a minimum inside a container; use `CustomMinimumSize` or scalar minimums. diff --git a/docs/llms-full.txt b/docs/llms-full.txt index 686a27a3..1f5871c1 100644 --- a/docs/llms-full.txt +++ b/docs/llms-full.txt @@ -55,6 +55,7 @@ animation targets one `#id`. In a shared `.fcss` the id must belong to the root | Check a view or stylesheet | `forma-xaml validate [--format human|json|sarif] ` | | Format | `forma-xaml format [--check] ` | | Render one view | `forma-xaml preview View.fhtml -o out.png [--state hover] [--lang ja] [--scale 130] [--size 1280x720]` | +| Find clipped or overflowing text | `forma-xaml validate --layout View.fhtml [--lang ja] [--scale 130] [--size 1280x720]`; in a test `UIContext.FindLayoutProblems` and `UiMatrix.Run`; in the live app a game MCP `ui_layout_problems` when the game provides it | | Reference docs | `forma-xaml docs --out docs` (regenerates); `forma-xaml docs --out docs --check` (drift) | | Find controls in the live app | game MCP `game_ui` `ui-query button=` | | Why is a rule (not) applied | game MCP `game_ui` `ui-inspect button=` | @@ -65,6 +66,9 @@ animation targets one `#id`. In a shared `.fcss` the id must belong to the root Preview renders with the application, so give it a long timeout (3 minutes) and read the PNG afterwards. A view with no scene in the project's preview host cannot be previewed; preview the nearest screen and say so. +After any layout change, run the layout check for every language and UI scale the game ships, plus the pseudo-locale +(`PseudoLocalizer`), and fix the layout; do not shorten text to pass. + The `forma-xaml mcp` server exposes `validate`, `format`, `preview` and the generated docs to any MCP client. # Troubleshooting diff --git a/tools/Forma.Xaml.Tool/AgentKit.cs b/tools/Forma.Xaml.Tool/AgentKit.cs index aaf1f75e..77cc9dac 100644 --- a/tools/Forma.Xaml.Tool/AgentKit.cs +++ b/tools/Forma.Xaml.Tool/AgentKit.cs @@ -135,6 +135,7 @@ private static string Tooling() => """ | Check a view or stylesheet | `forma-xaml validate [--format human|json|sarif] ` | | Format | `forma-xaml format [--check] ` | | Render one view | `forma-xaml preview View.fhtml -o out.png [--state hover] [--lang ja] [--scale 130] [--size 1280x720]` | + | Find clipped or overflowing text | `forma-xaml validate --layout View.fhtml [--lang ja] [--scale 130] [--size 1280x720]`; in a test `UIContext.FindLayoutProblems` and `UiMatrix.Run`; in the live app a game MCP `ui_layout_problems` when the game provides it | | Reference docs | `forma-xaml docs --out docs` (regenerates); `forma-xaml docs --out docs --check` (drift) | | Find controls in the live app | game MCP `game_ui` `ui-query button=` | | Why is a rule (not) applied | game MCP `game_ui` `ui-inspect button=` | @@ -145,6 +146,9 @@ private static string Tooling() => """ Preview renders with the application, so give it a long timeout (3 minutes) and read the PNG afterwards. A view with no scene in the project's preview host cannot be previewed; preview the nearest screen and say so. + After any layout change, run the layout check for every language and UI scale the game ships, plus the pseudo-locale + (`PseudoLocalizer`), and fix the layout; do not shorten text to pass. + The `forma-xaml mcp` server exposes `validate`, `format`, `preview` and the generated docs to any MCP client. """;