M
Marai.UI
v1.0.0-alpha.7

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

razor
@using Marai.UI.Components.MInput

Basic Usage

Preview
razor
@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.

Preview
razor
@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.

Preview
razor
<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

Preview
razor
<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:

Preview
razor
<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

Preview
razor
<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.

Preview
razor
@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.

razor
<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.

Preview
razor
@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

Preview
razor
<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

Preview
razor
@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

Preview
razor
<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.

Preview
razor
<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

Preview
razor
<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 id and for attributes
  • Use appropriate type for semantic HTML and better mobile keyboards
  • Add aria-label for inputs without visible labels
  • Use aria-describedby to link inputs with help text or error messages
  • The password toggle button carries a live aria-label ("Show password" / "Hide password") and an aria-hidden icon — 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.