Skip to content
API 风格:

Calendar ​

Month-view calendar built on the DatePicker core, with selection modes, optional range constraint and grid keyboard navigation.

Basic usage ​

Basic
Oct 2026
SunMonTueWedThuFriSat
vue
<script setup>
import { ref } from 'vue'
const date = ref(new Date())
</script>

<template>
  <LhCalendar v-model="date" />
</template>
vue
<script>
export default {
  data() {
    return { date: new Date() }
  },
}
</script>

<template>
  <LhCalendar v-model="date" />
</template>

Selection modes ​

selection changes the picking semantics: 'single' (default), 'range' (two clicks for a start/end span), or 'multiple' (toggle individual dates). The shape of v-model follows the mode.

Range span
Oct 2026
SunMonTueWedThuFriSat
Nov 2026
SunMonTueWedThuFriSat
vue
<script setup>
import { ref } from 'vue'
// range mode holds [start, end]
const span = ref([new Date(2026, 8, 5), new Date(2026, 8, 20)])
</script>

<template>
  <LhCalendar
    v-model="span"
    selection="range"
    :panels="2"
  />
</template>
vue
<script>
export default {
  data() {
    // range mode holds [start, end]
    return { span: [new Date(2026, 8, 5), new Date(2026, 8, 20)] }
  },
}
</script>

<template>
  <LhCalendar
    v-model="span"
    selection="range"
    :panels="2"
  />
</template>
Multiple dates
Oct 2026
SunMonTueWedThuFriSat
vue
<script setup>
import { ref } from 'vue'
// multiple mode holds Date[]
const dates = ref([new Date(2026, 8, 10)])
</script>

<template>
  <LhCalendar
    v-model="dates"
    selection="multiple"
  />
</template>
vue
<script>
export default {
  data() {
    // multiple mode holds Date[]
    return { dates: [new Date(2026, 8, 10)] }
  },
}
</script>

<template>
  <LhCalendar
    v-model="dates"
    selection="multiple"
  />
</template>

Range constraint ​

range restricts the selectable dates to a given interval — useful together with selection="range".

Range constraint
Oct 2026
SunMonTueWedThuFriSat
vue
<script setup>
import { ref } from 'vue'

// JS months are 0-based: new Date(2026, 8, 1) is September 1st
const range = [new Date(2026, 8, 1), new Date(2026, 8, 28)]
const rangeDate = ref([])
</script>

<template>
  <LhCalendar
    v-model="rangeDate"
    selection="range"
    :range="range"
  />
</template>
vue
<script>
export default {
  data() {
    return {
      // JS months are 0-based: new Date(2026, 8, 1) is September 1st
      range: [new Date(2026, 8, 1), new Date(2026, 8, 28)],
      rangeDate: [],
    }
  },
}
</script>

<template>
  <LhCalendar
    v-model="rangeDate"
    selection="range"
    :range="range"
  />
</template>

Collapsible input mode ​

mode="input" collapses the always-visible panel into an input that expands on click. panels controls how many month panels are shown at once (laid out with flex wrap), placeholder sets the hint text, and close-on-select decides whether the panel collapses after a selection.

Input mode with two panels
vue
<script setup>
import { ref } from 'vue'
const inputDate = ref(new Date())
</script>

<template>
  <LhCalendar
    v-model="inputDate"
    mode="input"
    :panels="2"
    placeholder="Pick a date"
  />
</template>
vue
<script>
export default {
  data() {
    return { inputDate: new Date() }
  },
}
</script>

<template>
  <LhCalendar
    v-model="inputDate"
    mode="input"
    :panels="2"
    placeholder="Pick a date"
  />
</template>
Keep open after selecting
vue
<script setup>
import { ref } from 'vue'
const inputDate2 = ref(new Date())
</script>

<template>
  <LhCalendar
    v-model="inputDate2"
    mode="input"
    :close-on-select="false"
    placeholder="Panel stays open after selecting"
  />
</template>
vue
<script>
export default {
  data() {
    return { inputDate2: new Date() }
  },
}
</script>

<template>
  <LhCalendar
    v-model="inputDate2"
    mode="input"
    :close-on-select="false"
    placeholder="Panel stays open after selecting"
  />
</template>

API ​

LhCalendar Props ​

AttributeDescriptionTypeDefault
modelValueSelected date (controlled v-model)Date | Date[]—
selectionSelection mode: single / range span / multiple"single" | "range" | "multiple"'single'
rangeSelectable date range constraint[Date, Date]—
modeDisplay form: always-visible panel / collapsible input"panel" | "input"'panel'
panelsNumber of month panels shown at once (flex wrap)number1
placeholderPlaceholder text for input modestring—
closeOnSelectWhether input mode collapses the panel after selectingbooleantrue
sxQuick layout propsLhSxProps—

LhCalendar Events ​

EventDescriptionCallback
update:modelValueSelected value changed (v-model)(value: Date | Date[]) => void
changeSelected value changed(value: Date | Date[]) => void
selectA date cell is clicked, before the selected value updates(date: Date) => void

Slots: cell (custom cell), header (header).

Accessibility ​

  • Grid semantics: role="grid" (rows and gridcells), today gets aria-current="date"
  • Arrow keys move the focused date (±1 day / ±7 days), Home/End, PageUp/Down per month (APG grid pattern)
  • Dates outside the range are natively disabled and removed from interaction

Type Definitions ​

The TypeScript type structures exported by this component (auto-extracted from packages/components/calendar/src/types.ts and @lh-ui/share/core/* sources; click each entry to expand; see the Props table above for attribute descriptions):

LhCalendarMode
ts
export type LhCalendarMode = 'panel' | 'input'
LhCalendarValue
ts
export type LhCalendarValue = Date | Date[]
LhCalendarProps
ts
export interface LhCalendarProps {
  modelValue?: LhCalendarValue
  selection?: LhCalendarSelection
  range?: LhCalendarRange
  mode?: LhCalendarMode
  panels?: number
  placeholder?: string
  closeOnSelect?: boolean
  sx?: LhSxProps
}
LhCalendarSelection (from @lh-ui/share/core/calendar)
ts
export type LhCalendarSelection = 'single' | 'range' | 'multiple'
LhCalendarRange (from @lh-ui/share/core/calendar)
ts
export type LhCalendarRange = [Date, Date]

Beauty of tradition, foundation of code