From 1c4713fb3dfad627ed62116cc289a729100296ee Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Apr 2026 14:46:32 +0000 Subject: [PATCH 1/4] Bump ReportGenerator from 5.5.5 to 5.5.6 --- updated-dependencies: - dependency-name: ReportGenerator dependency-version: 5.5.6 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index b643ffb44f..2fb3bb63be 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -40,7 +40,7 @@ - + From 7fca62cd4e7e41e128c6de25922cbb51d92bc74f Mon Sep 17 00:00:00 2001 From: Tig Date: Tue, 28 Apr 2026 14:38:06 -0600 Subject: [PATCH 2/4] Update Examples link in README.md (#5104) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cddc3f9751..55350c9dd6 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ window.Add (label); app.Run (window); ``` -See the [Examples](Examples/) directory for more. +See the [Examples](Examples/README.md) for more. # Documentation From e4388c807a31865857d2e9473b17bc787fe40358 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Tue, 28 Apr 2026 16:01:44 -0600 Subject: [PATCH 3/4] Reframe layout docs around responsive UI and instructional style (#5110) * Initial plan * docs: reframe layout docs around responsive UI Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/a6b913bd-38e5-4d80-ac23-9dc8e6716045 Co-authored-by: tig <585482+tig@users.noreply.github.com> * docs: polish responsive layout wording Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/a6b913bd-38e5-4d80-ac23-9dc8e6716045 Co-authored-by: tig <585482+tig@users.noreply.github.com> * docs: tighten instructional sentence style Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/d453216b-6d43-4261-aa23-0dad98805e91 Co-authored-by: tig <585482+tig@users.noreply.github.com> * docs: fix remaining instructional prose Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/d7be6123-896e-4b95-8e3f-0cee1d6d35d1 Co-authored-by: tig <585482+tig@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: tig <585482+tig@users.noreply.github.com> --- .github/copilot-instructions.md | 7 +- AGENTS.md | 2 +- CLAUDE.md | 1 + Terminal.Gui/ViewBase/Layout/Dim.cs | 32 ++++---- Terminal.Gui/ViewBase/Layout/Pos.cs | 28 ++++--- Terminal.Gui/ViewBase/View.Layout.cs | 77 +++++++++++++----- docfx/docs/layout.md | 114 ++++++++++++++++++++------- llms.txt | 1 + 8 files changed, 187 insertions(+), 75 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 1b8e37d374..d919fa900e 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -236,4 +236,9 @@ public string Name - PRs must not introduce new compiler warnings (fix warnings in files you modify) - Title format: `Fixes #issue. Terse description` -- Update `Examples/UICatalog` scenarios when adding user-visible features \ No newline at end of file +- Update `Examples/UICatalog` scenarios when adding user-visible features + +## Documentation Style + +- In reference/how-to/API docs, write instructions as `To [goal], [imperative action].` +- Avoid `When/If you want/need to ...` unless describing a real condition. diff --git a/AGENTS.md b/AGENTS.md index 960350b3d0..4759b28b60 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -118,6 +118,7 @@ dotnet test --project Tests/UnitTestsParallelizable --no-build --filter-method " 7. **Backing fields** - Place immediately before their property 8. **Early return / guard clauses (CRITICAL)** - ALWAYS prefer guard clauses over nested `if`/`else`. Invert the condition, return/continue early, keep happy path at lowest indentation. This applies to methods, lambdas, loops — everywhere. See [early-return.md](/.claude/rules/early-return.md) for detailed examples. 9. **One type per file** - Public and internal types each get their own file +10. **Docs instruction style** - In reference/how-to/API docs, write `To [goal], [imperative action].` Avoid `When/If you want/need to ...` unless describing a real condition. ## Detailed Coding Rules @@ -518,6 +519,5 @@ See `.claude/cookbook/` for common UI patterns: - diff --git a/CLAUDE.md b/CLAUDE.md index 45df41e576..599c0b24ad 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -127,6 +127,7 @@ See `Tests/README.md` for the full list of test projects (including `Integration 8. **Unused lambda params** - use `_`: `(_, _) => { }` 9. **Early return / guard clauses** - ALWAYS invert conditions and return/continue early. Never wrap the happy path in a conditional. Applies to methods, lambdas, and loops. See `.claude/rules/early-return.md`. 10. **One type per file** - Public and internal types each get their own file +11. **Docs instruction style** - In reference/how-to/API docs, write `To [goal], [imperative action].` Avoid `When/If you want/need to ...` unless describing a real condition. ## Testing diff --git a/Terminal.Gui/ViewBase/Layout/Dim.cs b/Terminal.Gui/ViewBase/Layout/Dim.cs index c1994193ed..1f941d2e7c 100644 --- a/Terminal.Gui/ViewBase/Layout/Dim.cs +++ b/Terminal.Gui/ViewBase/Layout/Dim.cs @@ -3,17 +3,19 @@ namespace Terminal.Gui.ViewBase; /// +/// Describes a declarative, responsive dimension for a . +/// is the type of and . +/// Integer values are implicitly convertible to an absolute . +/// +/// /// -/// A Dim object describes the dimensions of a . Dim is the type of the -/// and properties of . +/// To make a view's size respond to the available space, its content, or the size and position of other views +/// rather than using a fixed number of cells, use . /// /// -/// Integer values are implicitly convertible to an absolute . These objects are created using -/// the static methods described below. The objects can be combined with the addition and -/// subtraction operators. +/// To define responsive sizing in Terminal.Gui, describe the relationship that should be maintained and let the +/// layout engine resolve the final whenever layout runs. /// -/// -/// /// /// /// @@ -109,8 +111,8 @@ public abstract record Dim : IEqualityOperators /// /// SubViews that use do not contribute to the auto-sizing calculation unless /// is specified. Without it, a SubView will - /// receive a size of 0. Use with a minimumContentDim to ensure - /// the SubView contributes a minimum size. + /// receive a size of 0. To ensure the SubView contributes a minimum size, use + /// with a minimumContentDim. /// /// /// @@ -141,9 +143,9 @@ public static Dim Auto (DimAutoStyle style = DimAutoStyle.Auto, Dim? minimumCont /// /// /// If the SuperView uses , a SubView does not - /// contribute to the auto-sizing calculation and will receive a size of 0. Use - /// with a minimumContentDim or with - /// a to parameter to ensure the SubView contributes to auto-sizing. + /// contribute to the auto-sizing calculation and will receive a size of 0. To make the SubView contribute to + /// auto-sizing, use with a minimumContentDim or + /// with a to parameter. /// See the Dim.Auto Deep Dive for details. /// /// @@ -162,9 +164,9 @@ public static Dim Auto (DimAutoStyle style = DimAutoStyle.Auto, Dim? minimumCont /// /// /// If the SuperView uses , a SubView does not - /// contribute to the auto-sizing calculation and will receive a size of 0. Use - /// with a minimumContentDim or with - /// a to parameter to ensure the SubView contributes to auto-sizing. + /// contribute to the auto-sizing calculation and will receive a size of 0. To make the SubView contribute to + /// auto-sizing, use with a minimumContentDim or + /// with a to parameter. /// See the Dim.Auto Deep Dive for details. /// /// diff --git a/Terminal.Gui/ViewBase/Layout/Pos.cs b/Terminal.Gui/ViewBase/Layout/Pos.cs index de79dfe562..8b93cb8b20 100644 --- a/Terminal.Gui/ViewBase/Layout/Pos.cs +++ b/Terminal.Gui/ViewBase/Layout/Pos.cs @@ -1,22 +1,28 @@ namespace Terminal.Gui.ViewBase; /// -/// Describes the position of a which can be an absolute value, a percentage, centered, or -/// relative to the ending dimension. Integer values are implicitly convertible to an absolute . These -/// objects are created using the static methods Percent, AnchorEnd, and Center. The objects can be -/// combined with the addition and subtraction operators. +/// Describes a declarative, responsive position for a . +/// A can be absolute, percentage-based, centered, anchored to an edge, or relative to another +/// . Integer values are implicitly convertible to an absolute . /// /// -/// Use the objects on the X or Y properties of a view to control the position. /// -/// These can be used to set the absolute position, when merely assigning an integer value (via the implicit -/// integer to conversion), and they can be combined to produce more useful layouts, like: -/// Pos.Center - 3, which would shift the position of the 3 characters to the left after -/// centering for example. +/// To describe where a view should be, relative to its , its available space, or its +/// sibling views, use with and . /// /// -/// Reference coordinates of another view by using the methods Left(View), Right(View), Bottom(View), Top(View). -/// The X(View) and Y(View) are aliases to Left(View) and Top(View) respectively. +/// To define responsive horizontal and vertical placement in Terminal.Gui, describe the relationship that should +/// be maintained and let the layout engine resolve the final whenever layout runs. +/// +/// +/// values can be combined to produce more useful layouts, such as +/// Pos.Center () - 3, which shifts the resolved position of the 3 cells earlier on +/// the axis after centering. +/// +/// +/// To reference coordinates of another view, use , , +/// , and . and are +/// aliases to and respectively. /// /// /// diff --git a/Terminal.Gui/ViewBase/View.Layout.cs b/Terminal.Gui/ViewBase/View.Layout.cs index ab9b441d47..e6cb655723 100644 --- a/Terminal.Gui/ViewBase/View.Layout.cs +++ b/Terminal.Gui/ViewBase/View.Layout.cs @@ -17,7 +17,9 @@ public partial class View // Layout APIs private Rectangle? _frame; - /// Gets or sets the absolute location and dimension of the view. + /// + /// Gets or sets the resolved location and dimension of the view. + /// /// /// The rectangle describing absolute location and dimension of the view, in coordinates relative to the /// 's Content, which is bound by . @@ -28,6 +30,11 @@ public partial class View // Layout APIs /// /// /// + /// is typically the output of Terminal.Gui's responsive layout system. To describe layout, + /// use , , , and . To inspect the + /// resolved result, read after layout has resolved those relationships. + /// + /// /// Frame is relative to the 's Content, which is bound by /// . /// @@ -207,7 +214,9 @@ private void PosDimSet () private Pos _x = Pos.Absolute (0); - /// Gets or sets the X position for the view (the column). + /// + /// Gets or sets the declarative horizontal position for the view. + /// /// The object representing the X position. /// /// @@ -215,6 +224,10 @@ private void PosDimSet () /// /// /// + /// To express responsive relationships such as "center this view", "anchor it to the end", or "place it to + /// the right of another view", use with . + /// + /// /// The position is relative to the 's Content, which is bound by /// . /// @@ -230,7 +243,7 @@ private void PosDimSet () /// /// Changing this property will cause to be updated. /// - /// The default value is Pos.At (0). + /// The default value is Pos.Absolute (0). /// public Pos X { @@ -252,7 +265,9 @@ public Pos X private Pos _y = Pos.Absolute (0); - /// Gets or sets the Y position for the view (the row). + /// + /// Gets or sets the declarative vertical position for the view. + /// /// The object representing the Y position. /// /// @@ -260,6 +275,10 @@ public Pos X /// /// /// + /// To express responsive relationships such as "center this view", "anchor it to the bottom", or "place it + /// below another view", use with . + /// + /// /// The position is relative to the 's Content, which is bound by /// . /// @@ -275,7 +294,7 @@ public Pos X /// /// Changing this property will cause to be updated. /// - /// The default value is Pos.At (0). + /// The default value is Pos.Absolute (0). /// public Pos Y { @@ -296,7 +315,9 @@ public Pos Y private Dim _height = Dim.Absolute (0); - /// Gets or sets the height dimension of the view. + /// + /// Gets or sets the declarative height for the view. + /// /// The object representing the height of the view (the number of rows). /// /// @@ -304,6 +325,10 @@ public Pos Y /// /// /// + /// To express responsive sizing such as filling remaining space, using a percentage of the available height, + /// or growing to fit content with Dim.Auto (), use with . + /// + /// /// The dimension is relative to the 's Content, which is bound by /// . /// @@ -383,7 +408,9 @@ protected virtual void OnHeightChanged (ValueChangedEventArgs args) { } private Dim _width = Dim.Absolute (0); - /// Gets or sets the width dimension of the view. + /// + /// Gets or sets the declarative width for the view. + /// /// The object representing the width of the view (the number of columns). /// /// @@ -391,6 +418,10 @@ protected virtual void OnHeightChanged (ValueChangedEventArgs args) { } /// /// /// + /// To express responsive sizing such as filling remaining space, using a percentage of the available width, + /// or growing to fit content with Dim.Auto (), use with . + /// + /// /// The dimension is relative to the 's Content, which is bound by /// /// . @@ -507,7 +538,7 @@ internal static bool Layout (IEnumerable views, Size contentSize) } /// - /// Performs layout of the view and its subviews within the specified content size. + /// Resolves the view's declarative layout and then lays out its subviews within the specified content size. /// /// /// @@ -515,8 +546,12 @@ internal static bool Layout (IEnumerable views, Size contentSize) /// /// /// - /// This method is intended to be called by the layout engine to - /// prepare the view for layout and is exposed as a public API primarily for testing purposes. + /// This method turns responsive and expressions into an absolute + /// , then recursively lays out SubViews. + /// + /// + /// This method is intended to be called by the layout engine to prepare the view for layout and is exposed as + /// a public API primarily for testing purposes. /// /// /// @@ -537,8 +572,8 @@ public bool Layout (Size contentSize) } /// - /// Performs layout of the view and its subviews using the content size of either the or - /// . + /// Resolves the view's declarative layout and then lays out its subviews using the content size of either the + /// or . /// /// /// @@ -546,21 +581,27 @@ public bool Layout (Size contentSize) /// /// /// - /// This method is intended to be called by the layout engine to - /// prepare the view for layout and is exposed as a public API primarily for testing purposes. + /// To force a responsive layout pass after changing , , , or + /// , call this overload. + /// + /// + /// This method is intended to be called by the layout engine to prepare the view for layout and is exposed as + /// a public API primarily for testing purposes. /// /// /// If the view could not be laid out (typically because dependency was not ready). public bool Layout () => Layout (GetContainerSize ()); /// - /// Sets the position and size of this view, relative to the SuperView's ContentSize (nominally the same as - /// this.SuperView.GetContentSize ()) based on the values of , , - /// , - /// and . + /// Resolves this view's declarative layout into a concrete position and size, relative to the SuperView's + /// content size, based on , , , and . /// /// /// + /// This method is the core step that turns responsive and expressions + /// into the view's absolute . + /// + /// /// If , , , or are /// absolute, they will be updated to reflect the new size and position of the view. Otherwise, they /// are left unchanged. diff --git a/docfx/docs/layout.md b/docfx/docs/layout.md index 25173b2892..1e3e7243cd 100644 --- a/docfx/docs/layout.md +++ b/docfx/docs/layout.md @@ -1,6 +1,8 @@ # Layout -Terminal.Gui provides a rich system for how [View](View.md) objects are laid out relative to each other. The layout system also defines how coordinates are specified. +Terminal.Gui layout is declarative and responsive. To define layout, describe how a [View](View.md) should relate to its `SuperView`, its content, and sibling views. To inspect the resolved result, read the final `Frame` after layout runs, including after terminal resizes. + +To apply a mental model similar to responsive web or React-style layouts, declare relationships such as "center this", "fill the remaining space", "stay 1 cell to the right of that view", or "use 50% of the available width", and let the layout engine resolve the actual coordinates. See [View Deep Dive](View.md), [Arrangement Deep Dive](arrangement.md), [Scrolling Deep Dive](scrolling.md), and [Drawing Deep Dive](drawing.md) for more. @@ -11,6 +13,7 @@ See [View Deep Dive](View.md), [Arrangement Deep Dive](arrangement.md), [Scrolli - [Composition](#composition) - [The Content Area](#the-content-area) - [The Viewport](#the-viewport) +- [Responsive Mental Model](#responsive-mental-model) - [Layout Engine](#layout-engine) - [Pos](#pos) - [Dim](#dim) @@ -96,17 +99,65 @@ The flags are organized into categories: - `HasHorizontalScrollBar` - Enables the built-in `HorizontalScrollBar` with .Auto behavior (automatically shown when content exceeds viewport) - `HasScrollBars` - Combines both vertical and horizontal scrollbar flags +## Responsive Mental Model + +To reason about Terminal.Gui layout, think of it as a small responsive layout language for TUIs: + +- `X` and `Y` answer **where should this view start?** +- `Width` and `Height` answer **how much space should it take?** +- `Pos` expresses location relationships. +- `Dim` expresses size relationships. +- `Frame` is the resolved result after layout runs. + +To build adaptive UIs, work with `Pos` and `Dim`, not `Frame`. + +Common patterns include: + +- Pinning to an edge with `Pos.AnchorEnd ()` +- Centering with `Pos.Center ()` +- Following another view with `Pos.Right (otherView)` or `Pos.Bottom (otherView)` +- Taking a percentage of the available space with `Dim.Percent (...)` +- Filling leftover space with `Dim.Fill ()` or `Dim.Fill (to: otherView)` +- Growing to content with `Dim.Auto ()` + +When the terminal size changes, or when the size of a `SuperView` or referenced view changes, layout runs again and these relationships are resolved into a new `Frame`. This is what makes Terminal.Gui layouts responsive. + ## Layout Engine -Terminal.Gui provides a rich system for how views are laid out relative to each other. The position of a view is set by setting the `X` and `Y` properties, which are of time . The size is set via `Width` and `Height`, which are of type . +The primary layout API is: + +- `X` and `Y` for position, using +- `Width` and `Height` for size, using + +These values are relative to the `SuperView`'s content area, not the screen. + +```cs +Label nameLabel = new () { Text = "Name:" }; +Button okButton = new () { Text = "OK", X = Pos.AnchorEnd () }; +TextField nameField = new () +{ + X = Pos.Right (nameLabel) + 1, + Y = Pos.Top (nameLabel), + Width = Dim.Fill (to: okButton) +}; +``` + +In this example: + +- `nameLabel` keeps its content-based width +- `okButton` stays anchored to the end of the line +- `nameField` stretches and shrinks between them -The layout system uses virtual properties for categorization without type checking: `ReferencesOtherViews()`, `DependsOnSuperViewContentSize`, `CanContributeToAutoSizing`, `GetMinimumContribution()`, `IsFixed`, and `RequiresTargetLayout`. This enables extensibility. +If the terminal or `SuperView` grows or shrinks, the same declarations are re-evaluated and the final `Frame` values change automatically. + +For advanced scenarios and custom layout primitives, the layout system also exposes virtual categorization hooks such as `ReferencesOtherViews()`, `DependsOnSuperViewContentSize`, `CanContributeToAutoSizing`, `GetMinimumContribution()`, `IsFixed`, and `RequiresTargetLayout`. ```cs -var label1 = new Label () { X = 1, Y = 2, Width = 3, Height = 4, Title = "Absolute") +Label absoluteLabel = new () { X = 1, Y = 2, Width = 12, Height = 1, Text = "Absolute" }; -var label2 = new Label () { - Title = "Computed", +Label responsiveLabel = new () +{ + Text = "Responsive", X = Pos.Right (otherView), Y = Pos.Center (), Width = Dim.Fill (), @@ -116,26 +167,26 @@ var label2 = new Label () { ### Pos - is the type of `View.X` and `View.Y` and supports the following sub-types: + is the type of `View.X` and `View.Y`. To make a view's position respond to available space or other views instead of using a fixed coordinate, use it. -* Absolute position, by passing an integer - `Pos.Absolute()`. -* Percentage of the parent's view size - `Pos.Percent()` -* Anchored from the end of the dimension - `Pos.AnchorEnd()` -* Centered, using `Pos.Center()` -* The `Pos.Left()`, `Pos.Right()`, `Pos.Top()`, and `Pos.Bottom()` tracks the position of another view. -* Aligned (left, right, center, etc...) with other views - `Pos.Align()` -* An arbitrary function - `Pos.Func()` +* Absolute position, by passing an integer - `Pos.Absolute ()` +* Percentage of the `SuperView` size - `Pos.Percent ()` +* Anchored from the end of the dimension - `Pos.AnchorEnd ()` +* Centered - `Pos.Center ()` +* Tracking another view - `Pos.Left ()`, `Pos.Right ()`, `Pos.Top ()`, `Pos.Bottom ()` +* Aligning as a group - `Pos.Align ()` +* Computing from a function - `Pos.Func ()` All coordinates are relative to the SuperView's content area. - values can be combined using addition or subtraction: + values can be combined using addition or subtraction, making it easy to express offsets in a responsive layout: ```cs // Set the X coordinate to 10 characters left from the center view.X = Pos.Center () - 10; view.Y = Pos.Percent (20); -anotherView.X = AnchorEnd (10); +anotherView.X = Pos.AnchorEnd (10); anotherView.Width = 9; myView.X = Pos.X (view); @@ -143,25 +194,28 @@ myView.Y = Pos.Bottom (anotherView) + 5; ``` ### Dim - is the type of `View.Width` and `View.Height` and supports the following sub-types: + is the type of `View.Width` and `View.Height`. To make size respond to content, terminal size, or sibling views instead of using a fixed number of cells, use it. + +* Automatic size based on the view's content - `Dim.Auto ()` - See [Dim.Auto Deep Dive](dimauto.md) +* Absolute size, by passing an integer - `Dim.Absolute ()` +* Percentage of the `SuperView` content area - `Dim.Percent ()` +* Fill the remaining space - `Dim.Fill ()` +* Fill up to another view - `Dim.Fill (to: otherView)` +* Track another view's size - `Dim.Width ()`, `Dim.Height ()` +* Compute from a function - `Dim.Func ()` -* Automatic size based on the View's content (either SubViews or Text) - `Dim.Auto()` - See [Dim.Auto Deep Dive](dimauto.md). -* Absolute size, by passing an integer - `Dim.Absolute()`. -* Percentage of the SuperView's Content Area - `Dim.Percent()`. -* Fill to the end of the SuperView's Content Area - `Dim.Fill()`. **Note:** `Dim.Fill` does not contribute to a SuperView's `Dim.Auto()` sizing unless `minimumContentDim` is specified. See [Dim.Auto Deep Dive](dimauto.md) for details. -* Reference the Width or Height of another view - `Dim.Width()`, `Dim.Height()`. -* An arbitrary function - `Dim.Func()`. +`Dim.Fill ()` is especially useful for responsive forms and panes. **Note:** `Dim.Fill` does not contribute to a `SuperView`'s `Dim.Auto ()` sizing unless `minimumContentDim` is specified. See [Dim.Auto Deep Dive](dimauto.md) for details. All dimensions are relative to the SuperView's content area. -Like, , objects of type can be combined using addition or subtraction, like this: +Like , objects of type can be combined using addition or subtraction: ```cs // Set the Width to be 10 characters less than filling // the remaining portion of the screen view.Width = Dim.Fill () - 10; -view.Height = Dim.Percent(20) - 1; +view.Height = Dim.Percent (20) - 1; anotherView.Height = Dim.Height (view) + 1; ``` @@ -190,11 +244,11 @@ classDiagram ## How To -This section provides solutions to common layout scenarios. +To solve common layout scenarios, use this section. ### Stretch a View Between Fixed Elements -**Scenario:** A label on the left, a text field that stretches to fill available space, and a button anchored to the right: +**Scenario:** A label on the left, a text field that stretches to fill available space, and a button anchored to the right. This is a classic responsive form row: ``` [label][ stretching text field ][button] @@ -206,11 +260,14 @@ Button btn = new () { Text = "_OK", X = Pos.AnchorEnd () }; TextField textField = new () { X = Pos.Right (label) + 1, - Width = Dim.Func (() => btn.Frame.X - label.Frame.Width - 1) + Width = Dim.Fill (to: btn) }; superView.Add (label, textField, btn); ``` +The text field expands and contracts automatically as the available width changes. +Here `to: btn` names the `Dim.Fill` parameter that tells the text field where its fill should stop. + ### Align Multiple Views (Like Dialog Buttons) **Scenario:** Align buttons horizontally using `Pos.Align()`, as does: @@ -250,4 +307,3 @@ Window popup = new () ``` The key insight is `maximumContentDim` subtracts the adornments thickness from 100% to ensure the view (including its , , and ) never exceeds the SuperView's bounds. - diff --git a/llms.txt b/llms.txt index 790b368876..2dbdf395e0 100644 --- a/llms.txt +++ b/llms.txt @@ -344,6 +344,7 @@ public sealed class FormWindow : Runnable 3. **Instance-based app** — `Application.Create ().Init ()` returns `IApplication` 4. **`App!.RequestStop ()`** — Not `Application.RequestStop ()` 5. **SubView/SuperView** — Never "child"/"parent"/"container" in docs/discussion +6. **Docs instruction style** — In reference/how-to/API docs, write `To [goal], [imperative action].` Avoid `When/If you want/need to ...` unless describing a real condition. ### Code Style (Library Contributors Only) From de4161d139d0a8c485c446994329149720e0bb45 Mon Sep 17 00:00:00 2001 From: Tig Date: Tue, 28 Apr 2026 18:46:09 -0600 Subject: [PATCH 4/4] Fixes #5114. Remove main from publish branch triggers; use tags only Main branch pushes were triggering the publish workflow without a release tag, causing GitVersion to produce invalid NuGet versions (e.g. 2.0.0-5420). - Remove main from branches trigger; stable releases now publish only on v* tag push - Develop branch pushes continue publishing pre-release packages automatically - Update template dispatch conditions to match tag-based flow Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/publish.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 186c66b5a1..8b61789300 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -2,7 +2,9 @@ name: Publish Terminal.Gui to Nuget on: push: - branches: [ main, develop ] + # Main releases are triggered only by pushing a v* tag (e.g., v2.0.0). + # Develop pushes publish pre-release packages (e.g., 2.1.0-develop.1). + branches: [ develop ] tags: - v* paths-ignore: @@ -71,7 +73,7 @@ jobs: run: dotnet nuget push Terminal.Gui/bin/Release/Terminal.Gui.${{ steps.gitversion.outputs.SemVer }}.nupkg --skip-duplicate --api-key ${{ secrets.NUGET_API_KEY }} # - name: Delist old NuGet packages - # if: github.ref == 'refs/heads/main' + # if: startsWith(github.ref, 'refs/tags/v') # shell: pwsh # run: | # $version = "${{ steps.gitversion.outputs.SemVer }}" @@ -79,13 +81,13 @@ jobs: # ./Scripts/delist-nuget.ps1 -ApiKey "${{ secrets.NUGET_API_KEY }}" -JustPublishedVersion "$version" - name: Prepare payload for template dispatch - if: github.ref == 'refs/heads/main' + if: startsWith(github.ref, 'refs/tags/v') id: payload run: | echo "json={\"version\":\"${{ steps.gitversion.outputs.SemVer }}\"}" >> $GITHUB_OUTPUT - name: Trigger Terminal.Gui.templates update - if: github.ref == 'refs/heads/main' + if: startsWith(github.ref, 'refs/tags/v') uses: peter-evans/repository-dispatch@v4 with: token: ${{ secrets.TEMPLATE_REPO_TOKEN }}