TextEntry
A Material Design-inspired text entry control with an animated floating placeholder, customizable border styling, left/right tool slots, hint text for validation errors, and character count display.
Features
Section titled “Features”- Animated Floating Placeholder — Slides up and scales down when the field is focused or contains text. Returns to center when empty and unfocused.
- Customizable Border — Configure border color, focused color, thickness, focused thickness, corner radius, and background color.
- Tool Slots — Left and right tool areas for icons, text, or interactive buttons. Tools can be simple labels or self-contained components like
ClearButtonTool. - Hint Text — Helper text below the field for instructions or validation errors. Automatically switches to error styling when
HasErroris true. - Character Count — Optional counter display showing current length vs. max length.
- Input Masking — Declarative
Maskproperty for formatted input (phone, credit card, date, SSN, ZIP). Raw digits inText, formatted display inFormattedText. - Input Modes — Password masking, read-only, keyboard type selection, return type configuration.
- Reusable Tools — Built-in
ClearButtonTool(auto-shows/hides based on text content) andTextEntrySpeechToTextTool(voice input via Shiny.Speech, in the SpeechAddins package).
AI Skill
Section titled “AI Skill”Step 1 — Add the marketplace:
claude plugin marketplace add shinyorg/skills Step 2 — Install plugins:
claude plugin install shiny-client@shiny claude plugin install shiny-maui@shiny claude plugin install shiny-controls@shiny claude plugin install shiny-mediator@shiny claude plugin install shiny-data@shiny claude plugin install shiny-aspire@shiny claude plugin install shiny-extensions@shiny Step 1 — Add the marketplace:
copilot plugin marketplace add https://github.com/shinyorg/skills Step 2 — Install plugins:
copilot plugin install shiny-client@shiny copilot plugin install shiny-maui@shiny copilot plugin install shiny-controls@shiny copilot plugin install shiny-mediator@shiny copilot plugin install shiny-data@shiny copilot plugin install shiny-aspire@shiny copilot plugin install shiny-extensions@shiny Basic Usage
Section titled “Basic Usage”.NET MAUI
Section titled “.NET MAUI”<shiny:TextEntry Placeholder="Email" Text="{Binding Email, Mode=TwoWay}" Keyboard="Email" HasError="{Binding HasEmailError}" HintText="{Binding EmailError}"> <shiny:ClearButtonTool /></shiny:TextEntry>Blazor
Section titled “Blazor”<TextEntry Placeholder="Email" @bind-Text="email" HasError="@hasError" HintText="@errorMessage"> <RightTools> <TextEntryClearButton Text="@email" TextChanged="v => email = v" /> </RightTools></TextEntry>Properties
Section titled “Properties”| Property | Type | Default | Description |
|---|---|---|---|
Text | string | "" | Current text value (TwoWay) |
Placeholder | string | "" | Animated floating placeholder text |
PlaceholderColor | Color/string | Grey / #9CA3AF | Placeholder color when unfocused |
FocusedPlaceholderColor | Color/string | #007AFF | Placeholder color when focused or floating |
BorderColor | Color/string | #CCCCCC | Border color when unfocused |
FocusedBorderColor | Color/string | #007AFF | Border color when focused |
BorderThickness | double | 1 | Border thickness (unfocused) |
FocusedBorderThickness | double | 2 | Border thickness (focused) |
CornerRadius | CornerRadius/string | 8 / 8px | Border corner radius |
EntryBackgroundColor | Color/string | Transparent | Background inside the border |
FontSize | double | 15 | Text and placeholder font size |
FontFamily | string? | null / inherit | Font family |
FontAttributes | FontAttributes | None | Bold/Italic (MAUI only) |
TextColor | Color/string | Black / inherit | Input text color |
IsReadOnly | bool | false | Read-only mode |
IsPassword | bool | false | Password masking |
ReturnType | ReturnType | Default | Keyboard return button (MAUI only) |
Keyboard | Keyboard | Default | Keyboard type (MAUI only) |
MaxLength | int | unlimited | Maximum character count |
Mask | string? | null | Input mask pattern (# = digit slot, others are auto-inserted literals) |
FormattedText | string | "" | Read-only formatted display value when Mask is set |
HintText | string? | null | Hint/helper text below the field |
HintColor | Color/string | Grey / #9CA3AF | Hint text color |
HasError | bool | false | Error state (changes border/hint to ErrorColor) |
ErrorColor | Color/string | #DC3545 | Error state color |
ShowCharacterCount | bool | false | Show character count below the field |
LeftTools | IList / RenderFragment | empty | Left tool slot |
RightTools | IList / RenderFragment | empty | Right tool slot (ContentProperty on MAUI) |
TextChangedCommand | ICommand? | null | Text change command (MAUI only) |
CompletedCommand | ICommand? | null | Return key command (MAUI only) |
Tool Slots
Section titled “Tool Slots”TextEntry supports left and right tool areas on both MAUI and Blazor. Tools are TextEntryTool subclass instances — on MAUI they’re declared in XAML, on Blazor they’re passed as List<TextEntryTool>.
Built-in Tools
Section titled “Built-in Tools”ClearButtonTool — Automatically appears when text is non-empty and clears the field on tap/click. Available on both MAUI and Blazor.
<!-- MAUI --><shiny:TextEntry Placeholder="Search" Text="{Binding Query, Mode=TwoWay}"> <shiny:ClearButtonTool /></shiny:TextEntry><!-- Blazor --><TextEntry Placeholder="Search" @bind-Text="query" RightTools="tools" />
@code { string query = ""; List<TextEntryTool> tools = [new ClearButtonTool()];}TextEntrySpeechToTextTool (MAUI, requires Shiny.Maui.Controls.SpeechAddins) — Voice input tool that listens for speech via ISpeechToTextService and fills the entry text. Toggles listening state with visual feedback.
SpeechToTextTool (Blazor, requires Shiny.Blazor.Controls.SpeechAddins) — Voice input tool using the Web Speech API via JS interop.
Custom Tools
Section titled “Custom Tools”<!-- MAUI --><shiny:TextEntry Placeholder="Amount"> <shiny:TextEntry.LeftTools> <shiny:TextEntryTool Text="$" ToolColor="#059669" /> </shiny:TextEntry.LeftTools> <shiny:ClearButtonTool /></shiny:TextEntry><!-- Blazor --><TextEntry Placeholder="Amount" LeftTools="leftTools" RightTools="rightTools" />
@code { List<TextEntryTool> leftTools = [new TextEntryTool { Text = "$", ToolColor = "#059669" }]; List<TextEntryTool> rightTools = [new ClearButtonTool()];}TextEntryTool Properties
Section titled “TextEntryTool Properties”MAUI:
| Property | Type | Description |
|---|---|---|
Icon | ImageSource? | Tool icon |
Text | string? | Tool text label |
ToolColor | Color | Text/icon color |
Command | ICommand? | Tap command |
CommandParameter | object? | Command parameter |
Blazor:
| Property | Type | Description |
|---|---|---|
Icon | string? | Icon text/emoji |
Text | string? | Tool text label |
ToolColor | string | CSS color |
IsVisible | bool | Whether the tool is shown (default: true) |
Clicked | Action? | Click callback |
CssClass | string? | Additional CSS class |
Creating Custom Tools
Section titled “Creating Custom Tools”MAUI — Implement ITextEntryAwareTool on a TextEntryTool subclass:
public interface ITextEntryAwareTool{ void Attach(TextEntry entry); void Detach();}Blazor — Override lifecycle methods on TextEntryTool:
public class MyTool : TextEntryTool{ public override void OnTextChanged(string? text) { /* react to text changes */ } protected override void OnClick() { SetEntryText("new value"); }}Input Masking
Section titled “Input Masking”Set Mask to automatically format input as the user types. The # character represents a digit slot; all other characters are literal separators inserted automatically.
When Mask is set:
Textalways contains raw digits only (e.g.,"5551234567")FormattedTextcontains the display value (e.g.,"(555) 123-4567")Keyboardauto-sets toNumeric- Cursor position is managed automatically
- Paste is handled gracefully (non-digits stripped, then reformatted)
.NET MAUI
Section titled “.NET MAUI”<shiny:TextEntry Placeholder="Phone Number" Mask="(###) ###-####" Text="{Binding Phone, Mode=TwoWay}" />
<shiny:TextEntry Placeholder="Credit Card" Mask="#### #### #### ####" Text="{Binding CardNumber, Mode=TwoWay}" />
<shiny:TextEntry Placeholder="MM/DD/YYYY" Mask="##/##/####" Text="{Binding DateString, Mode=TwoWay}" />Blazor
Section titled “Blazor”<TextEntry Placeholder="Phone Number" Mask="(###) ###-####" @bind-Text="phone" />
@code { string phone = ""; // Always raw digits, e.g. "5551234567"}Validation Example
Section titled “Validation Example”<shiny:TextEntry Placeholder="Email" Text="{Binding Email, Mode=TwoWay}" Keyboard="Email" HasError="{Binding HasEmailError}" HintText="{Binding EmailError}" ErrorColor="#DC3545"> <shiny:ClearButtonTool /></shiny:TextEntry>When HasError is true:
- The border changes to
ErrorColor - The floating placeholder changes to
ErrorColor - The hint text displays in
ErrorColor
Custom Styling Example
Section titled “Custom Styling Example”<shiny:TextEntry Placeholder="Purple theme" FocusedBorderColor="#7C3AED" FocusedPlaceholderColor="#7C3AED" FocusedBorderThickness="2" CornerRadius="16" EntryBackgroundColor="#F5F3FF"> <shiny:ClearButtonTool /></shiny:TextEntry>