Appearance
Date picker
Lets people type a date, or choose one from a calendar.
vue
<script setup lang="ts">
import { FsDatePicker, FsField } from '@fivespark/ui'
import { ref } from 'vue'
const levering = ref('')
</script>
<template>
<div class="min-h-[28rem] w-full max-w-xs">
<FsField label="Leverdatum">
<FsDatePicker v-model="levering" name="levering" />
</FsField>
</div>
</template>Usage
vue
<script setup lang="ts">
import { FsDatePicker, FsField } from '@fivespark/ui'
import { ref } from 'vue'
const levering = ref('')
</script>
<template>
<FsField label="Leverdatum">
<FsDatePicker v-model="levering" name="levering" />
</FsField>
</template>v-model is the date as YYYY-MM-DD, or an empty string. People type it the way they write it, such as 28-10-2026, and name submits the ISO date with a form. A date picker takes one date: no range, no time.
Examples
Earliest and latest date
min and max are YYYY-MM-DD. Earlier or later dates stop the calendar and are refused when typed.
vue
<script setup lang="ts">
import { FsDatePicker, FsField } from '@fivespark/ui'
import { ref } from 'vue'
const afspraak = ref('')
const today = new Date().toLocaleDateString('sv')
const inThreeMonths = new Date(Date.now() + 90 * 864e5).toLocaleDateString('sv')
</script>
<template>
<div class="min-h-[28rem] w-full max-w-xs">
<FsField label="Afspraak" description="Binnen drie maanden">
<FsDatePicker v-model="afspraak" :min="today" :max="inThreeMonths" name="afspraak" />
</FsField>
</div>
</template>Unavailable dates
unavailable gets each date as YYYY-MM-DD and returns true for one that cannot be taken. Keep it cheap, and say in the field's description why.
vue
<script setup lang="ts">
import { FsDatePicker, FsField } from '@fivespark/ui'
import { ref } from 'vue'
const levering = ref('')
const weekend = (date: string) => [0, 6].includes(new Date(`${date}T12:00`).getDay())
</script>
<template>
<div class="min-h-[28rem] w-full max-w-xs">
<FsField label="Leverdatum" description="Alleen op werkdagen">
<FsDatePicker v-model="levering" :unavailable="weekend" name="levering-werkdag" />
</FsField>
</div>
</template>Invalid
vue
<script setup lang="ts">
import { FsDatePicker, FsField } from '@fivespark/ui'
import { ref } from 'vue'
const levering = ref('')
</script>
<template>
<div class="min-h-[28rem] w-full max-w-xs">
<FsField label="Leverdatum" required error="Kies een leverdatum.">
<FsDatePicker v-model="levering" name="levering-fout" />
</FsField>
</div>
</template>Disabled
vue
<script setup lang="ts">
import { FsDatePicker, FsField } from '@fivespark/ui'
import { ref } from 'vue'
const levering = ref('2026-11-20')
</script>
<template>
<FsField label="Leverdatum" description="Alleen een planner kan de leverdatum wijzigen." disabled class="w-full max-w-xs">
<FsDatePicker v-model="levering" name="levering-vast" />
</FsField>
</template>Read-only
readonly on the field shows the date without letting it change.
vue
<script setup lang="ts">
import { FsDatePicker, FsField } from '@fivespark/ui'
import { ref } from 'vue'
const levering = ref('2026-11-20')
</script>
<template>
<FsField label="Leverdatum" readonly class="w-full max-w-xs">
<FsDatePicker v-model="levering" name="levering-vast" />
</FsField>
</template>Keyboard
In the calendar:
| Key | Does |
|---|---|
| →, ← | Moves to the next or previous day |
| ↓, ↑ | Moves to the same weekday next or last week |
| Home, End | Moves to Monday or Sunday of the week |
| Page Down, Page Up | Moves to the same day next or last month |
| Shift + Page Down, Shift + Page Up | Moves to the same day next or last year |
| Enter, Space | Chooses the day, unless it is unavailable |
| Esc | Closes the calendar |
API Reference
FsDatePicker
| Prop | Type | Default | Description |
|---|---|---|---|
min | string | The first date it takes, `YYYY-MM-DD`; before it the field says so, and the calendar stops. | |
max | string | The last date it takes, `YYYY-MM-DD`; after it the field says so, and the calendar stops. | |
unavailable | ((date: string) => boolean) | True for a date it does not take, given as `YYYY-MM-DD`: struck through in the calendar, an error when typed. Called for each day shown, so it must be quick, and must not throw. | |
name | string | Submits the date with a form, as `YYYY-MM-DD`, whatever the language. | |
size | "default" | "dense" | `default` is 36px high; `dense` is 32px, for tables and toolbars. The calendar is the same. In a field, the field's. | |
id | string | Only outside a field; in one, it takes the field's. | |
invalid | boolean | Marks the date as wrong; the field says why. In a field, the field's. Text it cannot take is invalid regardless, once left. | |
disabled | boolean | Unavailable until something else is done: not focusable, not submitted. A date to see but not change is `readonly`. In a field, the field's. | |
readonly | boolean | A date to see and copy, not change: no calendar. In a field, the field's. | |
required | boolean | In a field, the field's, which also shows the asterisk. | |
errorTexts | { unreadable?: ((example: string) => string) | undefined; impossible?: (() => string) | undefined; tooEarly?: ((min: string) => string) | undefined; tooLate?: ((max: string) => string) | undefined; between?: ((min: string, max: string) => string) | undefined; unavailable?: (() => string) | undefined; } | Replaces its error messages, each a function of the dates as the field writes them: an example, the limits. | |
calendarTexts | { choose?: string | undefined; previousMonth?: string | undefined; nextMonth?: string | undefined; week?: string | undefined; weekShort?: string | undefined; } | Replaces the calendar's words: the button's and the calendar's name, the month buttons' names, and the week column's header in full and short. | |
modelValue | string | "" | The date, `YYYY-MM-DD`; `''` when empty, or when the text cannot be taken. Without `v-model` it keeps its own. |
| Event | Payload | Description |
|---|---|---|
update:modelValue | [value: string] | Sent with the new `modelValue`, for `v-model`. |