diff --git a/Examples/Example/Example.cs b/Examples/Example/Example.cs
index e7ea27671c..7becbe1dd7 100644
--- a/Examples/Example/Example.cs
+++ b/Examples/Example/Example.cs
@@ -5,9 +5,9 @@
using Terminal.Gui.App;
using Terminal.Gui.Configuration;
+using Terminal.Gui.Input;
using Terminal.Gui.ViewBase;
using Terminal.Gui.Views;
-using Terminal.Gui.Input;
// Override the default configuration for the application to use the Amber Phosphor theme
ConfigurationManager.RuntimeConfig = """{ "Theme": "Amber Phosphor" }""";
diff --git a/Terminal.sln b/Terminal.sln
index 627570beb0..b4cb7cbf11 100644
--- a/Terminal.sln
+++ b/Terminal.sln
@@ -151,8 +151,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScenarioRunner", "Examples\
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{A589126F-C71A-4FEE-B7EA-2DCA1ADF6A46}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShortcutTest", "Examples\ShortcutTest\ShortcutTest.csproj", "{0EECEC4F-AD8D-1076-1B40-562926DE1CB3}"
-EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -239,10 +237,6 @@ Global
{DB0337E6-BBC0-4ECB-9F18-F7310705BDAF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DB0337E6-BBC0-4ECB-9F18-F7310705BDAF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DB0337E6-BBC0-4ECB-9F18-F7310705BDAF}.Release|Any CPU.Build.0 = Release|Any CPU
- {0EECEC4F-AD8D-1076-1B40-562926DE1CB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {0EECEC4F-AD8D-1076-1B40-562926DE1CB3}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {0EECEC4F-AD8D-1076-1B40-562926DE1CB3}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {0EECEC4F-AD8D-1076-1B40-562926DE1CB3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -270,7 +264,6 @@ Global
{26FDEE3C-9D1F-79A6-F48F-D0944C7F09F8} = {3DD033C0-E023-47BF-A808-9CCE30873C3E}
{566AFB59-FF8C-FFF4-C1F4-049B6246E4A7} = {3DD033C0-E023-47BF-A808-9CCE30873C3E}
{DB0337E6-BBC0-4ECB-9F18-F7310705BDAF} = {3DD033C0-E023-47BF-A808-9CCE30873C3E}
- {0EECEC4F-AD8D-1076-1B40-562926DE1CB3} = {3DD033C0-E023-47BF-A808-9CCE30873C3E}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {9F8F8A4D-7B8D-4C2A-AC5E-CD7117F74C03}
diff --git a/docfx/scripts/OutputView/OutputView.cs b/docfx/scripts/OutputView/OutputView.cs
index 374caeb497..ca726ab9c1 100644
--- a/docfx/scripts/OutputView/OutputView.cs
+++ b/docfx/scripts/OutputView/OutputView.cs
@@ -1,8 +1,9 @@
#nullable enable
+using AnsiConsoleToHtml;
using Terminal.Gui.App;
-using Terminal.Gui.Drivers;
using Terminal.Gui.Configuration;
using Terminal.Gui.Drawing;
+using Terminal.Gui.Drivers;
using Terminal.Gui.ViewBase;
using Terminal.Gui.Views;
using Attribute = Terminal.Gui.Drawing.Attribute;
@@ -30,8 +31,8 @@
string? outputFile = null;
string [] commandArgs = Environment.GetCommandLineArgs ();
-bool ansi = false;
-bool addBorderFrame = false;
+var ansi = false;
+var addBorderFrame = false;
for (var i = 0; i < commandArgs.Length; i++)
{
@@ -103,7 +104,7 @@
if (ansi)
{
- output = AnsiConsoleToHtml.AnsiConsole.ToHtml (output);
+ output = AnsiConsole.ToHtml (output);
}
// Write to file or console
@@ -128,13 +129,13 @@ public ViewDemoWindow ()
Height = 20;
// Use only white on black
- SetScheme (new (new Attribute (ColorName16.White, ColorName16.Black)));
+ SetScheme (new Scheme (new Attribute (ColorName16.White, ColorName16.Black)));
BorderStyle = LineStyle.None;
}
public static bool AddBorderFrame { get; set; }
- ///
+ ///
protected override void OnIsRunningChanged (bool newIsRunning)
{
base.OnIsRunningChanged (newIsRunning);
@@ -218,6 +219,7 @@ protected override void OnIsRunningChanged (bool newIsRunning)
{
view.Text = "This is some demo text.";
}
+
//view.Title = $"View: {type.Name}";
return view;
diff --git a/docfx/scripts/OutputView/Properties/launchSettings.json b/docfx/scripts/OutputView/Properties/launchSettings.json
index 893246195e..f69ff05414 100644
--- a/docfx/scripts/OutputView/Properties/launchSettings.json
+++ b/docfx/scripts/OutputView/Properties/launchSettings.json
@@ -6,7 +6,7 @@
},
"OutputView ": {
"commandName": "Project",
- "commandLineArgs": "--view=GraphView"
+ "commandLineArgs": "--view=AttributePicker"
},
"OutputView --ansi": {
"commandName": "Project",
diff --git a/plans/fix-border-subview-linecanvas-clipping.md b/plans/fix-border-subview-linecanvas-clipping.md
deleted file mode 100644
index dc73ab5f24..0000000000
--- a/plans/fix-border-subview-linecanvas-clipping.md
+++ /dev/null
@@ -1,239 +0,0 @@
-# Fix: Border SubView LineCanvas Lines Not Clipped at Parent Bounds
-
-## Bug Summary
-
-When a SubView of a Border has `SuperViewRendersLineCanvas = true` and its own border
-(`BorderStyle != None`), and the SubView's frame extends past the parent Border's bounds,
-the SubView's border lines bleed into the parent's border columns. For example, a `║`
-becomes `╫` because the SubView's `─` merges unclipped into the parent's LineCanvas.
-
-**Failing test:** `AdornmentSubViewLineCanvasTests.BorderSubView_WithBorder_ClippedWhenExceedingParentBounds`
-
-## Root Cause
-
-The merge at `View.Drawing.Adornments.cs:50` is unclipped:
-
-```csharp
-// Line 43: clip set to border's frame (only affects raster drawing via Driver.Clip)
-Region? saved = borderView.AddFrameToClip ();
-// Line 44: subviews are drawn (their LineCanvas lines are generated)
-borderView.DoDrawSubViews ();
-
-// Line 50: ALL lines from borderView's LineCanvas are merged — NO BOUNDS CHECK
-LineCanvas.Merge (borderView.LineCanvas);
-```
-
-`LineCanvas.Merge()` (LineCanvas.cs:510-524) copies every `StraightLine` unconditionally.
-`Driver.Clip` (set by `AddFrameToClip`) only restricts raster output (`AddStr`, `Move`),
-not LineCanvas data. The merged lines participate in intersection resolution and produce
-corrupted junction glyphs where they cross the parent's border lines.
-
-The class docs (LineCanvas.cs:44-48) describe a `Merge(LineCanvas, Region?)` overload for
-clipped merging, but **this overload does not exist**.
-
-## Draw Pipeline Context
-
-```
-View.Draw():
- 1. DoDrawAdornments() — Parent's border adds lines to this.LineCanvas
- 2. AddViewportToClip() — Clip to viewport (raster only)
- 3. DoDrawSubViews() — Content subviews drawn
- 4. SetClip → AddFrameToClip() — Clip to frame (raster only)
- 5. DoDrawAdornmentsSubViews() — Border subview lines merged into this.LineCanvas ← BUG
- 6. DoRenderLineCanvas() — Resolves all lines and renders to screen
-```
-
-The merge in step 5 must restrict lines to the border's content area before they enter
-the parent's LineCanvas in step 6.
-
-## Fix Options
-
-### Option A: Clipped `Merge` overload on LineCanvas
-
-Implement the documented but missing `Merge(LineCanvas, Rectangle clipBounds)` overload.
-It would trim or discard each incoming `StraightLine` to fit within `clipBounds` before
-adding it.
-
-**Where to change:**
-- `LineCanvas.cs` — Add `Merge(LineCanvas, Rectangle)` that clips each line using
- `StraightLineExtensions`-style logic (trim Start/Length to stay within bounds).
-- `View.Drawing.Adornments.cs:50` — Pass the border view's frame rect:
- ```csharp
- Rectangle borderBounds = borderView.FrameToScreen ();
- LineCanvas.Merge (borderView.LineCanvas, borderBounds);
- ```
-- Same pattern for Padding merge at line 84.
-
-**Pros:**
-- Clean, self-contained — clipping logic lives in LineCanvas where it belongs.
-- The documentation already describes this overload; just implement it.
-- Lines are trimmed *before* intersection resolution, so no corrupted junctions.
-- `StraightLineExtensions.Exclude` already has line-splitting logic that can be reused
- to clip lines against a rectangle boundary.
-
-**Cons:**
-- Trimming lines can produce different junction types at the clip boundary (the docs
- warn about this). A line that was `PassOverHorizontal` may become `StartRight` after
- clipping, which could change the resolved glyph. This is acceptable — the clipped
- edge is at the parent's border, which already has its own lines providing the correct
- junction context.
-- Must handle both horizontal and vertical lines, and both positive/negative lengths.
-
-**Complexity:** Medium. The line-trimming math is straightforward (clamp start/end to
-bounds, recompute length). `StraightLineExtensions` already demonstrates the pattern.
-
----
-
-### Option B: Exclude-based approach — add exclusion region to parent LineCanvas
-
-Instead of clipping lines before merge, merge everything, then exclude the out-of-bounds
-cells from the parent's LineCanvas output.
-
-**Where to change:**
-- `View.Drawing.Adornments.cs:50` — After merge, compute the region outside the border
- view's frame and call `LineCanvas.Exclude()` on those areas.
-
-**Pros:**
-- Simpler implementation — no line-splitting math.
-- Uses existing `Exclude` API.
-
-**Cons:**
-- **Does not fix the bug.** `Exclude` hides cells from `GetCellMap` output but lines
- still participate in intersection resolution. The out-of-bounds `─` still crosses the
- parent's `║` during resolution, producing `╫` — even though the `╫` cell at the
- parent's border column would be excluded, the parent's own `║` line at that position
- would ALSO be excluded because exclusion is position-based, not line-based.
-- Would need careful region math to only exclude the *SubView's* cells outside bounds
- without excluding the parent's own border cells at those positions.
-- Fragile and semantically wrong — the problem is that lines exist where they shouldn't,
- not that their output needs hiding.
-
-**Verdict: Not viable** without significant additional work to make exclusion line-aware.
-
----
-
-### Option C: Clip in `DoDrawSubViews` — restrict the SubView's own LineCanvas generation
-
-Prevent the SubView from generating LineCanvas lines outside the border's frame in the
-first place, by clipping the SubView's layout/frame before it draws.
-
-**Where to change:**
-- `View.Drawing.Adornments.cs:44` or the SubView's own `Draw()` — Constrain the
- SubView's effective frame to the intersection of its frame and the border view's frame
- before drawing.
-
-**Pros:**
-- Fixes the problem at the source — lines are never generated outside bounds.
-- No post-hoc filtering or trimming needed.
-
-**Cons:**
-- Changing the SubView's frame/layout is invasive and could have side effects on hit
- testing, mouse events, and other layout-dependent behavior.
-- The SubView's `BorderView.OnDrawingContent` adds lines based on the SubView's
- `FrameToScreen()`. Changing the frame changes the border geometry, not just clips it.
-- Would need to be undone after drawing, adding complexity.
-- Conceptually wrong — layout shouldn't change during draw.
-
-**Verdict: Too invasive.** Mixing layout mutation with draw is a design smell.
-
----
-
-### Option D: Filter during `RenderLineCanvas` — clip at output time
-
-Instead of clipping during merge, filter the resolved `cellMap` in `RenderLineCanvas`
-to only include cells within the view's frame.
-
-**Where to change:**
-- `View.Drawing.LineCanvas.cs:48-60` — Skip cells outside `FrameToScreen()`.
-
-**Pros:**
-- Simple one-line check in the render loop.
-- No changes to LineCanvas data structure.
-
-**Cons:**
-- **Does not fix junction corruption.** The out-of-bounds lines still participate in
- intersection resolution. Even if the corrupted `╫` cell is not rendered, the parent's
- `║` line at that position may resolve differently because of the intersecting `─`.
- The resolved glyph at the parent's border column would be wrong even if we skip
- rendering out-of-bounds cells.
-- Only addresses the symptom (rendering) not the cause (unclipped lines in the canvas).
-
-**Verdict: Insufficient.** Junction corruption happens during resolution, not rendering.
-
-## Recommendation
-
-**Option A** is the correct fix. It addresses the root cause (unclipped lines entering
-the parent's LineCanvas), uses the existing documented API contract, and produces correct
-junction glyphs because the parent's own border lines are the only lines at the boundary
-during intersection resolution.
-
-### Implementation sketch
-
-```csharp
-// LineCanvas.cs — new overload
-public void Merge (LineCanvas lineCanvas, Rectangle clipBounds)
-{
- foreach (StraightLine line in lineCanvas._lines)
- {
- // Clip the line to clipBounds; may produce 0 or 1 clipped line
- StraightLine? clipped = ClipLine (line, clipBounds);
-
- if (clipped is { })
- {
- AddLine (clipped);
- }
- }
-
- // Exclusion regions are position-based — intersect with clipBounds
- if (lineCanvas._exclusionRegion is { })
- {
- Region clippedExclusion = lineCanvas._exclusionRegion.Clone ();
- clippedExclusion.Intersect (clipBounds);
- _exclusionRegion ??= new Region ();
- _exclusionRegion.Union (clippedExclusion);
- }
-}
-
-private static StraightLine? ClipLine (StraightLine line, Rectangle bounds)
-{
- Rectangle lineBounds = line.Bounds;
- Rectangle clipped = Rectangle.Intersect (lineBounds, bounds);
-
- if (clipped.IsEmpty)
- {
- return null;
- }
-
- // Recompute Start and Length from the clipped rectangle
- Point newStart = line.Orientation == Orientation.Horizontal
- ? new Point (clipped.X, clipped.Y)
- : new Point (clipped.X, clipped.Y);
-
- int newLength = line.Orientation == Orientation.Horizontal
- ? clipped.Width
- : clipped.Height;
-
- // Preserve direction (sign of Length)
- if (line.Length < 0)
- {
- newLength = -newLength;
- // Adjust start for negative-direction lines
- // ... (handle negative length start offset)
- }
-
- return new StraightLine (newStart, newLength, line.Orientation, line.Style, line.Attribute);
-}
-```
-
-Call site in `View.Drawing.Adornments.cs`:
-
-```csharp
-if (borderView.LineCanvas.Bounds != Rectangle.Empty)
-{
- Rectangle clipBounds = borderView.FrameToScreen ();
- LineCanvas.Merge (borderView.LineCanvas, clipBounds);
- borderView.LineCanvas.Clear ();
-}
-```
-
-Same for the Padding merge at line 82-86.
diff --git a/plans/refactor-border-tab-to-borderview.md b/plans/refactor-border-tab-to-borderview.md
deleted file mode 100644
index c3b84e3250..0000000000
--- a/plans/refactor-border-tab-to-borderview.md
+++ /dev/null
@@ -1,359 +0,0 @@
-# Plan: Move Tab-Related Functionality from Border to BorderView
-
-## Problem
-
-`Border` is instantiated on **every** `View` — it should be as lightweight as possible. Currently it carries tab-related members (`TabSide`, `TabOffset`, `TabLength`, `TabEnd`, `EffectiveTabLength`, `SettingsChanged`) that are only meaningful when `BorderSettings.Tab` is active. This functionality belongs on `BorderView`, which is lazily created only when needed.
-
-## Goals
-
-1. **Minimize Border's footprint** — Border stores only `Thickness`, `LineStyle`, and `Settings`.
-2. **Move tab configuration to BorderView** — `TabSide`, `TabOffset`, `TabLength`, `EffectiveTabLength` become properties on `BorderView`. `TabEnd` is deleted (zero consumers).
-3. **Update all consumers** — backwards compatibility is not a concern. All call sites change from `view.Border.TabSide` to `((BorderView)view.Border.View!).TabSide` (or use a helper/local).
-4. **No behavioral changes** — rendering, tests, and UICatalog scenarios produce identical output.
-
-## Approach
-
-**Option B: Move completely, remove from Border.** All tab properties are deleted from `Border` and added to `BorderView`. Every consumer is updated. This gives the cleanest separation.
-
----
-
-## Current State Inventory
-
-### Members on `Border` today
-
-| Member | Kind | Tab-Only? | Consumers |
-|--------|------|-----------|-----------|
-| `Thickness` | inherited | No | Everywhere — **stays** |
-| `LineStyle` | property | No | Everywhere — **stays** |
-| `Settings` | property | No (but triggers tab setup) | Everywhere — **stays** |
-| `SettingsChanged` | event | Yes (only subscriber: BorderView) | 1 internal — **remove** |
-| `TabSide` | property | **Yes** | ~48 locations — **move** |
-| `TabOffset` | property | **Yes** | ~80 locations — **move** |
-| `TabLength` | property | **Yes** | ~13 locations — **move** |
-| `TabEnd` | computed property | **Yes** | 0 consumers — **delete** |
-| `EffectiveTabLength` | internal property | **Yes** | ~11 locations — **move** |
-
-### Members on `BorderView` today
-
-BorderView already has all the tab **rendering** logic. It reads tab configuration from `Border` via its `Adornment` reference. After this refactor, it owns the configuration too.
-
----
-
-## Execution Order
-
-Work in three phases, building green after each.
-
-### Phase 1: `EffectiveTabLength` and `TabEnd`
-
-Low-risk warm-up. `EffectiveTabLength` is `internal` and `TabEnd` is dead code.
-
-### Phase 2: `TabSide`, `TabOffset`, `TabLength`
-
-The bulk of the work — these are public properties with many consumers.
-
-### Phase 3: `SettingsChanged` event
-
-Cleanup — replace the event with a direct call.
-
----
-
-## Phase 1: Move `EffectiveTabLength`, Delete `TabEnd`
-
-### Step 1.1: Add `EffectiveTabLength` to `BorderView`
-
-Add to `BorderView.cs` (tab support region):
-
-```csharp
-internal int EffectiveTabLength
-{
- get
- {
- if (TabLength is { } explicitLength)
- {
- return explicitLength;
- }
-
- if (TitleView is not (ITitleView itv and View tv))
- {
- return 0;
- }
-
- if (itv.MeasuredTabLength > 0)
- {
- return itv.MeasuredTabLength;
- }
-
- // TitleView hasn't been laid out yet — set text and orientation, then measure.
- tv.Text = Adornment?.Parent?.Title ?? string.Empty;
- itv.Orientation = TabSide is Side.Left or Side.Right ? Orientation.Vertical : Orientation.Horizontal;
-
- int measured = TabSide is Side.Top or Side.Bottom ? tv.GetAutoWidth () : tv.GetAutoHeight ();
- itv.MeasuredTabLength = measured;
-
- return measured;
- }
-}
-```
-
-Note: This initially reads `TabSide` and `TabLength` from `Border` (via `Adornment`). After Phase 2, these become local properties and the reads simplify.
-
-### Step 1.2: Delete `EffectiveTabLength` from `Border`
-
-Remove the full `EffectiveTabLength` property from `Border.cs`.
-
-### Step 1.3: Update consumers of `EffectiveTabLength`
-
-All consumers currently access `border.EffectiveTabLength` or `tab.Border.EffectiveTabLength`.
-
-**Library code (`Tabs.cs`)** — 4 reads. Pattern: `tab.Border.EffectiveTabLength`. Change to:
-
-```csharp
-((BorderView)tab.Border.View!).EffectiveTabLength
-```
-
-Or introduce a local helper in `Tabs.cs`:
-
-```csharp
-private static BorderView GetBorderView (View tab) => (BorderView)tab.Border.View!;
-```
-
-Then: `GetBorderView (tab).EffectiveTabLength`
-
-**Library code (`BorderView.cs`)** — 1 read in `DrawTabBorder`. Change `border.EffectiveTabLength` → `EffectiveTabLength` (now local).
-
-**Tests** — ~5 assertions. Change `view.Border.EffectiveTabLength` → cast and access.
-
-### Step 1.4: Delete `TabEnd` from `Border`
-
-Remove the `TabEnd` computed property entirely. It has **zero consumers**.
-
-### Step 1.5: Build and test
-
-```bash
-dotnet build --no-restore
-dotnet test --project Tests/UnitTestsParallelizable --no-build
-```
-
----
-
-## Phase 2: Move `TabSide`, `TabOffset`, `TabLength`
-
-### Step 2.1: Add properties to `BorderView`
-
-Add to `BorderView.cs` (tab support region):
-
-```csharp
-public Side TabSide
-{
- get;
- set
- {
- if (field == value)
- {
- return;
- }
-
- field = value;
- Adornment?.Parent?.SetNeedsLayout ();
- }
-} = Side.Top;
-
-public int TabOffset
-{
- get;
- set
- {
- if (field == value)
- {
- return;
- }
-
- field = value;
- Adornment?.Parent?.SetNeedsLayout ();
- }
-}
-
-public int? TabLength
-{
- get;
- set
- {
- if (field == value)
- {
- return;
- }
-
- field = value;
- Adornment?.Parent?.SetNeedsLayout ();
- }
-}
-```
-
-### Step 2.2: Delete properties from `Border`
-
-Remove `TabSide`, `TabOffset`, `TabLength` (including backing fields, setters, and XML docs) from `Border.cs`.
-
-### Step 2.3: Update `BorderView` internal reads
-
-All reads in `BorderView.cs` that go through `border.TabSide`, `border.TabOffset`, `border.TabLength` change to `TabSide`, `TabOffset`, `TabLength` (now `this`). Affected methods:
-
-| Method | Properties read |
-|--------|----------------|
-| `ConfigureForTabMode()` | `border.TabSide` → `TabSide` |
-| `UpdateTitleViewLayout()` | `border.TabSide`, `border.TabOffset`, `border.TabLength` → local |
-| `GetTabBorderBounds()` | `border.TabSide` → `TabSide` |
-| `DrawTabBorder()` | `border.TabSide`, `border.TabOffset`, `border.EffectiveTabLength` → local |
-| `GetTabDepth()` | Uses `Adornment.Thickness` only — **no change** |
-| `IsFocusedOrLastTab()` | No tab config reads — **no change** |
-
-Also update `EffectiveTabLength` getter (from Phase 1) to read `TabSide`/`TabLength` from `this` instead of from Border.
-
-### Step 2.4: Update `Tabs.cs`
-
-This is the primary external consumer. All patterns are `view.Border.TabSide`, `tab.Border.TabOffset`, etc.
-
-Add a static helper (or extension) to reduce cast noise:
-
-```csharp
-// In Tabs.cs (private helper)
-private static BorderView GetBorderView (View tab) => (BorderView)tab.Border.View!;
-```
-
-Then update all call sites:
-
-| Old | New |
-|-----|-----|
-| `view.Border.TabSide = _tabSide` | `GetBorderView (view).TabSide = _tabSide` |
-| `tab.Border.TabOffset = offset` | `GetBorderView (tab).TabOffset = offset` |
-| `tab.Border.TabLength = null` | `GetBorderView (tab).TabLength = null` |
-| `tab.Border.EffectiveTabLength` | `GetBorderView (tab).EffectiveTabLength` |
-
-Approximate count: ~15 sites in `Tabs.cs`.
-
-### Step 2.5: Update `BorderEditor.cs`
-
-`BorderEditor.cs` in `Examples/UICatalog/Scenarios/EditorsAndHelpers/` casts to `Border` and reads/writes `TabSide`, `TabOffset`. Change to cast to `BorderView` via `AdornmentToEdit.View`:
-
-```csharp
-// Old:
-((Border)AdornmentToEdit).TabSide
-// New:
-((BorderView)AdornmentToEdit.View!).TabSide
-```
-
-Approximate count: ~5 sites.
-
-### Step 2.6: Update `Adornments.cs` scenario
-
-`Examples/UICatalog/Scenarios/Adornments.cs` reads `window.Border.TabSide`, `window.Border.TabOffset`, `window.Border.TabLength`. Change to access via `BorderView`:
-
-```csharp
-BorderView bv = (BorderView)window.Border.View!;
-bv.TabSide ...
-bv.TabOffset ...
-```
-
-Approximate count: ~5 sites.
-
-### Step 2.7: Update `UICatalogRunnable.cs`
-
-Has 2 commented-out references to `Border.TabSide`. Update or remove the comments.
-
-### Step 2.8: Update tests
-
-Tests that access `view.Border.TabSide`, `view.Border.TabOffset`, `view.Border.TabLength` need updating:
-
-| Test file | Approx sites |
-|-----------|-------------|
-| `TabsTests.cs` | ~10 |
-| `TabsScrollingTests.cs` | ~55 |
-| `BorderViewTests.cs` | ~30 |
-| `TitleViewTests.cs` | ~5 |
-| `TabCompositionTests.cs` | ~3 |
-| `AdornmentSubViewLineCanvasTests.cs` | ~2 |
-
-Pattern: add a local helper or inline cast. For test files with many accesses, a helper at the top of the class:
-
-```csharp
-private static BorderView Bv (View v) => (BorderView)v.Border.View!;
-```
-
-### Step 2.9: Update docs
-
-- `docfx/docs/borders.md` — update "Key Properties" table and code examples to use `BorderView` access pattern.
-- `Border.cs` XML docs — remove tab-related examples and references.
-- `BorderView.cs` XML docs — add docs for the new properties.
-- `BorderSettings.cs` — update `Tab` doc to reference `BorderView.TabSide` etc. instead of `Border.TabSide`.
-
-### Step 2.10: Build and test
-
-```bash
-dotnet build --no-restore
-dotnet test --project Tests/UnitTestsParallelizable --no-build
-dotnet test --project Tests/UnitTests --no-build
-```
-
----
-
-## Phase 3: Remove `SettingsChanged` Event
-
-### Step 3.1: Replace event with direct call
-
-In `Border.Settings` setter, replace:
-
-```csharp
-SettingsChanged?.Invoke (this, EventArgs.Empty);
-```
-
-with:
-
-```csharp
-(View as BorderView)?.ConfigureForTabMode ();
-```
-
-Make `ConfigureForTabMode` `internal` (currently `private`).
-
-### Step 3.2: Remove event + subscription
-
-- Delete `public event EventHandler? SettingsChanged;` from `Border.cs`.
-- Delete `border.SettingsChanged += OnSettingsChanged;` from `BorderView` constructor.
-- Delete the `OnSettingsChanged` bridge method from `BorderView`.
-
-### Step 3.3: Build and test
-
-```bash
-dotnet build --no-restore
-dotnet test --project Tests/UnitTestsParallelizable --no-build
-```
-
----
-
-## Files Changed
-
-| File | Phase | Change |
-|------|-------|--------|
-| `Terminal.Gui/ViewBase/Adornment/Border.cs` | 1,2,3 | Remove `TabSide`, `TabOffset`, `TabLength`, `TabEnd`, `EffectiveTabLength`, `SettingsChanged`; update `Settings` setter |
-| `Terminal.Gui/ViewBase/Adornment/BorderView.cs` | 1,2 | Add `TabSide`, `TabOffset`, `TabLength`, `EffectiveTabLength`; update all internal reads to use local props; make `ConfigureForTabMode` internal |
-| `Terminal.Gui/ViewBase/Adornment/BorderSettings.cs` | 2 | Update XML doc for `Tab` to reference `BorderView` |
-| `Terminal.Gui/Views/Tabs.cs` | 1,2 | Add helper; update ~15 call sites |
-| `Examples/UICatalog/Scenarios/EditorsAndHelpers/BorderEditor.cs` | 2 | Update ~5 call sites |
-| `Examples/UICatalog/Scenarios/Adornments.cs` | 2 | Update ~5 call sites |
-| `Examples/UICatalog/UICatalogRunnable.cs` | 2 | Update 2 commented-out references |
-| `Tests/.../TabsTests.cs` | 2 | Update ~10 sites |
-| `Tests/.../TabsScrollingTests.cs` | 2 | Update ~55 sites |
-| `Tests/.../BorderViewTests.cs` | 1,2 | Update ~30 sites |
-| `Tests/.../TitleViewTests.cs` | 2 | Update ~5 sites |
-| `Tests/.../TabCompositionTests.cs` | 2 | Update ~3 sites |
-| `Tests/.../AdornmentSubViewLineCanvasTests.cs` | 2 | Update ~2 sites |
-| `docfx/docs/borders.md` | 2 | Update property table and examples |
-
----
-
-## Risk Assessment
-
-| Risk | Mitigation |
-|------|------------|
-| `Tabs.cs` accesses tab properties before `BorderView` exists | `Tabs.cs` always sets `Border.Settings = Tab \| Title` first, which triggers `GetOrCreateView()` — `BorderView` exists before any tab property access |
-| Tests that set `Border.TabOffset` without first enabling `BorderSettings.Tab` | These tests must also set `Border.Settings` to include `Tab` (which creates `BorderView`) before accessing tab properties. Fix in test updates. |
-| Forgot a consumer — compile error | Good: compile errors are easy to find and fix. No silent runtime breakage. |
-| `ConfigureForTabMode` visibility change | Making it `internal` is safe — it's only called from within the assembly |