Usage
Use the v-model directive to control the selected date.
<script setup lang="ts">
import { CalendarDate } from '@internationalized/date'
const value = shallowRef(new CalendarDate(2022, 2, 3))
</script>
<template>
<PInputDate v-model="value" />
</template>
Use the default-value prop to set the initial value when you do not need to control its state.
<script setup lang="ts">
import { CalendarDate } from '@internationalized/date'
const defaultValue = shallowRef(new CalendarDate(2022, 2, 6))
</script>
<template>
<PInputDate :default-value="defaultValue" />
</template>
Range
Use the range prop to select a range of dates.
<script setup lang="ts">
import { CalendarDate } from '@internationalized/date'
const value = shallowRef({
start: new CalendarDate(2022, 2, 3),
end: new CalendarDate(2022, 2, 20)
})
</script>
<template>
<PInputDate range v-model="value" />
</template>
Color
Use the color prop to change the color of the InputDate.
<template>
<PInputDate color="neutral" highlight />
</template>
Variant
Use the variant prop to change the variant of the InputDate.
<template>
<PInputDate variant="subtle" />
</template>
Size
Use the size prop to change the size of the InputDate.
<template>
<PInputDate size="xl" />
</template>
Separator Icon
Use the separator-icon prop to change the icon of the range separator.
<template>
<PInputDate range separator-icon="i-lucide-arrow-right" />
</template>
Disabled
Use the disabled prop to disable the InputDate.
<template>
<PInputDate disabled />
</template>
Examples
With unavailable dates
Use the is-date-unavailable prop with a function to mark specific dates as unavailable.
<script setup lang="ts">
import type { DateValue } from '@internationalized/date';
import { CalendarDate } from '@internationalized/date';
import { shallowRef } from 'vue';
const modelValue = shallowRef({
start: new CalendarDate(2022, 1, 1),
end: new CalendarDate(2022, 1, 9),
});
function isDateUnavailable(date: DateValue) {
return date.day >= 10 && date.day <= 16;
}
</script>
<template>
<PInputDate
v-model="modelValue"
:is-date-unavailable="isDateUnavailable"
range
/>
</template>
With min/max dates
Use the min-value and max-value props to limit the dates.
<script setup lang="ts">
import { CalendarDate } from '@internationalized/date';
import { shallowRef } from 'vue';
const modelValue = shallowRef(new CalendarDate(2023, 9, 10));
const minDate = new CalendarDate(2023, 9, 1);
const maxDate = new CalendarDate(2023, 9, 30);
</script>
<template>
<PInputDate
v-model="modelValue"
:min-value="minDate"
:max-value="maxDate"
/>
</template>
As a DatePicker
Use a Calendar and a Popover component to create a date picker.
<script setup lang="ts">
import { CalendarDate } from '@internationalized/date';
import { shallowRef, useTemplateRef } from 'vue';
const inputDateRef = useTemplateRef('inputDateRef');
const modelValue = shallowRef(new CalendarDate(2022, 1, 10));
</script>
<template>
<PInputDate
ref="inputDateRef"
v-model="modelValue"
>
<template #trailing>
<PPopover :reference="inputDateRef?.inputsRef[3]?.$el">
<PButton
color="neutral"
variant="link"
size="sm"
icon="i-lucide-calendar"
aria-label="Select a date"
class="akar:px-0"
/>
<template #content>
<PCalendar
v-model="modelValue"
class="p-2"
/>
</template>
</PPopover>
</template>
</PInputDate>
</template>
As a DateRangePicker
Use a Calendar and a Popover component to create a date range picker.
<script setup lang="ts">
import { CalendarDate } from '@internationalized/date';
import { shallowRef, useTemplateRef } from 'vue';
const inputDateRef = useTemplateRef('inputDateRef');
const modelValue = shallowRef({
start: new CalendarDate(2022, 1, 10),
end: new CalendarDate(2022, 1, 20),
});
</script>
<template>
<PInputDate
ref="inputDateRef"
v-model="modelValue"
range
>
<template #trailing>
<PPopover :reference="inputDateRef?.inputsRef[0]?.$el">
<PButton
color="neutral"
variant="link"
size="sm"
icon="i-lucide-calendar"
aria-label="Select a date range"
class="px-0"
/>
<template #content>
<PCalendar
v-model="modelValue"
class="p-2"
:number-of-months="2"
range
/>
</template>
</PPopover>
</template>
</PInputDate>
</template>
API
Props
| Prop | Default | Type |
|---|---|---|
as | 'div' | anyThe element or component this component should render as. |
color | 'primary' | "primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral" |
variant | 'solid' | "outline" | "soft" | "subtle" | "ghost" | "none" |
size | 'md' | "md" | "xs" | "sm" | "lg" | "xl" |
highlight | boolean Highlight the ring color like a focus state. | |
autofocus | boolean | |
autofocusDelay | 0 | number |
separatorIcon | appConfig.pohon.icons.minus | string | objectThe icon to use as a range separator. |
range | RWhether or not a range of dates can be selecteu | |
defaultValue | CalendarDate | CalendarDateTime | ZonedDateTime | DateRange | |
modelValue | null | CalendarDate | CalendarDateTime | ZonedDateTime | DateRange | |
icon | string | objectDisplay an icon based on the | |
avatar | PAvatarPropsDisplay an avatar on the left side.
| |
leading | boolean When | |
leadingIcon | string | objectDisplay an icon on the left side. | |
trailing | boolean When | |
trailingIcon | string | objectDisplay an icon on the right side. | |
loading | boolean When | |
loadingIcon | appConfig.pohon.icons.loading | string | objectThe icon when the |
defaultPlaceholder | CalendarDate | CalendarDateTime | ZonedDateTime | |
placeholder | CalendarDate | CalendarDateTime | ZonedDateTime | |
hourCycle | 12 | 24The hour cycle used for formatting times. Defaults to the local preference | |
step | DateStepThe stepping interval for the time fields. Defaults to
| |
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 | boolean Whether or not to hide the time zone segment of the field | |
maxValue | CalendarDate | CalendarDateTime | ZonedDateTime | |
minValue | CalendarDate | CalendarDateTime | ZonedDateTime | |
disabled | boolean Whether or not the date field is disabled | |
readonly | boolean Whether or not the date field is readonly | |
isDateUnavailable | (date: DateValue): booleanA function that returns whether or not a date is unavailable | |
id | stringId of the element | |
name | stringThe name of the field. Submitted with its owning form as part of a name/value pair. | |
required | boolean When | |
pohon | { root?: ClassValue; base?: ClassValue; leading?: ClassValue; leadingIcon?: ClassValue; leadingAvatar?: ClassValue; leadingAvatarSize?: ClassValue; trailing?: ClassValue; trailingIcon?: ClassValue; segment?: ClassValue; separatorIcon?: ClassValue; } |
Slots
| Slot | Type |
|---|---|
leading | { pohon: object; } |
default | { pohon: object; } |
trailing | { pohon: object; } |
separator | { pohon: object; } |
Emits
| Event | Type |
|---|---|
update:modelValue | [date: InputDateModelValue<R>] |
update:placeholder | [date: DateValue] & [date: DateValue] |
change | [event: Event] |
blur | [event: FocusEvent] |
focus | [event: FocusEvent] |
Theme
Below is the theme configuration skeleton for the PInputDate. Since the component is provided unstyled by default, you will need to fill in these values to apply your own custom look and feel. If you prefer to use our pre-built, opinionated styling, you can instead use our UnoCSS preset, this docs is using it as well.
export default defineAppConfig({
pohon: {
inputDate: {
slots: {
root: '',
base: '',
leading: '',
leadingIcon: '',
leadingAvatar: '',
leadingAvatarSize: '',
trailing: '',
trailingIcon: '',
segment: '',
separatorIcon: ''
},
variants: {
fieldGroup: {
horizontal: '',
vertical: ''
},
size: {
xs: {
base: '',
leading: '',
trailing: '',
leadingIcon: '',
leadingAvatarSize: '',
trailingIcon: '',
segment: ''
},
sm: {
base: '',
leading: '',
trailing: '',
leadingIcon: '',
leadingAvatarSize: '',
trailingIcon: '',
segment: ''
},
md: {
base: '',
leading: '',
trailing: '',
leadingIcon: '',
leadingAvatarSize: '',
trailingIcon: '',
segment: ''
},
lg: {
base: '',
leading: '',
trailing: '',
leadingIcon: '',
leadingAvatarSize: '',
trailingIcon: '',
segment: ''
},
xl: {
base: '',
leading: '',
trailing: '',
leadingIcon: '',
leadingAvatarSize: '',
trailingIcon: '',
segment: ''
}
},
variant: {
outline: '',
soft: '',
subtle: '',
ghost: '',
none: ''
},
color: {
primary: '',
secondary: '',
success: '',
info: '',
warning: '',
error: '',
neutral: ''
},
leading: {
true: ''
},
trailing: {
true: ''
},
loading: {
true: ''
},
highlight: {
true: ''
},
type: {
file: ''
}
},
compoundVariants: [],
defaultVariants: {
size: 'md',
color: 'primary',
variant: 'outline'
}
}
}
};
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import pohon from 'pohon-ui/vite'
export default defineAppConfig({
pohon: {
inputDate: {
slots: {
root: '',
base: '',
leading: '',
leadingIcon: '',
leadingAvatar: '',
leadingAvatarSize: '',
trailing: '',
trailingIcon: '',
segment: '',
separatorIcon: ''
},
variants: {
fieldGroup: {
horizontal: '',
vertical: ''
},
size: {
xs: {
base: '',
leading: '',
trailing: '',
leadingIcon: '',
leadingAvatarSize: '',
trailingIcon: '',
segment: ''
},
sm: {
base: '',
leading: '',
trailing: '',
leadingIcon: '',
leadingAvatarSize: '',
trailingIcon: '',
segment: ''
},
md: {
base: '',
leading: '',
trailing: '',
leadingIcon: '',
leadingAvatarSize: '',
trailingIcon: '',
segment: ''
},
lg: {
base: '',
leading: '',
trailing: '',
leadingIcon: '',
leadingAvatarSize: '',
trailingIcon: '',
segment: ''
},
xl: {
base: '',
leading: '',
trailing: '',
leadingIcon: '',
leadingAvatarSize: '',
trailingIcon: '',
segment: ''
}
},
variant: {
outline: '',
soft: '',
subtle: '',
ghost: '',
none: ''
},
color: {
primary: '',
secondary: '',
success: '',
info: '',
warning: '',
error: '',
neutral: ''
},
leading: {
true: ''
},
trailing: {
true: ''
},
loading: {
true: ''
},
highlight: {
true: ''
},
type: {
file: ''
}
},
compoundVariants: [],
defaultVariants: {
size: 'md',
color: 'primary',
variant: 'outline'
}
}
}
};
Akar
With Pohon UI, you can achieve similar component functionality with less code and effort, as it comes with built-in styles mechanism and behaviors that are optimized for common use cases. Since it's using unocss-variants it adds a runtime cost, but it can be worth it if you prioritize development speed and ease of use over fine-grained control.
If this is a deal breaker for you, you can always stick to using Akar and build your own custom components on top of it.