Inline date selection
Keep a date grid visible when choosing a date is the main task.
Components / Forms
An inline keyboard-accessible single-date or date-range calendar.
npx @getweini/cli@latest add calendarKeep a date grid visible when choosing a date is the main task.
Let users choose start and end dates directly in a page without opening a popover.
<script setup lang="ts">
import { ref } from 'vue'
import Calendar from './components/ui/calendar/Calendar.vue'
const date = ref('2026-10-12')
const messages = { previousMonth: 'Previous month', nextMonth: 'Next month' }
</script>
<template><Calendar v-model="date" :messages="messages" /></template>Locale changes labels; firstDayOfWeek separately controls the week grid.
<script setup lang="ts">
import { ref } from 'vue'
import Calendar from './components/ui/calendar/Calendar.vue'
const usDate = ref('2026-10-12')
const frenchDate = ref('2026-10-12')
const english = { previousMonth: 'Previous month', nextMonth: 'Next month' }
const french = { previousMonth: 'Mois précédent', nextMonth: 'Mois suivant' }
</script>
<template>
<section aria-label="US event date">
<Calendar v-model="usDate" locale="en-US" :first-day-of-week="0" :messages="english" />
</section>
<section aria-label="Date de l’événement">
<Calendar v-model="frenchDate" locale="fr-FR" :first-day-of-week="1" :messages="french" />
</section>
</template>The second tuple entry stays empty until the end date is chosen.
<script setup lang="ts">
import { ref } from 'vue'
import Calendar from './components/ui/calendar/Calendar.vue'
const range = ref<[string, string]>(['', ''])
const messages = { previousMonth: 'Previous month', nextMonth: 'Next month' }
</script>
<template>
<section aria-label="Available dates">
<Calendar v-model="range" mode="range" min="2026-10-01" max="2026-12-31" locale="en-GB" :first-day-of-week="1" :messages="messages" />
</section>
<p v-if="range[0]">Start: {{ range[0] }}; end: {{ range[1] || 'choose an end date' }}</p>
</template>Keep the chosen local date and IANA zone separate; an existing instant can be displayed in that zone with Intl.
<script setup lang="ts">
import { computed, ref } from 'vue'
import Calendar from './components/ui/calendar/Calendar.vue'
const localDate = ref('2026-10-12')
const timeZone = ref('Europe/Luxembourg')
const existingInstant = ref('2026-10-12T13:00:00Z')
const messages = { previousMonth: 'Previous month', nextMonth: 'Next month' }
const existingLocalTime = computed(() => new Intl.DateTimeFormat('en-GB', {
dateStyle: 'medium', timeStyle: 'short', timeZone: timeZone.value,
}).format(new Date(existingInstant.value)))
const schedulingInput = computed(() => ({ localDate: localDate.value, timeZone: timeZone.value }))
</script>
<template>
<section aria-label="Meeting date">
<Calendar v-model="localDate" locale="en-GB" :first-day-of-week="1" :messages="messages" />
</section>
<p>Chosen date: {{ schedulingInput.localDate }} in {{ schedulingInput.timeZone }}</p>
<p>Existing appointment in that zone: {{ existingLocalTime }}</p>
</template> These calendars share one selected YYYY-MM-DD date. Locale changes the displayed month and day names; firstDayOfWeek changes the grid. The underlying date value remains the same. Calendar renders Gregorian dates; setting a locale does not switch calendar systems.
Selected date: 2026-10-12
An event at 2026-10-12T23:30:00Z lands on different local dates. Calendar does not convert instants; choose and store an IANA time zone in your application when scheduling events.
The most useful props, models, slots, events, and methods for this component.
| Name | Type | Default or requirement |
|---|---|---|
v-model | string | [string, string] | undefined |
mode | single | range | single |
min / max | YYYY-MM-DD | undefined |
locale | string | en-US |
firstDayOfWeek | 0–6 | 1 |
messages | CalendarMessages | required |
Arrow keys move by day or week; Home/End jump to week edges and Page Up/Down change months. Range mode emits an empty end until the second date is selected.