<script setup lang="ts">
import { ADateRangeFieldInput, ADateRangeFieldRoot, ALabel } from 'akar';
</script>
<template>
<div class="flex flex-col gap-2">
<ALabel
class="text-sm"
for="birthday"
>
Booking
</ALabel>
<ADateRangeFieldRoot
id="booking"
v-slot="{ segments }"
:is-date-unavailable="date => date.day === 19"
class="group text-sm color-text-highlighted px-2.5 py-1.5 rounded-md bg-background inline-flex gap-0.5 select-none ring ring-ring-accented ring-inset transition-colors items-center relative focus-visible:(ring-2 ring-primary ring-inset)"
>
<template
v-for="item in segments.start"
:key="item.part"
>
<ADateRangeFieldInput
type="start"
:part="item.part"
class="text-center outline-hidden rounded transition-colors-280 data-[placeholder]:color-text-dimmed data-[segment=literal]:color-text-muted focus:bg-background-elevated"
:class="{
'w-11': item.part === 'year',
'w-7': item.part === 'month' || item.part === 'day',
}"
>
{{ item.value }}
</ADateRangeFieldInput>
</template>
<span class="mx-2">
-
</span>
<template
v-for="item in segments.end"
:key="item.part"
>
<ADateRangeFieldInput
type="end"
:part="item.part"
class="text-center outline-hidden rounded transition-colors-280 data-[placeholder]:color-text-dimmed data-[segment=literal]:color-text-muted focus:bg-background-elevated"
:class="{
'w-11': item.part === 'year',
'w-7': item.part === 'month' || item.part === 'day',
}"
>
{{ item.value }}
</ADateRangeFieldInput>
</template>
</ADateRangeFieldRoot>
</div>
</template>
The component depends on the @internationalized/date package, which solves a lot of the problems that come with working with dates and times in JavaScript.
We highly recommend reading through the documentation for the package to get a solid feel for how it works, and you'll need to install it in your project to use the date-related components.
Install the date package.
pnpm add @internationalized/date
npm install @internationalized/date
bun add @internationalized/date
Import all parts and piece them together.
<script setup>
import {
ADateRangeFieldInput,
ADateRangeFieldRoot,
} from 'akar';
</script>
<template>
<ADateRangeFieldRoot>
<ADateRangeFieldInput />
</ADateRangeFieldRoot>
</template>
One benefit of using Akar is its flexibility and low-level control over the components. However, this also means that you may need to manually construct more complex UI elements by combining multiple Akar components together.
If you feel there's a lot of elements that needs to be constructed manually using Akar, consider using Pohon UI instead. It provides a higher-level abstraction over Akar components with pre-defined styles and behaviors that can help you build UIs faster.
Contains all the parts of a date field
| Prop | Default | Type |
|---|---|---|
as | 'div' | APrimitiveAsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. | |
defaultPlaceholder | DateValueThe default placeholder date | |
defaultValue | DateRangeThe default value for the calendar | |
dir | 'ltr' | 'rtl'The reading direction of the date field when applicable. | |
disabled | false | booleanWhether or not the date field is disabled |
granularity | 'day' | 'hour' | 'minute' | 'second'The granularity to use for formatting times. Defaults to day if a CalendarDate is provided, otherwise defaults to minute. The field will render segments for each part of the date up to and including the specified granularity | |
hideTimeZone | booleanWhether or not to hide the time zone segment of the field | |
hourCycle | 12 | 24The hour cycle used for formatting times. Defaults to the local preference | |
id | stringId of the element | |
isDateUnavailable | DateMatcherA function that returns whether or not a date is unavailable | |
locale | stringThe locale to use for formatting dates | |
maxValue | DateValueThe maximum date that can be selected | |
minValue | DateValueThe minimum date that can be selected | |
modelValue | DateRange | nullThe controlled checked state of the calendar. Can be bound as | |
name | stringThe name of the field. Submitted with its owning form as part of a name/value pair. | |
placeholder | DateValueThe placeholder date, which is used to determine what month to display when no date is selected. This updates as the user navigates the calendar and can be used to programmatically control the calendar view | |
readonly | false | booleanWhether or not the date field is readonly |
required | booleanWhen | |
step | DateStepThe stepping interval for the time fields. Defaults to |
| Event | Type |
|---|---|
update:modelValue | [DateRange]Event handler called whenever the model value changes |
update:placeholder | [date: DateValue]Event handler called whenever the placeholder value changes |
| Slot | Type |
|---|---|
modelValue | DateRange | null |
segments | { start: { part: SegmentPart; value: string; }[]; end: { part: SegmentPart; value: string; }[]; } |
Contains the date field segments
| Prop | Default | Type |
|---|---|---|
as | 'div' | APrimitiveAsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. | |
part* | 'day' | 'month' | 'year' | 'hour' | 'minute' | 'second' | 'dayPeriod' | 'literal' | 'timeZoneName'The part of the date to render | |
type* | 'start' | 'end'The type of field to render (start or end) |
| Attribute | Value |
|---|---|
[data-disabled] | Present when disabled |
[data-invalid] | Present when invalid |
[data-placeholder] | Present when no value is set |
| Key | Description |
|---|---|
Tab | When focus moves onto the date field, focuses the first segment. |
ArrowLeftArrowRight | Navigates between the date field segments. |
ArrowUpArrowDown | Increments/changes the value of the segment. |
0-9 | When the focus is on a numeric |
Backspace | Deletes a digit from the focused numeric segments. |
AP | When the focus is on the day period, it sets it to AM or PM. |