Datefield
Component

DateField

A segmented date/time input component with explicit format strings and full keyboard navigation.

Demo

Selected: 2026-01-08

Selected: 2026-01-08 09:21

Selected: 01/08/2026 09:21 AM

Features

  • Segmented editing (each part is independently editable)
  • Explicit format strings - no CultureInfo dependency, no extra WASM downloads
  • Support for both DateOnly and DateTime types
  • 12-hour and 24-hour time formats via TimeFormat parameter
  • Localized segment labels and AM/PM from browser's Intl API
  • Min/max validation and EditForm integration
  • WCAG compliant with proper ARIA attributes

Installation

bash
dotnet add package SummitUI

Anatomy

Import the components and structure them as follows:

razor
<DateFieldRoot @bind-Value="date" Format="yyyy-MM-dd" class="group">
    <DateFieldLabel>Select a date</DateFieldLabel>
    <DateFieldInput class="..." />
</DateFieldRoot>

Sub-components

DateFieldRoot

Root container managing date field state.

DateFieldLabel

Accessible label for the date field.

DateFieldInput

Container that renders date/time segments.

DateFieldSegment

Individual editable segment (auto-generated).

API Reference

DateFieldRoot

Property Type Default Description
Formatrequired string - Date format pattern (e.g., "yyyy-MM-dd", "MM/dd/yyyy")
TimeFormat string "HH:mm" Time format pattern. Use "hh:mm" for 12-hour, "HH:mm" for 24-hour
Value DateOnly? null Bound DateOnly value (date only, no time)
ValueChanged EventCallback<DateOnly?> - DateOnly value change callback
DateTimeValue DateTime? null Bound DateTime value (shows time segments)
DateTimeValueChanged EventCallback<DateTime?> - DateTime value change callback
Placeholder DateOnly Today Placeholder date shown when Value is null
DateTimePlaceholder DateTime Now Placeholder datetime shown when DateTimeValue is null
MinValue DateOnly? null Minimum allowed DateOnly value
MaxValue DateOnly? null Maximum allowed DateOnly value
MinDateTime DateTime? null Minimum allowed DateTime value
MaxDateTime DateTime? null Maximum allowed DateTime value
Disabled bool false Disables the entire date field
ReadOnly bool false Makes the field read-only
Invalid bool false Indicates validation error state
Name string? null Form field name for submission
Required bool false Marks the field as required

Format Strings

Date Format Examples

Format Region Example Output
yyyy-MM-dd ISO / Sweden 2025-01-15
MM/dd/yyyy United States 01/15/2025
dd/MM/yyyy United Kingdom 15/01/2025
dd.MM.yyyy Germany 15.01.2025

Time Format Examples

TimeFormat Clock Type Example Output
HH:mm 24-hour (default) 14:30
hh:mm 12-hour with AM/PM 02:30 PM
HH.mm 24-hour with dot separator 14.30

Use lowercase h for 12-hour format (shows AM/PM), uppercase H for 24-hour format.

Examples

Basic DateOnly Field

razor
@code {
    private DateOnly? selectedDate = DateOnly.FromDateTime(DateTime.Today);
}

<DateFieldRoot @bind-Value="selectedDate" Format="yyyy-MM-dd" class="group">
    <DateFieldLabel>Select a date</DateFieldLabel>
    <DateFieldInput class="..." />
</DateFieldRoot>

<p>Selected: @(selectedDate?.ToString("yyyy-MM-dd") ?? "None")</p>

DateTime with Time

Bind to DateTimeValue to show time segments.

razor
@code {
    private DateTime? selectedDateTime = DateTime.Now;
}

<DateFieldRoot @bind-DateTimeValue="selectedDateTime" 
               Format="yyyy-MM-dd"
               class="group">
    <DateFieldLabel>Select date and time</DateFieldLabel>
    <DateFieldInput class="..." />
</DateFieldRoot>

<p>Selected: @(selectedDateTime?.ToString("yyyy-MM-dd HH:mm") ?? "None")</p>

12-Hour Time Format

Use lowercase 'h' in TimeFormat for 12-hour clock with AM/PM.

razor
@code {
    private DateTime? dateTime = DateTime.Now;
}

<DateFieldRoot @bind-DateTimeValue="dateTime" 
               Format="MM/dd/yyyy"
               TimeFormat="hh:mm"
               class="group">
    <DateFieldLabel>Select date and time</DateFieldLabel>
    <DateFieldInput class="..." />
</DateFieldRoot>

<p>Selected: @(dateTime?.ToString("MM/dd/yyyy hh:mm tt") ?? "None")</p>

Min/Max Validation

Constrain the date range.

razor
@code {
    private DateOnly? date = DateOnly.FromDateTime(DateTime.Today);
    private DateOnly minDate = new DateOnly(2025, 1, 1);
    private DateOnly maxDate = new DateOnly(2025, 12, 31);
}

<DateFieldRoot @bind-Value="date" 
               Format="yyyy-MM-dd"
               MinValue="@minDate" 
               MaxValue="@maxDate"
               class="group">
    <DateFieldLabel>Select a date (Jan - Dec 2025)</DateFieldLabel>
    <DateFieldInput class="..." />
</DateFieldRoot>

EditForm Integration

Use with Blazor forms and validation.

razor
<EditForm EditContext="editContext" OnSubmit="HandleSubmit">
    <DataAnnotationsValidator />
    
    <DateFieldRoot @bind-Value="model.BirthDate"
                   Format="yyyy-MM-dd"
                   Name="birthDate"
                   Required="true"
                   Invalid="@(submitted && model.BirthDate == null)"
                   class="group">
        <DateFieldLabel>Birth Date (Required)</DateFieldLabel>
        <DateFieldInput class="..." />
    </DateFieldRoot>
    <ValidationMessage For="@(() => model.BirthDate)" />

    <button type="submit">Submit</button>
</EditForm>

Styling

Data Attributes

Attribute Values Description
data-disabled Present when disabled Date field is disabled
data-readonly Present when read-only Date field is read-only
data-invalid Present when invalid Validation error state
data-placeholder Present when no value Showing placeholder
data-segment Segment type Identifies segment type for styling

Tailwind Example

html
<!-- DateFieldInput with Tailwind classes -->
<DateFieldInput class="inline-flex items-center px-3 py-2 bg-su-background 
    border border-su-border rounded-lg text-sm mt-2 transition-all min-w-[200px] 
    focus-within:border-su-primary focus-within:ring-2 focus-within:ring-su-primary/20 
    group-data-[disabled]:opacity-50 group-data-[disabled]:cursor-not-allowed 
    group-data-[invalid]:border-su-destructive 
    [&_[data-segment]:not([data-segment='literal'])]:px-1.5 
    [&_[data-segment]:not([data-segment='literal'])]:py-0.5 
    [&_[data-segment]:not([data-segment='literal'])]:rounded-md 
    [&_[data-segment]:not([data-segment='literal'])]:min-w-[1.5em] 
    [&_[data-segment]:not([data-segment='literal'])]:text-center 
    [&_[data-segment]:not([data-segment='literal'])]:focus:bg-su-primary/10 
    [&_[data-segment]:not([data-segment='literal'])]:focus:text-su-primary 
    [&_[data-segment='literal']]:text-su-muted-foreground 
    [&_[data-segment][data-placeholder]]:text-su-muted-foreground/60" />

Accessibility

Keyboard Navigation

Key Action
ArrowUp Increment the focused segment value
ArrowDown Decrement the focused segment value
ArrowLeft Move focus to previous segment
ArrowRight Move focus to next segment
Tab Move focus to next segment (or next element)
0-9 Type numeric value directly into segment
Backspace / Delete Clear the value (sets to null)
A / P Toggle AM/PM on DayPeriod segment

ARIA Attributes

  • Root: Has role="group" with aria-labelledby pointing to label
  • Segments: Each has role="spinbutton" with aria-valuemin, aria-valuemax, aria-valuenow
  • Labels: Segment labels (Year, Month, etc.) are localized from the browser's Intl.DisplayNames API
  • Literals: Separator segments have aria-hidden="true"
An unhandled error has occurred. Reload X