@gigerit/vuetify-date-input-advanced
v3.5.0
Published
Advanced Vuetify 4 date picker and input components with multi-month range selection.
Downloads
2,206
Readme
@gigerit/vuetify-date-input-advanced
Demo
Features
- Multi-month picker with range selection by default
- Single-date mode with
:range="false" - Inline picker or input-triggered overlay
- Desktop menu and mobile fullscreen dialog behavior in
VAdvancedDateInput - Vuetify-styled split start/end inputs in range mode
- Typed input parsing and validation
- Controlled
v-model:textsupport with draft-state events - Configurable overlay draft close strategies: revert, preserve, or commit
- Exposed input instance API for parent-driven validate / commit / revert flows
- Optional picker-only single-date mode with
inputReadonly - Built-in range presets plus custom preset slots
min,max,allowedDates,allowedStartDates, andallowedEndDatesconstraints- Configurable week start via
firstDayOfWeek - Optional week numbers
- Keyboard navigation and live announcements
- Theme-aware styling with CSS custom properties and optional Sass variables
Advanced date selection components for Vuetify 4.
@gigerit/vuetify-date-input-advanced provides two components:
VAdvancedDatePicker: a standalone multi-month calendar panelVAdvancedDateInput: a typed input wrapper that adds overlay behavior and the same picker surface
The components use Vuetify's active date adapter through useDate(), so locale, formatting, and runtime value types follow your app's Vuetify date configuration.
Exports
| Export | Description |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------- |
| AdvancedDatePlugin | Registers both components globally |
| VAdvancedDateInput | Text field wrapper + picker |
| VAdvancedDatePicker | Standalone picker panel |
| dateInputAdvancedEn, dateInputAdvancedCs, dateInputAdvancedDe, dateInputAdvancedFr, dateInputAdvancedIt, dateInputAdvancedLt | Built-in locale message bundles |
| AdvancedDateModel, PresetRange, AdvancedDateAdapter, AdvancedDateDay, AdvancedDateMonthData, AdvancedDateWeek, DateBounds, NormalizedRange, DateInputAdvancedLocaleMessages, AdvancedDateIconValue, AdvancedDateIconSvgPath, AdvancedDateInputField, AdvancedDateInputFieldProps | Core public TypeScript types |
| AdvancedDateInputDraft, AdvancedDateInputPublicInstance, AdvancedDateInputCommitPayload, AdvancedDateInputInvalidPayload, AdvancedDateInputClosePayload, AdvancedDateInputSource, AdvancedDateInputParseStatus, AdvancedDateInputAvailabilityStatus, AdvancedDateInputValidationStatus, AdvancedDateInputCloseStrategy | Text-input draft and public-handle contracts |
Requirements
vue@^3.5.0vuetify@^4.0.0- A Vuetify app already configured in your project, including any official Vuetify icon setup you want to use
Default component icons use Vuetify aliases ($calendar, $prev, and $next), so they resolve through the same icon configuration as native Vuetify components.
Install
npm install vue vuetify
npm install @gigerit/vuetify-date-input-advancedImport the stylesheet once in your app entry:
import '@gigerit/vuetify-date-input-advanced/style.css'Register the components globally:
import { createApp } from 'vue'
import App from './App.vue'
import vuetify from './plugins/vuetify'
import { AdvancedDatePlugin } from '@gigerit/vuetify-date-input-advanced'
import '@gigerit/vuetify-date-input-advanced/style.css'
createApp(App).use(vuetify).use(AdvancedDatePlugin).mount('#app')If you prefer local registration, import VAdvancedDateInput and VAdvancedDatePicker directly instead of using AdvancedDatePlugin.
Styling
For the default styling path, import the prebuilt stylesheet once:
import '@gigerit/vuetify-date-input-advanced/style.css'If you need compile-time customization, compile the package Sass entry instead
of importing style.css:
@use '@gigerit/vuetify-date-input-advanced/styles' with (
$advanced-date-picker-cell-size: 48px,
$advanced-date-picker-month-slide-duration: 0.36s,
$advanced-date-picker-month-slide-easing: cubic-bezier(0.4, 0, 0.2, 1),
$advanced-date-picker-preset-width: 260px,
$advanced-date-picker-day-font-weight: 600,
$advanced-date-picker-week-label-color: rgb(90, 90, 90)
);Desktop month navigation can be tuned with
$advanced-date-picker-month-slide-duration and
$advanced-date-picker-month-slide-easing.
Weekday headers and week numbers use $advanced-date-picker-week-label-color.
The package ships with a slightly larger default day geometry than stock
Vuetify (44px cells and 42px day buttons) while keeping the existing
typography defaults. If you customize Vuetify's day size, that value still
flows into the package defaults. Configure vuetify/settings before loading
the package styles in the same Sass graph:
@use 'vuetify/settings' with (
$date-picker-month-day-size: 48px,
$button-font-weight: 600
);
@use '@gigerit/vuetify-date-input-advanced/styles';Use either the prebuilt CSS import or the Sass entry. Importing both will load the component styles twice.
Quick Start
<script setup lang="ts">
import { ref } from 'vue'
import type { AdvancedDateModel } from '@gigerit/vuetify-date-input-advanced'
const today = new Date()
const inSevenDays = new Date(today)
inSevenDays.setDate(today.getDate() + 6)
const value = ref<AdvancedDateModel<Date>>([today, inSevenDays])
</script>
<template>
<v-advanced-date-input v-model="value" label="Travel dates" :months="2" />
</template>Single-date mode:
<script setup lang="ts">
import { ref } from 'vue'
import type { AdvancedDateModel } from '@gigerit/vuetify-date-input-advanced'
const value = ref<AdvancedDateModel<Date>>(new Date())
</script>
<template>
<v-advanced-date-input
v-model="value"
label="Departure"
:range="false"
:show-presets="false"
/>
</template>Standalone inline picker with controlled visible month:
<script setup lang="ts">
import { ref } from 'vue'
import type { AdvancedDateModel } from '@gigerit/vuetify-date-input-advanced'
const value = ref<AdvancedDateModel<Date>>(null)
const month = ref(0)
const year = ref(2026)
</script>
<template>
<v-advanced-date-picker
v-model="value"
v-model:month="month"
v-model:year="year"
:months="2"
:first-day-of-week="1"
:auto-apply="false"
variant="outlined"
/>
</template>In the current implementation and tests, month is zero-based, so 0 is January.
Use first-day-of-week in templates to match Vuetify's VDatePicker behavior, where 0 is Sunday, 1 is Monday, and so on.
Model Shapes
Examples below use native Date, but the actual runtime value type is the active Vuetify adapter type TDate.
| range | returnObject | Emitted shape |
| ------- | -------------- | -------------------------- |
| true | false | null or [start, end] |
| true | true | null or { start, end } |
| false | ignored | null or date |
Notes:
- In range mode, the component accepts either a tuple or
{ start, end }object as input. - With
autoApply=true, range selection can emit an incomplete value such as[start, null]after the first click. - If the user picks an earlier end date, the range is normalized into chronological order before emit.
Behavior
Presets
Presets are shown only in range mode. If you omit presets, the picker generates these built-in options:
TodayYesterdayLast 7 DaysLast 30 DaysThis MonthLast MonthThis QuarterLast QuarterYear to DateLast Year
Built-in rolling presets use completed days rather than including today:
Last 7 DaysandLast 30 Daysboth end on yesterday.Year to Datespans January 1 through yesterday and is omitted on January 1.This MonthandThis Quarterremain full calendar-period presets.
Custom preset shape:
type PresetRange<TDate> = {
label: string
value: [TDate, TDate] | (() => [TDate, TDate])
slot?: string
}If preset.slot is "highlight", the picker looks for a preset-highlight slot before falling back to preset.
Presets that violate the active date constraints are rendered disabled and do not emit presetSelect.
Example:
<script setup lang="ts">
import type { PresetRange } from '@gigerit/vuetify-date-input-advanced'
const presets: PresetRange<Date>[] = [
{
label: 'Weekend Escape',
slot: 'highlight',
value: () => {
const start = new Date('2026-01-16')
const end = new Date('2026-01-18')
return [start, end]
},
},
]
</script>
<template>
<v-advanced-date-input :presets="presets" :auto-apply="false">
<template #preset-highlight="{ preset }">
<div class="d-flex align-center justify-space-between w-100">
<span>{{ preset.label }}</span>
<v-chip size="x-small" color="primary" variant="tonal">Custom</v-chip>
</div>
</template>
</v-advanced-date-input>
</template>Typed Input
VAdvancedDateInput parses text on blur and on Enter. In single-date mode,
inputReadonly makes the text field a picker opener only.
On mobile non-inline layouts, built-in activator presses are intercepted before the text input can focus, and the activator becomes readonly while the fullscreen dialog is opening or open. This prevents the virtual keyboard from flashing during the transition.
Parsing order:
parseInput(value)if providedadapter.date(value)- ISO strings matching
YYYY-MM-DD... - native
Date.parse
Validation uses the same min, max, allowedDates, allowedStartDates, and allowedEndDates constraints as calendar clicks.
Input formatting uses displayFormat, which is passed directly to adapter.format(...). The default is fullDate.
Range text uses rangeSeparator, which defaults to –. The current implementation also accepts common spaced dash separators such as - and —.
Range Input Fields
In range mode, the default activator renders two Vuetify text fields: one for
the start date and one for the end date. Shared Vuetify field props such as
label, variant, color, hideDetails, messages, rules, clearable, and
validation state apply to the grouped control. Side-specific input details use
startFieldProps and endFieldProps.
text, update:text, and draft.text remain a single combined string using
rangeSeparator. Users can still paste a complete range into either side. When
a side becomes active, its full native input text is selected so typing replaces
the current value immediately.
<script setup lang="ts">
import { ref } from 'vue'
import type {
AdvancedDateInputFieldProps,
AdvancedDateModel,
} from '@gigerit/vuetify-date-input-advanced'
const value = ref<AdvancedDateModel<Date>>(null)
const startFieldProps = {
placeholder: 'Start date',
name: 'bookingStartDate',
ariaLabel: 'Booking start date',
} satisfies AdvancedDateInputFieldProps
const endFieldProps = {
placeholder: 'End date',
name: 'bookingEndDate',
ariaLabel: 'Booking end date',
} satisfies AdvancedDateInputFieldProps
</script>
<template>
<v-advanced-date-input
v-model="value"
label="Booking dates"
:start-field-props="startFieldProps"
:end-field-props="endFieldProps"
/>
</template>Controlled Text and Draft Lifecycle
Bind v-model:text when the parent needs to own the visible field text instead of treating it as a formatted mirror of modelValue.
update:textemits whenever the component wants to change the displayed textupdate:draftemits the currentAdvancedDateInputDraft<TDate>snapshot, including parse, availability, and validation stateinputCommitemits after a successful text or picker commitinputInvalidemits when commit or close validation failsdraftClosereports overlay close attempts with theirreason,strategy, andoutcome
When the text is controlled and differs from the formatted committed value, the input enters text-draft mode. In that mode the popup selection is kept in sync with the parsed text, including parser and availability changes from parseInput, rangeSeparator, min, max, allowedDates, allowedStartDates, and allowedEndDates.
closeDraftStrategy controls what happens when the overlay closes while a draft is still pending:
revert: discard the draft and return to the committed valuepreserve: close the overlay but keep the current draft text and draft selectioncommit: validate and commit the draft before closing; if validation fails, the close is blocked
Parent-managed submit flow:
<script setup lang="ts">
import { ref } from 'vue'
import type {
AdvancedDateInputDraft,
AdvancedDateInputPublicInstance,
AdvancedDateModel,
} from '@gigerit/vuetify-date-input-advanced'
const value = ref<AdvancedDateModel<Date>>(null)
const text = ref('')
const draft = ref<AdvancedDateInputDraft<Date> | null>(null)
const inputRef = ref<AdvancedDateInputPublicInstance<Date> | null>(null)
async function submitFromParent() {
const committed = await inputRef.value?.commitInput()
if (!committed) {
console.log(inputRef.value?.errorMessages)
}
}
</script>
<template>
<v-advanced-date-input
ref="inputRef"
v-model="value"
v-model:text="text"
:auto-apply="false"
close-draft-strategy="commit"
@update:draft="draft = $event"
/>
<v-btn @click="submitFromParent">Submit</v-btn>
</template>Input Attr Forwarding
When VAdvancedDateInput renders a single-date field, non-prop attrs and
listeners fall through to the internal VTextField. Use this for form-oriented
attrs such as id, name, aria-*, data-*, and hooks such as @blur or
@keydown.
<v-advanced-date-input
v-model="value"
:range="false"
id="booking-start-date"
name="bookingStartDate"
data-testid="booking-start-date"
@blur="validateField"
/>In range mode, non-prop attrs and listeners are applied to the connected range
field shell. Put native start/end input attrs in startFieldProps and
endFieldProps.
<v-advanced-date-input
v-model="value"
id="booking-dates"
data-testid="booking-dates"
:start-field-props="{ id: 'booking-start-date', name: 'bookingStartDate' }"
:end-field-props="{ id: 'booking-end-date', name: 'bookingEndDate' }"
/>If you provide the activator slot, the slot content owns its own attrs and listeners.
inputReadonly only affects the built-in single-date text field, so it has no
effect in range mode, when inline is enabled, or when you provide a custom
activator slot. Use readonly, startFieldProps.readonly, or
endFieldProps.readonly for range-mode readonly fields. The mobile fullscreen
keyboard-suppression behavior still applies to built-in range fields.
Overlay and Mobile Behavior
VAdvancedDateInput changes presentation by context:
- Desktop, non-inline: picker inside
VMenu - Mobile, non-inline: picker inside fullscreen
VDialog inline: picker rendered directly with no overlay
On mobile, the picker switches to a vertically scrollable, windowed month list instead of desktop-style prev/next nav buttons.
The built-in mobile fullscreen activator fields suppress control focus on press
and become readonly while the dialog is opening or open to avoid showing the
touchscreen keyboard. Custom activator slots own their own mobile focus and
keyboard behavior.
Apply / Cancel
autoApply controls calendar click behavior:
true: updatesmodelValueas the user selects datesfalse: keeps a draft selection in the picker and showsApply/Cancel
API
Shared Props
These props are accepted by both VAdvancedDateInput and VAdvancedDatePicker.
| Prop | Type | Default | Notes |
| ------------------- | -------------------------------------------------------------------- | ------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| modelValue | AdvancedDateModel<TDate> | null | Current value |
| range | boolean | true | Set false for single-date mode |
| returnObject | boolean | false | Range mode only; emits { start, end } instead of a tuple |
| months | number | 2 | Visible month count, clamped to at least 1 |
| month | number \| undefined | current month | Leading visible month |
| year | number \| undefined | current year | Leading visible year |
| presets | PresetRange<TDate>[] \| undefined | built-in range presets | Ignored when range=false |
| showPresets | boolean | true | Shows or hides the preset list in range mode |
| swipeable | boolean | true | Public prop; the current source does not attach swipe handlers |
| autoApply | boolean | true | false enables draft selection and footer actions |
| min | TDate \| null | null | Minimum selectable date |
| max | TDate \| null | null | Maximum selectable date |
| allowedDates | (date: TDate) => boolean | undefined | Shared per-day availability check applied to both endpoints |
| allowedStartDates | (date: TDate) => boolean | undefined | Additional availability check for single dates and ordered range starts |
| allowedEndDates | (date: TDate) => boolean | undefined | Additional availability check for ordered range ends |
| showWeekNumbers | boolean | false | Displays week numbers; uses adapter week calculations when available and otherwise falls back to ISO week numbers |
| firstDayOfWeek | string \| number \| undefined | adapter or locale default | Mirrors Vuetify VDatePicker; 0 starts weeks on Sunday, 1 on Monday, and so on |
| prevIcon | AdvancedDateIconValue | $prev | Previous-month navigation icon; accepts Vuetify aliases, prefixed set strings, SVG path arrays, or components |
| nextIcon | AdvancedDateIconValue | $next | Next-month navigation icon; accepts Vuetify aliases, prefixed set strings, SVG path arrays, or components |
| disabled | boolean | false | Applies disabled state to wrapper controls; day availability still comes primarily from date constraints |
| readonly | boolean | false | Full picker read-only mode: blocks calendar and preset interaction, and hides the manual action footer |
| theme | string \| undefined | inherited | Passed to the picker VCard |
| rounded | string \| number \| boolean \| undefined | undefined | Passed to the picker VCard |
| border | string \| number \| boolean | true | Passed to the picker VCard |
| elevation | string \| number | 2 | Passed to the picker VCard |
| variant | 'elevated' \| 'flat' \| 'tonal' \| 'outlined' \| 'text' \| 'plain' | elevated | Picker surface variant. When passed through VAdvancedDateInput, it affects the inline picker only |
| width | string \| number \| undefined | undefined | Picker width |
| minWidth | string \| number \| undefined | undefined | Picker min width; also used for the desktop menu wrapper |
| maxWidth | string \| number \| undefined | undefined | Picker max width |
| density | 'default' \| 'comfortable' \| 'compact' | default | Picker density and input density |
VAdvancedDateInput-Only Props
| Prop | Type | Default | Notes |
| -------------------- | ------------------------------------------ | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| menu | boolean | false | Controlled open state for the menu or dialog |
| inline | boolean | false | Renders the picker directly instead of using an overlay |
| label | string \| undefined | undefined | Shared field label for either the single-date field or range field group |
| placeholder | string \| undefined | undefined | Single-date input placeholder. In range mode, use startFieldProps.placeholder and endFieldProps.placeholder |
| variant | string \| undefined | mode-dependent | Outside inline mode, styles the built-in field(s). In inline mode, styles the picker VCard. Omit it to keep the default outlined field or elevated inline picker |
| hideDetails | boolean \| 'auto' | auto | Shared field details behavior |
| messages | string \| string[] \| undefined | undefined | Shared field messages |
| error | boolean | false | Combines with internal parse and validation errors |
| errorMessages | string \| string[] \| undefined | undefined | Merged with internal parse and validation errors |
| rules | readonly unknown[] | [] | Validates the single-date field or combined range text |
| clearable | boolean | false | Clears both text and model |
| color | string \| undefined | undefined | Applies the Vuetify field color to the built-in text control(s); supports utility names with or without text- and raw CSS colors |
| focused | boolean | false | Single-date VTextField focus state. In range mode, use activeField |
| activeField | 'start' \| 'end' \| undefined | undefined | Range-mode active side. When set on desktop, the side input is focused and its text selected, and programmatic picker opens use it as the default boundary |
| prependInnerIcon | AdvancedDateIconValue \| undefined | undefined | Single-date VTextField prepend icon. In range mode, use side-specific field props |
| appendInnerIcon | AdvancedDateIconValue | $calendar | Single-date VTextField append icon. In range mode, use side-specific field props |
| startFieldProps | AdvancedDateInputFieldProps \| undefined | undefined | Range-mode start input props |
| endFieldProps | AdvancedDateInputFieldProps \| undefined | undefined | Range-mode end input props |
| inputReadonly | boolean | false | Makes the single-date field readonly while keeping the picker, icon, and footer actions interactive |
| text | string \| undefined | undefined | Controlled combined text value for parent-owned draft flows |
| closeDraftStrategy | 'revert' \| 'preserve' \| 'commit' | revert | Controls how pending drafts behave when the overlay closes |
| displayFormat | string | fullDate | Passed to adapter.format(...) for text display |
| rangeSeparator | string | – | Separator used for formatted range text |
| parseInput | (value: string) => TDate \| null | undefined | Custom parser used before adapter and native parsing |
AdvancedDateInputFieldProps supports the side-specific range input details
that should not apply to the whole grouped field:
type AdvancedDateInputField = 'start' | 'end'
interface AdvancedDateInputFieldProps {
placeholder?: string
prependInnerIcon?: AdvancedDateIconValue
appendInnerIcon?: AdvancedDateIconValue
readonly?: boolean
id?: string
name?: string
ariaLabel?: string
class?: unknown
style?: StyleValue
attrs?: Record<string, string | number | boolean | null | undefined>
}Events
| Event | Component | Payload | Notes |
| -------------------- | --------- | ---------------------------------------- | ---------------------------------------------------------------------- |
| update:modelValue | both | AdvancedDateModel<TDate> | Main value update |
| update:menu | input | boolean | Overlay open state |
| update:text | input | string | Requested text change for controlled text mode |
| update:activeField | input | 'start' \| 'end' | Active range input side |
| update:draft | input | AdvancedDateInputDraft<TDate> | Current parsed draft snapshot |
| update:month | both | number | Leading visible month after user navigation |
| update:year | both | number | Leading visible year after user navigation |
| apply | both | AdvancedDateModel<TDate> | Fired when Apply is used with autoApply=false |
| cancel | both | none | Fired from picker cancel flows, including Escape inside the calendar |
| inputCommit | input | AdvancedDateInputCommitPayload<TDate> | Fired when a text or picker draft commits |
| inputInvalid | input | AdvancedDateInputInvalidPayload<TDate> | Fired when commit validation fails |
| draftClose | input | AdvancedDateInputClosePayload<TDate> | Fired after an overlay close attempt resolves or is blocked |
| presetSelect | both | PresetRange<TDate> | Fired when a preset is chosen |
Slots
All picker slots can be passed either directly to VAdvancedDatePicker or through VAdvancedDateInput, which forwards them to the internal picker.
| Slot | Component | Slot props |
| --------------- | --------- | --------------------------------------------------------------------------------------------- |
| activator | input | { props, isOpen } |
| day | both | { date, outside, disabled, today, selected, rangeStart, rangeEnd, inRange, preview, props } |
| preset | both | { preset, active, disabled, props } |
| preset-<name> | both | Same as preset, selected when preset.slot === '<name>' |
| actions | both | { apply, cancel, disabled } |
When overriding day, spread the provided props onto your interactive element to preserve keyboard and ARIA behavior.
Exposed Picker Methods
A ref on VAdvancedDatePicker exposes these methods:
| Method | Description |
| ------------------- | ----------------------------------------------- |
| focusDate(date) | Navigates if needed and focuses a specific date |
| focusActiveDate() | Focuses the active or first available date |
| prevMonth() | Moves to the previous visible month |
| nextMonth() | Moves to the next visible month |
Exposed Input Methods
A ref on VAdvancedDateInput exposes the AdvancedDateInputPublicInstance<TDate> handle:
| Member | Type | Description |
| ------------------- | ------------------------------- | ---------------------------------------------------------------- |
| commitInput() | () => Promise<boolean> | Validates the current draft and commits it when possible |
| validate() | () => Promise<string[]> | Runs draft validation and returns the current messages |
| resetValidation() | () => Promise<void> | Clears parse and rule validation state |
| revertDraft() | () => void | Restores the committed value and formatted text |
| text | string | Current visible input text |
| draft | AdvancedDateInputDraft<TDate> | Current draft snapshot |
| isDirty | boolean | Whether the current text differs from the committed display text |
| isPristine | boolean | Whether the field has avoided validation so far |
| isValid | boolean \| null | null while pristine, then the current validation state |
| errorMessages | string[] | Current merged parse and field-rule errors |
Styling and Theming
Import @gigerit/vuetify-date-input-advanced/style.css once. The picker uses .v-advanced-date-picker as its root class. The input wrapper uses .v-advanced-date-input.
Key CSS custom properties:
| Variable | Default | Purpose |
| ------------------------------------ | -------------------------------------------------------------------------------- | -------------------------- |
| --v-advanced-date-picker-color | rgb(var(--v-theme-primary)) | Accent color |
| --v-advanced-date-range-bg | computed | Confirmed range background |
| --v-advanced-date-range-preview-bg | computed | Hover-preview background |
| --v-advanced-date-selected-bg | var(--v-advanced-date-picker-color) | Selected day background |
| --v-advanced-date-selected-color | rgb(var(--v-theme-on-primary)) | Selected day text color |
| --v-advanced-date-preset-width | 220px | Preset column width |
| --v-advanced-date-cell-size | 44px | Calendar cell size |
| --v-advanced-date-day-size | calc(var(--v-advanced-date-cell-size) - 2px) | Day button size |
| --v-advanced-date-day-inset | calc((var(--v-advanced-date-cell-size) - var(--v-advanced-date-day-size)) / 2) | Range background inset |
| --v-advanced-date-gap | 24px | Gap between visible months |
By default, --v-advanced-date-day-size and
--v-advanced-date-day-inset stay derived from
--v-advanced-date-cell-size, so a runtime cell-size override keeps the grid
and range highlights aligned unless you also override the inner variables.
Example:
.booking-picker {
--v-advanced-date-preset-width: 18rem;
--v-advanced-date-cell-size: 48px;
--v-advanced-date-picker-color: rgb(var(--v-theme-secondary));
}Picker accent color is controlled through the CSS custom properties above.
VAdvancedDateInput.color only forwards to the built-in text field control(s);
it does not remap picker accent styling.
Accessibility and Keyboard
The current implementation includes:
- Per-day
aria-label,aria-selected,aria-disabled, andaria-current="date" - A live region that announces visible months and selected values
- Roving focus across day buttons
- Keyboard navigation on the calendar grid
Keyboard shortcuts:
| Key | Behavior |
| --------------------------------- | ------------------------------------------------------------------ |
| ArrowLeft / ArrowRight | Move 1 day |
| ArrowUp / ArrowDown | Move 1 week |
| Home / End | Move to start or end of the current week based on firstDayOfWeek |
| PageUp / PageDown | Move 1 month |
| Shift+PageUp / Shift+PageDown | Move 1 year |
| Enter / Space | Select active day |
| Escape | Cancel picker interaction |
Development
Repository layout:
src/: components, composables, utilities, styles, and plugin entryplayground/: local Vite app for manual QAtests/: Vitest and Vue Test Utils coveragedist/: generated build output
Useful scripts:
npm install
npm run dev
npm run typecheck
npm run test
npm run lint
npm run build
npm run formatCI
GitHub Actions now validates the repo automatically with .github/workflows/ci.yml.
- pull requests to
main, pushes tomain, and manualworkflow_dispatchruns execute the same core checks used locally - the workflow installs dependencies with
npm ciand runsnpm run typecheck,npm run lint,npm run test, andnpm run build - the job uses Node
22.x, matching the current release pipeline runtime - in-progress runs for the same ref are canceled when a newer commit is pushed
Before opening a PR, the matching local safety check is:
npm run typecheck
npm run lint
npm run test
npm run buildReleases
Releases are automated from .github/workflows/release.yml.
.github/workflows/ci.ymlhandles routine validation for pushes and pull requestsgoogleapis/release-please-actionopens and maintains the release PR from conventional commits onmain- when that release PR is merged, GitHub Actions builds, validates, and publishes the package to npm with provenance
- npm publishing is configured for trusted publishing via GitHub OIDC, so no long-lived
NPM_TOKENis required in the workflow
Because npm trusted publishers can only be configured for packages that already exist on the registry, the first publish still has to be done manually by an authenticated maintainer.
After the initial publish, configure the package as a trusted publisher for this repository and workflow in npm, or with npm CLI v11.10.0+:
npm trust github @gigerit/vuetify-date-input-advanced \
--repo gigerIT/vuetify-date-input-advanced \
--file .github/workflows/release.ymlVerified from the repository configuration:
- The library is built with Vite in library mode
- Output formats are ESM and CommonJS
- Declaration files are generated from
src/ - Styles are exported as
@gigerit/vuetify-date-input-advanced/style.css - Tests run in
jsdomwith Vuetify bootstrapped in Vue Test Utils
Notes
- Examples in this README use native
Date, but the actual value type follows your configured Vuetify date adapter. - Default package icons use Vuetify aliases (
$calendar,$prev,$next) so they follow your app's official Vuetify icon configuration.
