# RazorConsole > High-performance Blazor TUI framework, built on top of [Spectre.Console](https://spectreconsole.net). --- # Document: Quick Start ### Quick Start Guide Get up and running with RazorConsole in four straightforward steps. #### Step 1 · Installation Install the core package from NuGet: ```shell dotnet add package RazorConsole.Core ``` #### Step 2 · Project Setup Enable the Razor SDK so your Razor components compile correctly. Update your project file: ```xml Exe net8.0 enable ``` #### Step 3 · Build Your First Component Create a `Counter.razor` component: ```razor @using Microsoft.AspNetCore.Components @using Microsoft.AspNetCore.Components.Web @using RazorConsole.Components

Current count

@code { private int currentCount = 0; private void IncrementCount() { currentCount++; } } ``` Wire it up in `Program.cs`: ```csharp using Microsoft.Extensions.Hosting; using RazorConsole.Core; IHostBuilder hostBuilder = Host.CreateDefaultBuilder(args) .UseRazorConsole(); IHost host = hostBuilder.Build(); await host.RunAsync(); ``` #### Step 4 · Run the App Build and run your console UI: ```shell dotnet run ``` ![quick-start-counter image](https://github.com/user-attachments/assets/24d8cc11-6428-4886-93c1-873e45b47c74) You should see an interactive counter in the terminal. Use **Tab** to traverse focusable elements and **Enter** or **Space** to trigger actions. --- # Document: Built-in Components # Built-in Components RazorConsole ships with a library of Spectre.Console-powered components covering layout, input, display, and utility scenarios. You can combine them just like regular Razor components to build rich terminal experiences. ## Layout | Component | Highlights | | ------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | | [Align](https://razorconsole.github.io/RazorConsole/components/Align) | Centers or aligns child content horizontally/vertically with optional fixed width/height. | | [Columns](https://razorconsole.github.io/RazorConsole/components/Columns) | Flows children left-to-right, optionally expanding to fill the console width. | | [Rows](https://razorconsole.github.io/RazorConsole/components/Rows) | Stacks children vertically, great for wizard-style layouts. | | [Grid](https://razorconsole.github.io/RazorConsole/components/Grid) | Builds a multi-column layout with configurable column count and width. | | [Padder](https://razorconsole.github.io/RazorConsole/components/Padder) | Adds Spectre padding around nested content to create spacing. | | [Scrollable](https://razorconsole.github.io/RazorConsole/components/Scrollable) | Renders a sliding window of items (`PageSize`) with built-in keyboard navigation (Arrow keys, PageUp/Down). | ```razor ``` ## Input | Component | Highlights | | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | | [TextButton](https://razorconsole.github.io/RazorConsole/components/TextButton) | Focusable button with customizable colors and click handlers via `EventCallback`. | | [TextInput](https://razorconsole.github.io/RazorConsole/components/TextInput) | Collects user input with placeholder, change handler, and optional password masking. | | [Select](https://razorconsole.github.io/RazorConsole/components/Select) | Keyboard-driven dropdown with highlighted selection state and callbacks. | ```razor ``` ## Display | Component | Highlights | | --------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | | [Markup](https://razorconsole.github.io/RazorConsole/components/Markup) | Renders Spectre markup with color, background, and text decoration support. | | [Panel](https://razorconsole.github.io/RazorConsole/components/Panel) | Creates framed sections with optional title and border styling. | | [Border](https://razorconsole.github.io/RazorConsole/components/Border) | Wraps child content in a configurable border and padding. | | [BarChart](https://razorconsole.github.io/RazorConsole/components/BarChart) | Visualizes numeric data as horizontal bars with customizable styling, labels, and scaling. | | [BreakdownChart](https://razorconsole.github.io/RazorConsole/components/BreakdownChart) | Displays proportional data segments (pie-style) with optional legends and percentage values. | | [StepChart](https://razorconsole.github.io/RazorConsole/components/StepChart) | Plots discrete values over time using Unicode box-drawing characters and multiple series. | | [Figlet](https://razorconsole.github.io/RazorConsole/components/Figlet) | Produces large ASCII headers using Figlet fonts. | | [SyntaxHighlighter](https://razorconsole.github.io/RazorConsole/components/SyntaxHighlighter) | Displays colorized source code with optional line numbers. | | [SpectreCanvas](https://razorconsole.github.io/RazorConsole/components/SpectreCanvas) | Provides a low-level pixel buffer for drawing custom graphics or pixel art. | | [Markdown](https://razorconsole.github.io/RazorConsole/components/Markdown) | Renders Markdown text directly in the console. | | [Table](https://razorconsole.github.io/RazorConsole/components/Table) | Converts semantic `` markup into Spectre tables. | ```razor ``` ## Utilities | Component | Highlights | | ------------------------------------------------------------------------- | -------------------------------------------------- | | [Spinner](https://razorconsole.github.io/RazorConsole/components/Spinner) | Animated progress indicator with optional message. | | [Newline](https://razorconsole.github.io/RazorConsole/components/Newline) | Emits an empty line to separate sections. | ```razor ``` ## Tips - All components can be composed within one another—wrap inputs inside `Panel`, place buttons in `Columns`, etc. - Spectre colors map to `Spectre.Console.Color`; use `Color.Red`, `Color.Blue`, or RGB constructors for precise styling. - Prefer `EventCallback` parameters for handlers so components remain async-friendly. - Combine with RazorConsole focus management features to deliver intuitive keyboard navigation. --- # Document: Hot Reload ### Hot Reload Support Build, tweak, and iterate without leaving your running console app. RazorConsole supports hot reload via its metadata update handler so UI changes are reflected instantly—no restart required. #### How it works 1. Run your application with `dotnet watch`. 2. Update a Razor component. 3. Save the file. 4. Watch the running console UI refresh automatically. ```shell dotnet watch run ``` > **Tip:** Hot reload shines for component tweaks. Certain structural changes may still need a full restart. --- # Document: Routing # Routing This document explains how routing works in modern `RazorConsole` and how to use it. --- ## 1. Routing basics Routing in Blazor maps URLs to _Razor components_. Key pieces: - `@page` directive – declares a route for a component. - `` / `Routes.razor` – central router component that matches URLs to pages. - `NavigationManager` – service for programmatic navigation. --- ## 2. The `@page` directive Any Razor component (`.razor`) becomes routable when it has at least one `@page` directive: ```razor @page "/" @page "/home"

Home

``` - Each `@page` line defines a route template. - A component can have multiple routes (e.g., an old and a new URL). - Routes are relative to the app’s base URL `/`. ### Example from a simple page: ```razor @page "/welcome"

Welcome!

Welcome to Blazor!

``` ## 3. Route templates & parameters ### 3.1. Basic parameters You can define route parameters in the template: ```razor @page "/todos/{id:int}"

Todo @Id

@code { [Parameter] public int Id { get; set; } } ``` - `{id:int}` – parameter name is `id`, with an `int` constraint. - To get parameter from route use `[Parameter]` attribute. ### 3.2. Optional parameters Optional parameters use `?` syntax: ```razor @page "/products" @page "/products/{category?}"

Products @Category

@code { [Parameter] public string? Category { get; set; } } ``` `/products` and `/products/books` both resolve to the same component. ### 3.3. Multiple parameters ```razor @page "/orders/{year:int}/{month:int}" @code { [Parameter] public int Year { get; set; } [Parameter] public int Month { get; set; } } ``` ### 3.4. Catch-all parameters Catch-all parameters capture the rest of the URL segment: ```razor @page "/files/{*path}" @code { [Parameter] public string? Path { get; set; } } ``` Example URLs: - `/files/readme.txt` - `/files/images/logo.png` ## 4. Routing in `RazorConsole` In the new Blazor Web App template, routing is configured by the Routes component. Its as simple as in [web blazor](https://learn.microsoft.com/en-us/aspnet/core/blazor/fundamentals/routing?view=aspnetcore-10.0) A typical `Routes.razor` ```razor @using Microsoft.AspNetCore.Components.Routing

Sorry, there's nothing at this address.

``` Key points: - `AppAssembly` - router scans this assembly to find components with `@page`. - `` - renders the matched component. - `DefaultLayout` - layout used when the component doesn’t specify its own. - ``- content shown when no route matches. ## 5. Layouts and route rendering Layouts are normal components that wrap pages. Common pattern: ```razor @layout MainLayout @page "/counter"

Counter

... ``` If no `@layout` is specified: - The `DefaultLayout` from `RouteView` in `Routes.razor` is used. ## 6. Programmatic navigation with `NavigationManager` Blazor exposes [`NavigationManager`](https://learn.microsoft.com/en-us/aspnet/core/blazor/fundamentals/routing?view=aspnetcore-10.0) for navigating in code-behind or services. Inject it: ```razor @inject NavigationManager Navigation ``` Basic usage: ```cs Navigation.NavigateTo("/counter"); ``` ## 7. Unsupported features Feel free to contribute - `HeadOutlet` - there is no `head` in cli app. - [Hash routing](https://developer.mozilla.org/en-US/docs/Glossary/Hash_routing) - `NavLink` ## 8. Examples [RazorConsole.Gallery](https://github.com/RazorConsole/RazorConsole/blob/main/src/RazorConsole.Gallery) --- # Document: Native Ahead-of-Time Compilation # Native AOT This document explains how to use **Native Ahead-of-Time (AOT)** compilation with **RazorConsole** to build standalone, lightning-fast console applications. > [!WARNING] > Native AOT support in RazorConsole is currently **experimental**. > While core features like routing and rendering are tested and working, you may encounter edge cases with third-party > libraries or complex reflection scenarios. Please report any issues on [GitHub](https://github.com/RazorConsole/RazorConsole/issues/new?template=bug-report.yml). --- ## 1. What is Native AOT? Native AOT compiles your .NET application directly into _native machine code_ like other compiled languages does, rather than Intermediate Language (IL) that requires a JIT compiler at runtime. **Benefits for Console Apps:** - **Instant Startup:** No JIT warm-up time. - **Smaller Footprint:** No need to install the .NET Runtime on the target machine; the app is self-contained. - **Single File:** The output is a single binary executable. --- ## 2. Prerequisites To build Native AOT applications, you need platform-specific build tools installed on your development machine or CI environment. Look at this article in [msdocs](https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/?tabs=windows%2Cnet8). --- ## 3. How to Publish To publish your application as a native executable, use the standard `dotnet publish` command with the `-p:PublishAot=true` property. You **must** specify a Runtime Identifier (RID), as native code is platform-specific. ```bash # Publish for Linux dotnet publish -c Release -r linux-x64 -p:PublishAot=true # Publish for Windows dotnet publish -c Release -r win-x64 -p:PublishAot=true # Publish for macOS (Apple Silicon) dotnet publish -c Release -r osx-arm64 -p:PublishAot=true ``` The resulting binary will be located in `bin/Release/net8.0/{rid}/publish/`. --- ## 4. Known Warnings & Limitations ### 4.1. The `IL2104` Warning During the build, you might see: > `warning IL2104: Assembly 'Microsoft.AspNetCore.Components' produced trim warnings` **Why this happens:** Blazor was designed for browser scenarios where the full .NET runtime is available. Some internal Blazor APIs use reflection patterns that the AOT analyzer cannot verify. **Is it safe?** Yes, for RazorConsole use cases. We've tested core features (routing, rendering, DI) and they work correctly. The warnings are about unused code paths in Blazor's browser-specific features. **Suppressing the warning:** ```xml $(NoWarn);IL2104 ``` **When to investigate:** If you're using advanced Blazor features beyond basic component rendering, test thoroughly with AOT. ### 4.2. Routing and Pages By default, the .NET AOT compiler trims unused code aggressively. Because the Router finds pages via reflection, the trimmer might accidentally remove your page components if they aren't directly referenced. To ensure routing works correctly, you must prevent your application assembly from being trimmed. Add this to your project file (`.csproj`): ```xml ``` ### 4.3. Reflection & Parameters Native AOT aggressively trims unused code. Anonymous types rely on reflection to read properties at runtime, and the trimmer may remove property metadata if it cannot statically prove the properties are used. **Avoid Anonymous Types for Parameters:** ```csharp // Avoid this in AOT // The trimmer may remove property metadata, causing runtime failures var parameters = new { Title = "Hello", Count = 5 }; ``` **Use Dictionary Instead:** Explicitly using `Dictionary` ensures the AOT compiler preserves the data. ```csharp // Preferred way for AOT var parameters = new Dictionary { { "Title", "Hello" }, { "Count", 5 } }; await renderer.RenderAsync(parameters); ``` ### 4.4. What Works & What Doesn't **✅ AOT-Compatible:** - Razor component rendering - Routing (`@page` directives) - Dependency injection - `System.Text.Json` (with source generators) - LINQ (query syntax) **⚠️ Requires Care:** - Third-party libraries (check for `IsAotCompatible`) - Custom reflection code - Dynamic assembly loading **❌ Not Supported:** - `System.Reflection.Emit` - C# dynamic keyword --- ## 5. Troubleshooting ### Build fails with `error MSB3073` or `link.exe` not found (Windows) This usually means the C++ Build Tools are missing. 1. Open **Visual Studio Installer**. 2. Modify your installation. 3. Check **Desktop development with C++**. ### App crashes immediately (Segmentation Fault / MissingMethodException) If your app uses third-party libraries that rely heavily on reflection (e.g., JSON serializers other than `System.Text.Json` source generator), they might be incompatible with AOT. - Try enabling the AOT analysis warnings in your project to see potential issues: ```xml true ``` --- ## 6. Examples You can see a working AOT setup in the [RazorConsole.Gallery](https://github.com/RazorConsole/RazorConsole/blob/main/src/RazorConsole.Gallery) project. --- # Document: Custom Translators ### Custom Translators RazorConsole converts Razor components into Spectre.Console renderables through a Virtual DOM (VDOM) translation pipeline. You can plug into that pipeline with custom translators to render bespoke elements. #### Creating a translator Implement the `IVdomElementTranslator` interface and translate nodes that match your criteria: ```csharp using RazorConsole.Core.Rendering.Vdom; using RazorConsole.Core.Vdom; using Spectre.Console; using Spectre.Console.Rendering; public sealed class OverflowElementTranslator : IVdomElementTranslator { // Lower priority values are processed first (1-1000+) public int Priority => 85; public bool TryTranslate( VNode node, TranslationContext context, out IRenderable? renderable) { renderable = null; // Check for a div with an overflow attribute if (node.Kind != VNodeKind.Element || !string.Equals(node.TagName, "div", StringComparison.OrdinalIgnoreCase)) { return false; } if (!node.Attributes.TryGetValue("data-overflow", out var overflowType)) { return false; } if (!VdomSpectreTranslator.TryConvertChildrenToRenderables( node.Children, context, out var children)) { return false; } var content = VdomSpectreTranslator.ComposeChildContent(children); renderable = overflowType?.ToLowerInvariant() switch { "ellipsis" => new Padder(content).Overflow(Overflow.Ellipsis), "crop" => new Padder(content).Overflow(Overflow.Crop), "fold" => new Padder(content).Overflow(Overflow.Fold), _ => content }; return true; } } ``` #### Registering the translator ```csharp using Microsoft.Extensions.Hosting; using RazorConsole.Core; using RazorConsole.Core.Vdom; IHostBuilder hostBuilder = Host.CreateDefaultBuilder(args) .UseRazorConsole(configure: config => { config.ConfigureServices(services => { services.AddVdomTranslator(); }); } ); IHost host = hostBuilder.Build(); await host.RunAsync(); ``` #### Using it in components ```razor
This text will be truncated with ellipsis if it's too long
``` For a deeper dive, read the [custom translators guide](https://github.com/RazorConsole/RazorConsole/blob/main/design-doc/custom-translators.md). --- # Document: Absolute Positioning & Z-Index # Absolute Positioning & Z-Index This document explains how absolute positioning and layering work in `RazorConsole` and how to create complex layouts using the `absolute` coordinate system. --- ## 1. Positioning Basics By default, elements in `RazorConsole` follow the **Normal Flow** (stacked vertically or horizontally depending on the container). When you apply `position="absolute"`, the element is: - **Removed from the normal flow**: It no longer takes up space in the layout, and other elements behave as if it isn't there. - **Placed on an Overlay Layer**: It is rendered on top of the background content. - **Positioned relative to the Document Root (Canvas)** or its nearest positioned ancestor. --- ## 2. Coordinate System You can control the position of an absolute element using four attributes: `top`, `bottom`, `left`, and `right`. | Attribute | Description | | ------------ | -------------------------------------------------------- | | **`top`** | Distance from the top edge of the document/ancestor. | | **`left`** | Distance from the left edge of the document/ancestor. | | **`bottom`** | Distance from the bottom edge of the **total document**. | | **`right`** | Distance from the right edge of the **total document**. | ### 2.1. Stretching If you provide both `left` and `right` , the element will **stretch** to fill the specified range. `top` and `bottom` vertical stretching doesn't work, because of the current render system, that does not allow to set height directly. ```razor
``` > [!NOTE] Horizontal stretch will work correctly only with elements that allows to be expanded (like ``). --- ## 3. Hierarchical Positioning (Cumulative Offsets) `RazorConsole` supports nested absolute positioning. If an `absolute` element is placed inside another `absolute` element, the child's `top` and `left` values are added to the parent's coordinates. This is known as **Cumulative Offsets**. The formula for the final global position is: ### Example of nesting: ```razor
``` > [!NOTE] `bottom` and `right` always calculate their position relative to the **edges of the entire document (Canvas)**, regardless of nesting. --- ## 4. Z-Index and Layering The `z-index` attribute determines the stacking order of elements that overlap. - **Default value:** `0`. - **Higher values:** Elements move "closer" to the user (rendered on top). - **Lower/Negative values:** Elements move "further back". ```razor
Top Layer
Bottom Layer
``` In this example, the **Red Panel** will be rendered over the **Blue Panel** because it has a higher `z-index`, even though it starts earlier in the code. --- ## 5. Canvas Expansion In `RazorConsole`, the "Document" (Canvas) is dynamic. 1. It starts with the size of the background content. 2. If an absolute element is placed outside these bounds (e.g., `top="50"` when the background only has 10 lines), the **Canvas automatically expands** with empty lines to accommodate the element. --- ## 6. Implementation Details Absolute positioning is handled by the [`AbsolutePositionMiddleware`](https://github.com/LittleLittleCloud/RazorConsole/blob/main/src/RazorConsole.Core/Rendering/Translation/Translators/AbsolutePositionMiddleware.cs). It intercepts nodes with the `position="absolute"` attribute and moves them to a special `CollectedOverlays` list in the `TranslationContext`. The final composition is performed by [`OverlayRenderable`](https://github.com/LittleLittleCloud/RazorConsole/blob/main/src/RazorConsole.Core/Renderables/OverlayRenderable.cs), which: 1. Renders the background. 2. Splits the output into a line-based `canvas`. 3. Handles `z-index` sorting before merging 4. Merges overlay segments into the canvas. --- ## 7. Unsupported Features - **`position="relative"` or `position="fixed"`**: Currently, we have only `absolute` position or non-positioned elements in main flow. - **Percentage units**: Only integer values (character units) are supported (e.g., `top="10%"` is not supported). --- # Document: Keyboard Events ### Keyboard Events Interactive experiences rely on keyboard input. RazorConsole exposes the familiar Blazor event model so you can respond to keystrokes just like you would on the web. #### Custom key handling ```razor
@code { private string message = "Press any key..."; private void HandleKeyPress(KeyboardEventArgs e) { message = $"You pressed: {e.Key}"; StateHasChanged(); } } ``` #### Supported events - `@onkeydown` — fires when a key is pressed. - `@onkeyup` — fires when a key is released. - `@onkeypress` — fires when a key is pressed and released. --- # Document: Focus Management # Focus Management Console UIs need strong focus cues for keyboard navigation. RazorConsole provides a `FocusManager` that automatically tracks focusable elements and coordinates focus changes, making keyboard navigation predictable and accessible. ## Overview The `FocusManager` is a singleton service that: - Tracks all focusable elements in the virtual DOM - Manages focus order and navigation - Dispatches focus events (`onfocus`, `onfocusin`, `onfocusout`) - Automatically refocuses when the DOM structure changes - Provides programmatic control over focus Focus management is handled automatically when you use RazorConsole's built-in components, but you can also control focus programmatically for advanced scenarios. ## Making Elements Focusable Elements become focusable in two ways: ### 1. Using `data-focusable` Attribute Set `data-focusable="true"` on any element to make it focusable: ```razor
``` ### 2. Elements with Event Handlers Elements with event handlers (like `@onclick`, `@onkeydown`) are automatically focusable: ```razor
``` ### 3. Built-in Components Built-in components like `TextInput` and `TextButton` are automatically focusable: ```razor ``` ## Setting Focus Order Use the `FocusOrder` parameter on built-in components to control tab order: ```razor ``` For custom elements, use the `data-focus-order` attribute: ```razor
``` ## Keyboard Navigation Users can navigate between focusable elements using: - **Tab** - Move focus to the next element - **Shift + Tab** - Move focus to the previous element Navigation wraps around: when reaching the last element, Tab moves to the first, and vice versa. ## Programmatic Focus Control You can programmatically control focus by injecting `FocusManager` into your components. ### Injecting FocusManager ```razor @using RazorConsole.Core.Focus @inject FocusManager FocusManager @code { // Use FocusManager methods here } ``` ### Available Methods #### FocusAsync(string key) Focus a specific element by its key: ```razor @using RazorConsole.Core.Focus @inject FocusManager FocusManager @code { private string username = string.Empty; private string password = string.Empty; private async Task FocusUsername() { await FocusManager.FocusAsync("username-input"); } } ``` #### FocusNextAsync() and FocusPreviousAsync() Move focus programmatically: ```razor @using RazorConsole.Core.Focus @inject FocusManager FocusManager @code { private string field1 = string.Empty; private string field2 = string.Empty; private string field3 = string.Empty; private async Task MoveToNext() { await FocusManager.FocusNextAsync(); } private async Task MoveToPrevious() { await FocusManager.FocusPreviousAsync(); } } ``` #### Checking Focus State Check if an element is currently focused: ```razor @using RazorConsole.Core.Focus @inject FocusManager FocusManager
@code { // Check current focus private string? CurrentFocus => FocusManager.CurrentFocusKey; // Check if manager has any focusable elements private bool HasFocusables => FocusManager.HasFocusables; } ``` ### Subscribing to Focus Changes Subscribe to the `FocusChanged` event to react to focus changes: ```razor @using RazorConsole.Core.Focus @inject FocusManager FocusManager @implements IDisposable @code { private string? currentFocus; protected override void OnInitialized() { FocusManager.FocusChanged += OnFocusChanged; currentFocus = FocusManager.CurrentFocusKey; } private void OnFocusChanged(object? sender, FocusChangedEventArgs e) { currentFocus = e.Key; StateHasChanged(); } public void Dispose() { FocusManager.FocusChanged -= OnFocusChanged; } } ``` ## Responding to Focus Events Elements can respond to focus changes using event handlers: ### onfocus Fired when an element receives focus: ```razor
@code { private string message = "Not focused"; private void OnFocus(FocusEventArgs e) { message = "Focused!"; StateHasChanged(); } } ``` ### onfocusin Similar to `onfocus`, but bubbles up through parent elements: ```razor
@code { private void OnFocusIn(FocusEventArgs e) { // Fired when child receives focus } } ``` ### onfocusout Fired when an element loses focus: ```razor
@code { private string message = "Not focused"; private void OnFocus(FocusEventArgs e) { message = "Focused!"; StateHasChanged(); } private void OnFocusOut(FocusEventArgs e) { message = "Focus lost"; StateHasChanged(); } } ``` ## Focus Sessions Focus management operates within a session that tracks the current render context. Sessions are automatically managed by RazorConsole when your application starts. The `FocusManager`: - Automatically selects the first focusable element when a session begins - Maintains focus state across re-renders - Automatically refocuses when the currently focused element is removed from the DOM - Clears focus when all focusable elements are removed ## Navigation Between Pages When navigating between pages or components, focus management automatically adapts: 1. **New Page Loads**: The first focusable element is automatically focused 2. **Component Changes**: Focus is maintained if the same element exists in the new view 3. **Element Removal**: If the focused element is removed, focus moves to the next available element Example with navigation: ```razor @using RazorConsole.Core.Focus @inject FocusManager FocusManager @inject NavigationManager Navigation @code { private async Task NavigateToLogin() { Navigation.NavigateTo("/login"); // Focus will automatically move to the first focusable element // on the login page when it renders } } ``` ## Complete Example Here's a complete example demonstrating focus management: ```razor @using RazorConsole.Core.Focus @using RazorConsole.Components @inject FocusManager FocusManager @implements IDisposable @code { private string value1 = string.Empty; private string value2 = string.Empty; private string value3 = string.Empty; private string? currentFocus; protected override void OnInitialized() { FocusManager.FocusChanged += OnFocusChanged; currentFocus = FocusManager.CurrentFocusKey; } private void OnFocusChanged(object? sender, FocusChangedEventArgs e) { currentFocus = e.Key; StateHasChanged(); } private async Task FocusFirst() { await FocusManager.FocusAsync("input1"); } private async Task FocusSecond() { await FocusManager.FocusAsync("input2"); } private async Task FocusThird() { await FocusManager.FocusAsync("input3"); } private async Task FocusNext() { await FocusManager.FocusNextAsync(); } private async Task FocusPrevious() { await FocusManager.FocusPreviousAsync(); } public void Dispose() { FocusManager.FocusChanged -= OnFocusChanged; } } ``` ## Best Practices 1. **Always use `@key` attributes** on focusable elements to ensure stable focus keys 2. **Set `FocusOrder`** on form elements to create a logical tab sequence 3. **Handle focus events** to provide visual feedback when elements receive/lose focus 4. **Use `FocusManager` programmatically** for complex navigation scenarios or when focus needs to change based on application logic 5. **Clean up event subscriptions** by implementing `IDisposable` and unsubscribing from `FocusChanged` events 6. **Test keyboard navigation** to ensure your UI is accessible and intuitive --- # Document: VDom Tree Debugging ### VDom Tree Visualization Debug and inspect the Virtual DOM structure of your RazorConsole components with the built-in VDom tree printer. #### Overview RazorConsole uses a Virtual DOM (VDOM) to efficiently render Razor components to the console. When debugging complex component hierarchies or investigating rendering issues, you can enable the VDom tree printer to visualize the internal structure. #### How to Enable Set the `RC_PRINT_VDOM_TREE` environment variable to `true` before running your application: **On Windows (PowerShell):** ```shell $env:RC_PRINT_VDOM_TREE="true" dotnet run ``` **On Linux/macOS:** ```shell RC_PRINT_VDOM_TREE=true dotnet run ``` **Or inline:** ```shell RC_PRINT_VDOM_TREE=true dotnet watch run ``` #### What You'll See When enabled, the tree printer displays each frame's VDOM structure in a panel, showing: - **Node hierarchy** - Visual tree structure with indentation - **Node types** - Element, Text, Component, or Region - **Element details** - Tag names, keys, IDs, and text content - **Attributes** - All data attributes attached to nodes - **Events** - Registered event handlers (onclick, onfocus, etc.) **Example output:** ``` Frame 1 ┌─────────────────────────────────────────┐ │ • Element div key=root-key text='...' │ │ v-id=a3f2 attrs[data-rows=true] │ │ ├── Element span key=first │ │ │ text='First Item' v-id=b7c4 │ │ │ attrs[data-focusable=true] │ │ │ events[onfocus, onfocusin] │ │ └── Element span key=second │ │ text='Second Item' v-id=c1d8 │ │ attrs[data-focusable=true] │ │ events[onfocus, onfocusin] │ └─────────────────────────────────────────┘ ``` #### Frame History The tree printer accumulates frames as your application runs, allowing you to see how the VDOM evolves over time. Each panel represents a snapshot of the VDOM at a specific render cycle. > **Note:** This feature has a performance impact and is intended for development and debugging only. Don't enable it in production environments. #### Technical Details The VDom tree printer is implemented as an `IVdomElementTranslator` with priority 0 (highest priority). When enabled, it intercepts the translation process and generates a text representation of the entire VDOM tree before passing through to the standard rendering pipeline. For more information on custom translators, see the [Custom Translators](/docs#custom-translators) guide. --- # Document: Component Gallery ### Interactive Component Gallery Explore every RazorConsole component in a live playground. ```shell dotnet tool install --global RazorConsole.Gallery ``` ```shell razorconsole-gallery ``` The gallery lets you experiment with layouts, inputs, and utilities before pulling them into your own app. --- # Component: Align Wraps child content in an alignment container. ### Parameters: | Name | Type | Default | Description | | ------------ | ---------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------- | | ChildContent | Microsoft.AspNetCore.Components.RenderFragment | - | Aligns content horizontally and vertically within a container using Spectre.Console's Align renderable. | | Height | int? | - | Height of the alignment container in characters. If `null`, automatically determined by content. | | Horizontal | HorizontalAlignment | - | Horizontal alignment of the content. Default is Left. | | Vertical | VerticalAlignment | - | Vertical alignment of the content. Default is Top. | | Width | int? | - | Width of the alignment container in characters. If `null`, automatically determined by content. | ### Usage Example (Align_1.razor): ````razor @using Spectre.Console @using RazorConsole.Components ```` --- # Component: Border Creates a bordered panel around its children. ### Parameters: | Name | Type | Default | Description | | ------------ | ---------------------------------------------- | ------- | -------------------------------------------------------------------------------------- | | BorderColor | Color? | - | Color of the border. If `null`, uses default console color. | | BoxBorder | BoxBorder | - | Style of the border. Default is Rounded. See BoxBorder for available styles. | | ChildContent | Microsoft.AspNetCore.Components.RenderFragment | - | Renders a simple border around content without a title (simplified wrapper for Panel). | | Padding | Padding | - | Padding inside the border as (left, top, right, bottom). Default is (0, 0, 0, 0). | ### Usage Example (Border_1.razor): ````razor @using Spectre.Console @using RazorConsole.Components ```` --- # Component: BarChart Renders a horizontal bar chart with optional label, colors and value display. ### Parameters: | Name | Type | Default | Description | | --------------- | ------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | BarChartItems | List | - | Renders a bar chart using Spectre.Console's BarChart renderable. | | Culture | CultureInfo? | - | CultureInfo to use when rendering values. Default is CurrentCulture. | | Label | string? | - | Label (title) displayed above the bar chart. | | LabelAlignment | Justify? | - | Alignment of the chart label. Options: Left, Center, Right. | | LabelBackground | Color? | - | Background color of the chart label. Default is Plain background (transparent). | | LabelDecoration | Decoration? | - | Text decoration for the chart label (bold, italic, underline, etc.). Default is None. | | LabelForeground | Color? | - | Foreground (text) color of the chart label. Default is Plain foreground. | | MaxValue | double? | - | Fixed maximum value for scaling bars. When set, bars scale relative to this value instead of the largest data point. Example: `MaxValue = 100` creates a progress chart (0–100%). | | ShowValues | bool | - | Whether numeric values should be displayed next to each bar. Default is `false`. | | Width | int? | - | Width of the bar chart in characters. If `null`, uses available console width. | ### Usage Example (BarChart_1.razor): ````razor @using RazorConsole.Components @using System.Globalization @using Spectre.Console @code { private List SalesData => new() { new BarChartItem("Jan", 65.2, Color.FromHex("29B8DB")), new BarChartItem("Feb", 78.9, Color.FromHex("0DBC79")), new BarChartItem("Mar", 91.5, Color.FromHex("F5F543")) }; } ```` --- # Component: BreakdownChart Displays a breakdown chart showing proportional data. ### Parameters: | Name | Type | Default | Description | | ----------------------- | -------------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------ | | BreakdownChartItems | System.Collections.Generic.List{Spectre.Console.IBreakdownChartItem} | - | Renders a breakdown chart using Spectre.Console's BreakdownChart renderable. | | Compact | System.Boolean | - | Whether the chart and tags should be rendered in compact mode. Default is `false`. | | Culture | System.Globalization.CultureInfo | - | CultureInfo to use when rendering values. Default is CurrentCulture. | | Expand | System.Boolean | - | Whether the chart should expand to available space. When `false`, width is automatically calculated. Default is `false`. | | ShowTagValues | System.Boolean | - | Whether to show tag values. Default is `false`. | | ShowTagValuesPercentage | System.Boolean | - | Whether to show tag values with percentage. Default is `false`. | | ShowTags | System.Boolean | - | Whether to show tags. Default is `false`. | | ValueColor | System.Nullable{Spectre.Console.Color} | - | Color in which the values will be shown. If `null`, uses default color. | | Width | System.Nullable{System.Int32} | - | Width of the breakdown chart in characters. If `null`, automatically calculated. | ### Usage Example (BreakdownChart_1.razor): ````razor @using RazorConsole.Components @using System.Globalization @using Spectre.Console @code { private List Expenses => new() { new BreakdownChartItem("Food", 3200, Color.FromHex("F5F543")), new BreakdownChartItem("Transport", 1800, Color.FromHex("3B8EEA")), new BreakdownChartItem("Utilities", 2500, Color.FromHex("CD3131")), new BreakdownChartItem("Fun", 1400, Color.FromHex("0DBC79")), new BreakdownChartItem("Other", 1100, Color.FromHex("666666")) }; } ```` --- # Component: Columns Arranges children in columns. ### Parameters: | Name | Type | Default | Description | | ------------ | ---------------------------------------------- | ------- | ------------------------------------------------------------------------------------- | | ChildContent | Microsoft.AspNetCore.Components.RenderFragment | - | Content to arrange in columns. | | Expand | System.Boolean | - | Whether columns should expand to fill available horizontal space. Default is `false`. | ### Usage Example (Columns_1.razor): ````razor @using Spectre.Console @using RazorConsole.Components ```` --- # Component: Figlet Renders ASCII art text. ### Parameters: | Name | Type | Default | Description | | ------- | ------------- | ------- | ----------------------------------------------------------------------- | | Color | Color? | - | Color of the FIGlet text. Default is Default (console's default color). | | Content | string? | - | Text content to render as FIGlet ASCII art. | | Font | System.String | - | Custom FIGlet font name or path to .flf file | | Justify | Justify? | - | Horizontal alignment of the FIGlet text. Default is Center. | ### Usage Example (Figlet_1.razor): ````razor @using Spectre.Console @using RazorConsole.Components ```` --- # Component: Grid Arranges children in a grid layout. ### Parameters: | Name | Type | Default | Description | | ------------ | ---------------------------------------------- | ------- | -------------------------------------------------------------------------------- | | ChildContent | Microsoft.AspNetCore.Components.RenderFragment | - | Arranges content in a multi-column grid using Spectre.Console's Grid renderable. | | Columns | System.Int32 | - | Number of columns in the grid. Default is 2. Must be positive. | | Expand | System.Boolean | - | Whether the grid should expand to fill available space. Default is `false`. | | Width | System.Nullable{System.Int32} | - | Width of the grid in characters. If `null`, automatically determined by content. | ### Usage Example (Grid_1.razor): ````razor @using Spectre.Console @using RazorConsole.Components ```` --- # Component: ModalWindow Renders a modal in a dialog. ### Parameters: | Name | Type | Default | Description | | -------------------- | --------------------------------------------------------------------------- | ------- | --------------------------------------------------------- | | AdditionalAttributes | System.Collections.Generic.IReadOnlyDictionary{System.String,System.Object} | - | Additional HTML attributes to apply to the table element. | | ChildContent | Microsoft.AspNetCore.Components.RenderFragment | - | | | IsOpened | System.Boolean | - | Parameter that determines visibility of modal window | ### Usage Example (ModalWindow_1.razor): ````razor @using RazorConsole.Components @using Spectre.Console @using Panel = RazorConsole.Components.Panel @if (!_isOpened) { } @code { private bool _isOpened = true; private Color _currentColor = Color.Orange1; private void CloseModal() { _isOpened = false; StateHasChanged(); } private void OpenModal() { _isOpened = true; StateHasChanged(); } private void ChangeColor() { _currentColor = _currentColor == Color.Orange1 ? Color.Red3 : Color.Orange1; StateHasChanged(); } } ```` --- # Component: Markdown Renders markdown content. ### Parameters: | Name | Type | Default | Description | | ------- | ------------- | ------- | -------------------------------------------------------------- | | Content | System.String | - | Markdown content to render. Supports standard Markdown syntax. | ### Usage Example (Markdown_1.razor): ````razor @using Spectre.Console @using RazorConsole.Components @code { private static string markdownText => @"# Welcome to Markdown This is a **bold** statement and this is *italic*. You can also have `inline code`. ## Features Here's what you can do with markdown: - Create bullet lists - With multiple items - Like this one ### Ordered Lists 1. First item 2. Second item 3. Third item ### Nested Lists - Top level item A - Child item A.1 - Grandchild item `A.1.a` - Child item A.2 ### Code Blocks ```csharp public class HelloWorld { public static void Main() { Console.WriteLine(""Hello, World!""); } } ``` ```python def greet(name): print(f""Hello, {name}!"") greet(""World"") ``` ### Quotes > This is a quote block. > It can span multiple lines. ### Tables | Feature | Supported | Description | |---------|-----------|-------------| | Basic Tables | ✓ | Simple table formatting | | Column Alignment | ✓ | Left, center, right alignment | | Complex Content | ✓ | Code, links, and formatting in cells | Here's a more detailed table: | Language | Extension | Example Code | Performance | |:---------|:---------:|:-------------|------------:| | C# | `.cs` | `Console.WriteLine(""Hello"");` | Fast | | Python | `.py` | `print(""Hello"")` | Medium | | JavaScript | `.js` | `console.log(""Hello"");` | Variable | --- That's a horizontal rule above! ".Trim(); } ```` --- # Component: Markup Renders styled text with markup. ### Parameters: | Name | Type | Default | Description | | ---------- | ----------- | ------- | ------------------------------------------------------------------------------------------------------ | | Background | Color? | - | Background color. Default is Plain background. | | Content | string? | - | Text content to render. Content is automatically escaped to prevent markup interpretation. | | Decoration | Decoration? | - | Text decoration (bold, italic, underline, etc.). Default is None. Combine decorations with bitwise OR. | | Foreground | Color? | - | Foreground (text) color. Default is Plain foreground. | | link | string? | - | Optional hyperlink URL. When specified, text renders as a clickable link in supported terminals. | ### Usage Example (Markup_1.razor): ````razor @using Spectre.Console @using RazorConsole.Components ```` --- # Component: Padder Adds padding around its children. ### Parameters: | Name | Type | Default | Description | | ------------ | ---------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ChildContent | Microsoft.AspNetCore.Components.RenderFragment | - | Content to which padding will be applied. | | Padding | Spectre.Console.Padding | - | Padding to apply as (left, top, right, bottom) in characters. Default is (0, 0, 0, 0). Example: `new Padding(2, 1, 2, 1)` adds 2 characters horizontally and 1 line vertically. | ### Usage Example (Padder_1.razor): ````razor @using Spectre.Console @using RazorConsole.Components ```` --- # Component: Panel Creates a bordered panel with optional title. ### Parameters: | Name | Type | Default | Description | | ------------ | ---------------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------- | | Border | BoxBorder | - | Style of the panel border. See BoxBorder for available styles like Rounded, Square, and Double. | | BorderColor | Color? | - | Color of the panel border. If `null`, uses default console color. | | ChildContent | Microsoft.AspNetCore.Components.RenderFragment | - | Renders a panel with optional title, border, and padding using Spectre.Console's Panel renderable. | | Expand | bool | - | Whether the panel should expand to fill available space. Default is `false`. | | Height | int? | - | Height of the panel in lines. If `null` or less than 1, height is automatically determined by content. | | Padding | Padding? | - | Padding inside the panel border as (left, top, right, bottom). If `null`, no padding is applied. | | Title | string? | - | Title text displayed at the top of the panel border. If `null` or empty, no title is shown. | | TitleColor | Color? | - | Color of the panel title. If `null`, uses default console color. | | Width | int? | - | Width of the panel in characters. If `null` or less than 1, width is automatically determined by content. | ### Usage Example (Panel_1.razor): ````razor @using Spectre.Console @using RazorConsole.Components ```` --- # Component: Rows Arranges children in rows. ### Parameters: | Name | Type | Default | Description | | ------------ | ---------------------------------------------- | ------- | -------------------------------------------------------------------------- | | ChildContent | Microsoft.AspNetCore.Components.RenderFragment | - | Content to arrange in rows. | | Expand | System.Boolean | - | Arranges content in vertical rows using Spectre.Console's Rows renderable. | ### Usage Example (Rows_1.razor): ````razor @using Spectre.Console @using RazorConsole.Components ```` --- # Component: Scrollable Provides scrollable content area. ### Parameters: | Name | Type | Default | Description | | ------------------- | ----------------------------------------------------------------------------------------------------------- | ------- | ----------------------------------------------------------------------------- | | ChildContent | Microsoft.AspNetCore.Components.RenderFragment{RazorConsole.Components.Scrollable`1.ScrollContext{{TItem}}} | - | Child content template that receives the visible items and scroll context. | | IsScrollbarEmbedded | System.Boolean | - | Flag that determines will scrollbar be embedded or not. | | Items | System.Collections.Generic.IReadOnlyList{{TItem}} | - | Provides scrollable navigation through a list of items with keyboard support. | | PageSize | System.Int32 | - | Number of items visible at one time (page size). | | ScrollOffset | System.Int32 | - | Current scroll offset (index of the first visible item). | | ScrollOffsetChanged | Microsoft.AspNetCore.Components.EventCallback{System.Int32} | - | Event callback invoked when the scroll offset changes. | | Scrollbar | RazorConsole.Core.Rendering.ScrollbarSettings | - | Scrollbar settings. If provided, the scrollbar is enabled. | ### Usage Example (Scrollable_1.razor): ````razor @using Microsoft.AspNetCore.Components.Web @using Spectre.Console @using RazorConsole.Components N Letter @foreach (var item in context) { } @*Spaces beteween panels*@ N Letter @foreach (var item in context) { }
    @foreach (var item in context) {
  1. }
    @foreach (var item in context) {
  1. }
@code { private Color _tableColor = Color.White; record Item(int Number, string Letter, Color Color); private IReadOnlyList<(int Number, string Letter, Color Color)> GetAlphabetData() { return [ (1, "A", Color.Yellow), (2, "B", Color.Red), (3, "C", Color.Aqua), (4, "D", Color.Orange1), (5, "E", Color.Chartreuse1), (6, "F", Color.Magenta1), (7, "G", Color.Green3), (8, "H", Color.Blue), (9, "I", Color.Purple), (10, "J", Color.Gold1), (11, "K", Color.Turquoise2), (12, "L", Color.HotPink), (13, "M", Color.Lime), (14, "N", Color.LightCoral), (15, "O", Color.SkyBlue1) ]; } private void OnFocusTable(FocusEventArgs e) { _tableColor = Color.Aqua; } private void OnFocusOutTable(FocusEventArgs e) { _tableColor = Color.White; } } ```` --- # Component: ViewHeightScrollable Provides scrollable content area that scrolls through physical lines of any content. Has all functionalities of default Scrollable. ### Parameters: | Name | Type | Default | Description | | ------------------- | ---------------------------------------------------------------------------------------------------------- | ------- | ---------------------------------------------------------- | | ChildContent | Microsoft.AspNetCore.Components.RenderFragment{RazorConsole.Components.ViewHeightScrollable.ScrollContext} | - | | | IsScrollbarEmbedded | System.Boolean | - | Flag that determines will scrollbar be embedded or not. | | LinesToRender | System.Int32 | - | Number of lines visible at one time. | | ScrollOffset | System.Int32 | - | Current scroll offset (index of the first visible line). | | ScrollOffsetChanged | Microsoft.AspNetCore.Components.EventCallback{System.Int32} | - | Event callback invoked when the scroll offset changes. | | Scrollbar | RazorConsole.Core.Rendering.ScrollbarSettings | - | Scrollbar settings. If provided, the scrollbar is enabled. | ### Usage Example (ViewHeightScrollable_1.razor): ````razor @using RazorConsole.Components @using Spectre.Console @using Markup = RazorConsole.Components.Markup @using Panel = RazorConsole.Components.Panel @code { private readonly string _largeText =@" #### Counter.razor ```razor @using Microsoft.AspNetCore.Components @using Microsoft.AspNetCore.Components.Web @using RazorConsole.Components

Current count

@code { private int currentCount = 0; private void IncrementCount() { currentCount++; } } ``` #### Program.cs ```csharp using Microsoft.Extensions.Hosting; using RazorConsole.Core; IHostBuilder hostBuilder = Host.CreateDefaultBuilder(args) .UseRazorConsole(); IHost host = hostBuilder.Build(); await host.RunAsync(); ``` ".Trim(); } ```` --- # Component: Select Interactive dropdown for choosing a value with keyboard navigation. ### Parameters: | Name | Type | Default | Description | | ------------------------ | --------------------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------ | | AdditionalAttributes | System.Collections.Generic.IReadOnlyDictionary{System.String,System.Object} | - | Additional attributes to apply to the root element. | | Comparer | System.Collections.Generic.IEqualityComparer{{TItem}} | - | Custom comparer for items in the list. Default is object.Equals() | | Expand | System.Boolean | - | Expands the rows layout to fill available space when true. | | FocusedValue | {TItem} | - | Currently highlighted option during keyboard navigation (may differ from committed Value). | | FocusedValueChanged | Microsoft.AspNetCore.Components.EventCallback{{TItem}} | - | Event raised when the focused option changes. | | Formatter | System.Func{{TItem},System.String} | - | Custom formatter for the items in the list. Default is object.ToString() | | IsFocused | System.Boolean | - | Indicates whether the select currently has focus. | | IsFocusedChanged | Microsoft.AspNetCore.Components.EventCallback{System.Boolean} | - | Event raised when the focus state changes. | | OptionDecoration | Spectre.Console.Decoration | - | Text decoration for non-focused options. | | OptionForeground | Spectre.Console.Color | - | Foreground color for non-focused options. | | Options | {TItem}[] | - | Available options rendered by the select. | | SelectedIndicator | System.Char | - | Character used to indicate the focused option. | | SelectedOptionDecoration | Spectre.Console.Decoration | - | Text decoration for the focused option. | | SelectedOptionForeground | Spectre.Console.Color | - | Foreground color for the focused option. | | UnselectedIndicator | System.Char | - | Character used to indicate non-focused options. | | Value | {TItem} | - | Currently committed option value. | | ValueChanged | Microsoft.AspNetCore.Components.EventCallback{{TItem}} | - | Event raised when the committed value changes. | ### Usage Example (Select_1.razor): ````razor @using Spectre.Console @using RazorConsole.Components
Name Value
```` --- # Component: TextInput Single-line text input field. ### Parameters: | Name | Type | Default | Description | | --------------------- | ------------------------------------------------------------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------- | | AdditionalAttributes | System.Collections.Generic.IReadOnlyDictionary{System.String,System.Object} | - | Additional HTML attributes to apply to the input element. | | BorderColor | Spectre.Console.Color | - | Border color when input is not focused and not disabled. | | BorderPadding | Spectre.Console.Padding | - | Padding between the border and the content. | | BorderStyle | Spectre.Console.BoxBorder | - | Style of the input border. | | ContentPadding | Spectre.Console.Padding | - | Padding around the input content. | | Disabled | System.Boolean | - | Whether the input is disabled. When disabled, cannot receive focus or accept input. | | DisabledBorderColor | Spectre.Console.Color | - | Border color when input is disabled. | | Expand | System.Boolean | - | Whether the input should expand to fill available horizontal space. | | FocusOrder | System.Nullable{System.Int32} | - | Tab order for keyboard navigation. Lower values receive focus first. If `null`, natural document order is used. | | FocusedBorderColor | Spectre.Console.Color | - | Border color when input has focus. | | Label | System.String | - | Label text displayed above the input field. If null or empty, no label is shown. | | LabelColor | Spectre.Console.Color | - | Color of the label text. | | LabelDecoration | Spectre.Console.Decoration | - | Decoration style of the label text. | | MaskInput | System.Boolean | - | Whether input characters should be masked (displayed as bullets). Useful for password fields. Default is `false`. | | OnBlur | Microsoft.AspNetCore.Components.EventCallback{Microsoft.AspNetCore.Components.Web.FocusEventArgs} | - | Event callback invoked when input loses focus. | | OnFocus | Microsoft.AspNetCore.Components.EventCallback{Microsoft.AspNetCore.Components.Web.FocusEventArgs} | - | Event callback invoked when input receives focus. | | OnInput | Microsoft.AspNetCore.Components.EventCallback{System.String} | - | Event callback invoked on each character input (fired for every keystroke). | | OnSubmit | Microsoft.AspNetCore.Components.EventCallback{System.String} | - | Event callback invoked when submitting input (typically by pressing Enter). | | Placeholder | string? | - | Placeholder text shown when input is empty. | | PlaceholderColor | Spectre.Console.Color | - | Color of the placeholder text. | | PlaceholderDecoration | Spectre.Console.Decoration | - | Decoration style of the placeholder text. | | Value | string | - | Current value of the text input. Supports two-way binding with @bind-Value. | | ValueChanged | EventCallback | - | Event callback invoked when the value changes. | | ValueColor | Spectre.Console.Color | - | Color of the input value text. | | ValueExpression | System.Linq.Expressions.Expression{System.Func{System.String}} | - | Expression identifying the bound value for validation scenarios with EditContext. | ### Usage Example (TextInput_1.razor): ````razor @using Spectre.Console @using RazorConsole.Components @code { private static readonly Padding _inputPadding = new(1, 0, 1, 0); private string _firstName = string.Empty; private string _secretNote = string.Empty; private string PreviewText => _firstName.Length == 0 ? "Preview: (none)" : $"Preview: {_firstName}"; private string SecretLengthText => $"Stored secret length: {_secretNote.Length}"; private Task OnFirstNameChangedAsync(string? value) { _firstName = value ?? string.Empty; StateHasChanged(); return Task.CompletedTask; } private Task OnSecretChangedAsync(string? value) { _secretNote = value ?? string.Empty; StateHasChanged(); return Task.CompletedTask; } } ```` --- # Component: TextButton Interactive button component. ### Parameters: | Name | Type | Default | Description | | --------------- | --------------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------- | | BackgroundColor | Spectre.Console.Color | - | Background color when not focused. Default is Default. | | Content | System.String | - | Text content displayed on the button. | | FocusOrder | System.Nullable{System.Int32} | - | Tab order for keyboard navigation. Lower values receive focus first. If `null`, natural document order is used. | | FocusedColor | Spectre.Console.Color | - | Background color when focused. Default is DeepSkyBlue1. | | OnClick | Microsoft.AspNetCore.Components.EventCallback | - | Event callback invoked when the button is clicked. | ### Usage Example (TextButton_1.razor): ````razor @using Spectre.Console @using RazorConsole.Components

Count: @count

@code { private int count = 0; private void HandleClick() { count++; StateHasChanged(); } } ```` --- # Component: FlexBox Lays out children using a CSS-like flexbox model with configurable direction, justification, alignment, wrapping, and gap. ### Parameters: | Name | Type | Default | Description | | ------------ | ---------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------- | | Align | FlexAlign | - | How items are aligned along the cross axis. Default is Start. | | ChildContent | Microsoft.AspNetCore.Components.RenderFragment | - | The child content to lay out within the flex container. | | Direction | FlexDirection | - | Lays out child content using a CSS-like flexbox model with configurable direction, justification, alignment, wrapping, and gap. | | Gap | int | - | Spacing between items along the main axis in characters (Row) or lines (Column). Default is 0. | | Height | int? | - | Explicit height constraint in lines. When null, uses the natural content height. | | Justify | FlexJustify | - | How free space is distributed along the main axis. Default is Start. | | Width | int? | - | Explicit width constraint in characters. When null, uses all available width. | | Wrap | FlexWrap | - | Whether items wrap to new lines when they exceed the available space. Default is NoWrap. | ### Usage Example (FlexBox_1.razor): ````razor @using Spectre.Console @using RazorConsole.Components @using RazorConsole.Core.Renderables @* ── Name fields with SpaceBetween ── *@ @* ── Email field full width ── *@ @* ── Password field full width ── *@ @* ── Role selector with description ── *@