Input
A production-ready input with beautiful defaults, configurable sizes, and safe Tailwind overrides. Supports two-way binding and full attribute passthrough.
Overview
MInput is styled by default. Write <MInput Placeholder="Merchant name..." />
and it renders with borders, focus rings, placeholder styling, and disabled states already handled.
Use Size to control scale and Class for safe overrides.
Usage
@using Marai.UI.Components.MInputBasic Usage
@using Marai.UI.Components.MInput
<div class="max-w-sm">
<MInput Placeholder="Merchant name..." />
</div>
Sizes
Use Size to control input height, padding, and font size. Defaults to Size.Default.
@using Marai.UI.Components.MInput
<div class="flex flex-col gap-3 max-w-sm">
<MInput Size="Size.Sm" Placeholder="Small input" />
<MInput Size="Size.Default" Placeholder="Default input" />
<MInput Size="Size.Lg" Placeholder="Large input" />
</div>
Input Types
Use the Type parameter to specify the HTML input type.
<div class="flex flex-col gap-3 max-w-sm">
<div>
<label for="text-input" class="text-sm font-medium mb-1 block">Text</label>
<MInput id="text-input" Type="text"
Class="flex h-10 w-full rounded-md border border-border bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
Placeholder="Enter text..." />
</div>
<div>
<label for="email-input" class="text-sm font-medium mb-1 block">Email</label>
<MInput id="email-input" Type="email"
Class="flex h-10 w-full rounded-md border border-border bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
Placeholder="you@example.com" />
</div>
<div>
<label for="password-input" class="text-sm font-medium mb-1 block">Password</label>
<MInput id="password-input" Type="password"
Class="flex h-10 w-full rounded-md border border-border bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
Placeholder="••••••••" />
</div>
<div>
<label for="number-input" class="text-sm font-medium mb-1 block">Number</label>
<MInput id="number-input" Type="number"
Class="flex h-10 w-full rounded-md border border-border bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
Placeholder="123" />
</div>
<div>
<label for="search-input" class="text-sm font-medium mb-1 block">Search</label>
<MInput id="search-input" Type="search"
Class="flex h-10 w-full rounded-md border border-border bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
Placeholder="Search..." />
</div>
<div>
<label for="url-input" class="text-sm font-medium mb-1 block">URL</label>
<MInput id="url-input" Type="url"
Class="flex h-10 w-full rounded-md border border-border bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
Placeholder="https://example.com" />
</div>
</div>
Placeholder
<div class="flex flex-col gap-3 max-w-sm">
<MInput Class="flex h-10 w-full rounded-md border border-border bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
Placeholder="Email address" />
<MInput Class="flex h-10 w-full rounded-md border border-border bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
Placeholder="Search..." />
<MInput Class="flex h-10 w-full rounded-md border border-border bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
Placeholder="Full name" />
</div>
Two-Way Binding
Bind a string value using @bind-Value for two-way data binding:
<MInput Value="hello@example.com"
Class="flex h-10 max-w-sm rounded-md border border-border bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring" />
With Labels
<div class="flex flex-col gap-1.5 max-w-sm">
<label for="email-demo" class="text-sm font-medium">Email</label>
<MInput id="email-demo" Type="email"
Class="flex h-10 w-full rounded-md border border-border bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
Placeholder="you@example.com" />
</div>
Disabled State
Set Disabled="true" to prevent interaction. Default styling includes
disabled:cursor-not-allowed disabled:opacity-50.
@using Marai.UI.Components.MInput
<div class="flex flex-col gap-3 max-w-sm">
<MInput Value="ACC-00123" Disabled="true" />
<MInput Placeholder="Cannot modify" Disabled="true" />
</div>
Validation States
Use the Variant parameter to communicate semantic validation feedback.
Variant.Destructive applies a red border and focus ring; Variant.Success applies green.
No JavaScript or extra CSS is required.
<MInput Placeholder="Username" />
<MInput Variant="Variant.Destructive" Placeholder="Email already taken" />
<MInput Variant="Variant.Success" Placeholder="Username available" />Safe Tailwind Overrides
The Class parameter is always last — user-supplied classes win all conflicts.
@using Marai.UI.Components.MInput
<div class="flex flex-col gap-3 max-w-sm">
<MInput Class="font-mono" Placeholder="Transaction ID (monospace)" />
<MInput Class="text-center" Placeholder="Centered text" />
<MInput Class="rounded-full" Placeholder="Pill shape" />
</div>
Standard HTML Attributes
<MInput aria-label="Search query"
data-testid="search-input"
autocomplete="off"
Placeholder="Search..."
Class="flex h-10 max-w-sm rounded-md border border-border bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring" />
Common Examples
Email Input
@using Marai.UI.Components.MInput
<div class="flex flex-col gap-1.5 max-w-sm">
<label for="email-field" class="text-sm font-medium">Business Email</label>
<MInput id="email-field" Type="email" Placeholder="contact@merchant.com" />
</div>
Password Input
<div class="flex flex-col gap-1.5 max-w-sm">
<label for="password-field" class="text-sm font-medium">Password</label>
<MInput id="password-field" Type="password"
Class="flex h-10 w-full rounded-md border border-border bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
Placeholder="Enter your password" />
</div>
Password Input with Visibility Toggle
Set AllowPasswordToggle="true" on any Type="password" input to show a toggle button
that reveals or hides the value. The button is accessible, keyboard-focusable, and respects the
Disabled state. Use ShowPasswordIcon and HidePasswordIcon to
supply custom CSS icon classes instead of the built-in SVGs.
<div class="flex flex-col gap-1.5 max-w-sm">
<label for="password-toggle-field" class="text-sm font-medium">Password</label>
<MInput id="password-toggle-field"
Type="password"
AllowPasswordToggle="true"
Placeholder="Enter your password" />
</div>
Search Input
<MInput Type="search"
Class="flex h-10 max-w-sm rounded-md border border-border bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
Placeholder="Search..." />
Accessibility
- Focus-visible ring is built in — keyboard navigation is visible by default
- Always associate inputs with labels using
idandforattributes - Use appropriate
typefor semantic HTML and better mobile keyboards - Add
aria-labelfor inputs without visible labels - Use
aria-describedbyto link inputs with help text or error messages - The password toggle button carries a live
aria-label("Show password" / "Hide password") and anaria-hiddenicon — screen readers announce the action correctly - The toggle button is removed from tab order (
tabindex="-1") so keyboard users navigate through it with the mouse or pointer; the input itself remains the primary focus target
API Reference
| Parameter | Type | Default | Description |
|---|---|---|---|
| Size | Size | Size.Default |
Height, padding, and font-size preset (Sm, Default, Lg). |
| Variant | Variant | Variant.Default |
Semantic validation state. Destructive applies a red border and focus ring; Success applies green. Use Default for normal state. |
| Value | string? | null |
The current value. Use with @bind-Value for two-way binding. |
| ValueChanged | EventCallback<string?> | — | Callback invoked each time the input value changes. Wired automatically by @bind-Value. |
| ValueExpression | Expression<Func<string?>>? | null |
Expression for <ValidationMessage>. Set automatically by @bind-Value. |
| Type | string | "text" |
HTML type attribute. |
| Placeholder | string? | null |
Hint text displayed when the input is empty. |
| Disabled | bool | false |
Sets the native disabled attribute. |
| Class | string? | null |
Additional Tailwind classes. User-supplied classes win all conflicts. |
| AdditionalAttributes | Dictionary<string, object>? | null |
Arbitrary HTML attributes forwarded to the <input> element. |
| AllowPasswordToggle | bool | false |
Renders a show/hide toggle button inside the input. Only active when Type="password". |
| ShowPasswordIcon | string? | null |
CSS class(es) for a custom "show password" icon. Falls back to the built-in SVG eye icon when omitted. |
| HidePasswordIcon | string? | null |
CSS class(es) for a custom "hide password" icon. Falls back to the built-in SVG eye-off icon when omitted. |