<script setup lang="ts">
import { Label, TimeFieldInput, TimeFieldRoot } from 'akar';
import './styles.css';
</script>
<template>
<div class="akar-demo akar-demo-TimeField">
<div class="TimeFieldWrapper">
<Label
class="TimeFieldLabel"
for="time-field"
>Appointment</Label>
<TimeFieldRoot
id="time-field"
v-slot="{ segments }"
granularity="second"
class="TimeField"
>
<template
v-for="item in segments"
:key="item.part"
>
<TimeFieldInput
v-if="item.part === 'literal'"
:part="item.part"
class="TimeFieldLiteral"
>
{{ item.value }}
</TimeFieldInput>
<TimeFieldInput
v-else
:part="item.part"
class="TimeFieldSegment"
>
{{ item.value }}
</TimeFieldInput>
</template>
</TimeFieldRoot>
</div>
</div>
</template>@import '../_colors/black-alpha.css';
@import '../_colors/mauve.css';
@import '../_colors/grass.css';
@scope (.akar-demo-TimeField) {
.TimeFieldWrapper {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.TimeFieldLabel {
font-size: 0.875rem;
line-height: 1.25rem;
color: var(--gray-9);
}
.TimeField {
display: flex;
padding: 0.5rem;
align-items: center;
border-radius: 0.25rem;
border-width: 1px;
text-align: center;
background-color: #ffffff;
user-select: none;
color: var(--green-10);
border: 1px solid var(--gray-9);
}
.TimeField::placeholder {
color: var(--mauve-5);
}
.TimeField[data-invalid] {
border: 1px solid var(--red-500);
}
.TimeFieldLiteral {
padding: 0.25rem;
}
.TimeFieldSegment {
padding: 0.25rem;
}
.TimeFieldSegment:hover {
background-color: var(--grass-4);
}
.TimeFieldSegment:focus {
background-color: var(--grass-2);
}
.TimeFieldSegment[aria-valuetext='Empty'] {
color: var(--grass-6);
}
}Features
- Full keyboard navigation
- Can be controlled or uncontrolled
- Focus is fully managed
- Localization support
- Highly composable
- Accessible by default
Preface
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.
Installation
Install the date package.
pnpm add @internationalized/date
yarn add @internationalized/date
npm install @internationalized/date
bun add @internationalized/date
Install the component from your command line.
pnpm add akar
yarn add akar
npm install akar
bun add akar
Anatomy
Import all parts and piece them together.
<script setup>
import {
TimeFieldInput,
TimeFieldRoot,
} from 'akar';
</script>
<template>
<TimeFieldRoot>
<TimeFieldInput />
</TimeFieldRoot>
</template>
API Reference
Root
Contains all the parts of a time field
| Prop | Default | Type |
|---|---|---|
as | "div" | AsTag | 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 | TimeValueThe default placeholder date | |
defaultValue | TimeValueThe default value for the calendar | |
dir | "ltr" | "rtl"The reading direction of the time field when applicable. If omitted, inherits globally from | |
disabled | false | booleanWhether or not the time field is disabled |
granularity | "hour" | "minute" | "second"The granularity to use for formatting times. Defaults to minute if a Time 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 | |
locale | stringThe locale to use for formatting dates | |
maxValue | TimeValueThe maximum date that can be selected | |
minValue | TimeValueThe minimum date that can be selected | |
modelValue | TimeValue | nullThe controlled checked state of the field. Can be bound as | |
name | stringThe name of the field. Submitted with its owning form as part of a name/value pair. | |
placeholder | TimeValueThe placeholder date, which is used to determine what time to display when no time is selected. This updates as the user navigates the field | |
readonly | false | booleanWhether or not the time field is readonly |
required | booleanWhen | |
step | DateStepThe stepping interval for the time fields. Defaults to | |
stepSnapping | false | booleanWhether to enforce snapping the value to the nearest step increment after input. Defaults to |
| Event | Payload |
|---|---|
update:modelValue | date: TimeValueEvent handler called whenever the model value changes |
update:placeholder | date: TimeValueEvent handler called whenever the placeholder value changes |
| Slot (default) | Payload |
|---|---|
modelValue | TimeValueThe current time of the field |
segments | { part: SegmentPart; value: string; }[]The time field segment contents |
isInvalid | booleanValue if the input is invalid |
| Method | Type |
|---|---|
setFocusedElement | (el: HTMLElement) => voidHelper to set the focused element inside the DateField |
| Data attribute | Value |
|---|---|
[data-readonly] | Present when readonly |
[data-disabled] | Present when disabled |
[data-invalid] | Present when invalid |
Input
Contains the time field segments
| Prop | Default | Type |
|---|---|---|
as | "div" | AsTag | 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 |
| Data attribute | Value |
|---|---|
[data-disabled] | Present when disabled |
[data-invalid] | Present when invalid |
[data-placeholder] | Present when no value is set |
Accessibility
Keyboard Interactions
| Key | Description |
|---|---|
| Tab | When focus moves onto the time field, focuses the first segment. |
| ArrowLeft/ArrowRight | Navigates between the time field segments. |
| ArrowUp/ArrowDown | Increments/changes the value of the segment. |
| 0-9 | When the focus is on a numeric TimeFieldInput, it types in the number and focuses the next segment if the next input would result in an invalid value. |
| Backspace | Deletes a digit from the focused numeric segments. |
| A/P | When the focus is on the day period, it sets it to AM or PM. |