Date Range Field

Allows users to input a range of dates within a designated field.

llms.txt
Hotel dates
	<script lang="ts">
  import { DateRangeField } from "bits-ui";
</script>
 
<DateRangeField.Root class="group flex w-full max-w-[320px] flex-col gap-1.5">
  <DateRangeField.Label class="block select-none text-sm font-medium">
    Hotel dates
  </DateRangeField.Label>
  <div
    class="h-input rounded-input border-border-input bg-background text-foreground focus-within:border-border-input-hover focus-within:shadow-date-field-focus hover:border-border-input-hover group-data-invalid:border-destructive flex w-full select-none items-center border px-2 py-3 text-sm tracking-[0.01em]"
  >
    {#each ["start", "end"] as const as type (type)}
      <DateRangeField.Input {type}>
        {#snippet children({ segments })}
          {#each segments as { part, value }, i (part + i)}
            <div class="inline-block select-none">
              {#if part === "literal"}
                <DateRangeField.Segment
                  {part}
                  class="text-muted-foreground p-1"
                >
                  {value}
                </DateRangeField.Segment>
              {:else}
                <DateRangeField.Segment
                  {part}
                  class="rounded-5px hover:bg-muted focus:bg-muted focus:text-foreground aria-[valuetext=Empty]:text-muted-foreground focus-visible:ring-0! focus-visible:ring-offset-0! px-1 py-1"
                >
                  {value}
                </DateRangeField.Segment>
              {/if}
            </div>
          {/each}
        {/snippet}
      </DateRangeField.Input>
      {#if type === "start"}
        <div aria-hidden="true" class="text-muted-foreground px-1">–⁠⁠⁠⁠⁠</div>
      {/if}
    {/each}
  </div>
</DateRangeField.Root>

Overview

The DateRangeField component combines two Date Field components to create a date range field. Check out the Date Field component documentation for information on how to customize this component.

Structure

	<script lang="ts">
  import { DateRangeField } from "$lib";
</script>
 
<DateRangeField.Root>
  <DateRangeField.Label>Check-in date</DateRangeField.Label>
  {#each ["start", "end"] as const as type}
    <DateRangeField.Input {type}>
      {#snippet children({ segments })}
        {#each segments as { part, value }}
          <DateRangeField.Segment {part}>
            {value}
          </DateRangeField.Segment>
        {/each}
      {/snippet}
    </DateRangeField.Input>
  {/each}
</DateRangeField.Root>

Managing Placeholder State

This section covers how to manage the placeholder state of the component.

Two-Way Binding

Use bind:placeholder for simple, automatic state synchronization:

	<script lang="ts">
  import { DateRangeField } from "bits-ui";
  import { CalendarDateTime } from "@internationalized/date";
  let myPlaceholder = $state(new CalendarDateTime(2024, 8, 3, 12, 30));
</script>
 
<DateRangeField.Root bind:placeholder={myPlaceholder}>
  <!-- ... -->
</DateRangeField.Root>

Fully Controlled

Use a Function Binding for complete control over the state's reads and writes.

	<script lang="ts">
  import { DateRangeField } from "bits-ui";
  import { CalendarDateTime } from "@internationalized/date";
  let myPlaceholder = $state(new CalendarDateTime(2024, 8, 3, 12, 30));
 
  function getPlaceholder() {
    return myPlaceholder;
  }
 
  function setPlaceholder(newPlaceholder: CalendarDateTime) {
    myPlaceholder = newPlaceholder;
  }
</script>
 
<DateRangeField.Root bind:placeholder={getPlaceholder, setPlaceholder}>
  <!-- ... -->
</DateRangeField.Root>

Managing Value State

This section covers how to manage the value state of the component.

Two-Way Binding

Use bind:value for simple, automatic state synchronization:

	<script lang="ts">
  import { DateRangeField, type DateRange } from "bits-ui";
  import { CalendarDateTime } from "@internationalized/date";
  let myValue = $state<DateRange>({
    start: new CalendarDateTime(2024, 8, 3, 12, 30),
    end: new CalendarDateTime(2024, 8, 4, 12, 30),
  });
</script>
 
<button
  onclick={() => {
    value = {
      start: value.start.add({ days: 1 }),
      end: value.end.add({ days: 1 }),
    };
  }}
>
  Add 1 day
</button>
<DateRangeField.Root bind:value={myValue}>
  <!-- ... -->
</DateRangeField.Root>

Fully Controlled

Use a Function Binding for complete control over the state's reads and writes.

	<script lang="ts">
  import { DateRangeField } from "bits-ui";
  let myValue = $state<DateRange>({
    start: undefined,
    end: undefined,
  });
 
  function getValue() {
    return myValue;
  }
 
  function setValue(newValue: DateRange) {
    myValue = newValue;
  }
</script>
 
<DateRangeField.Root bind:value={getValue, setValue}>
  <!-- ... -->
</DateRangeField.Root>

API Reference

DateRangeField.Root

The root date field component.

Property Details
value
onValueChange
placeholder
onPlaceholderChange
errorMessageId
validate
onInvalid
minValue
maxValue
granularity
hideTimeZone
hourCycle
locale
disabled
readonly
readonlySegments
required
onStartValueChange
onEndValueChange
ref
children
child
Data Attribute Details
data-date-range-field-root

DateRangeField.Input

The container for the segments of the date field.

Property Details
type
name
ref
children
child
Data Attribute Details
data-invalid
data-disabled
data-date-field-input

DateRangeField.Segment

A segment of the date field.

Property Details
part
ref
children
child
Data Attribute Details
data-invalid
data-disabled
data-segment
data-date-field-segment

DateRangeField.Label

The label for the date field.

Property Details
ref
children
child
Data Attribute Details
data-invalid
data-date-field-label