Skip to content

Calendar

A tiled calendar component that supports single, multiple, and range selection. You can customize each day cell, restrict the maximum range, and limit min/max dates. It complements the wheel-based DatetimePicker and is ideal for order, travel, leave, and check-in scenarios that benefit from clear visualization.

Platform Differences

App (vue)App (nvue)H5Mini Program

Basic Usage · Single Selection

  • The default mode is 'single'. Click a date to select it, then tap the bottom Confirm button to fire update:modelValue and onConfirm.
  • Use monthsCount to control how many months are rendered (default 6).
html
<see-calendar v-model="value" :months-count="1" @on-confirm="onConfirm" />

<script lang="ts" setup>
import { ref } from 'vue'

const value = ref<Date | ''>('')
const onConfirm = (val) => {
  console.log('Confirmed date:', val)
}
</script>

Confirm on Tap

  • Set isShowConfirm to false. In single-selection mode, tapping a date triggers update:modelValue immediately, skipping the confirm button.
html
<see-calendar v-model="value" mode="single" :is-show-confirm="false" />

Multiple Selection

  • Set mode to 'multiple' to select multiple dates.
  • Tapping an already-selected date removes it.
  • The bound value is a Date[] array.
html
<see-calendar v-model="value" mode="multiple" :is-show-confirm="false" />

<script lang="ts" setup>
import { ref } from 'vue'

const value = ref<Date[]>([])
</script>

Range Selection

  • Set mode to 'range'. The first tap picks the start date and the second tap picks the end date.
  • If the second tap precedes the start date, the order is automatically reversed.
  • Dates between start and end are highlighted.
  • The bound value is [startDate, endDate].
html
<see-calendar v-model="value" mode="range" :months-count="2" />

<script lang="ts" setup>
import { ref } from 'vue'

const value = ref<Date[]>([])
</script>

Range · Maximum Days

  • Use maxRange to cap the number of days a range can span. When exceeded, the selection is not completed and onOverRange is emitted.
html
<see-calendar v-model="value" mode="range" :max-range="7" @on-over-range="onOverRange" />

<script lang="ts" setup>
const onOverRange = () => {
  uni.showToast({ title: '7 days max', icon: 'none' })
}
</script>

Range · Allow Same Day

  • allowSameDay defaults to false. Tapping the start date again will not complete the selection.
  • When set to true, the start and end can be the same day (useful for half-day scenarios).
html
<see-calendar v-model="value" mode="range" allow-same-day />

Min and Max Date

  • Use minDate and maxDate to constrain the selectable range. Dates outside the range are automatically disabled.
html
<see-calendar
  v-model="value"
  :min-date="minDate"
  :max-date="maxDate"
/>

<script lang="ts" setup>
import { ref } from 'vue'

const value = ref<Date | ''>('')
const minDate = new Date(2026, 5, 1)
const maxDate = new Date(2026, 11, 31)
</script>

First Day of Week

  • Use firstDayOfWeek to set the first day of each week (0 = Sunday, 1 = Monday, ...).
html
<see-calendar v-model="value" :first-day-of-week="1" />

Custom Day Cells (formatter)

  • The formatter callback lets you inject topInfo, bottomInfo, and className on each day cell, or disable specific days by setting isDisabled = true.
  • The formatter receives a CalendarDay and must return it; the component renders based on the returned value.
html
<see-calendar v-model="value" :formatter="dayFormatter" />

<script lang="ts" setup>
import { ref } from 'vue'
import type { CalendarDay } from 'see-u-ui'

const value = ref<Date | ''>('')

const dayFormatter = (day: CalendarDay): CalendarDay => {
  if (!day.date) return day
  const dom = day.date.getDate()
  const dow = day.date.getDay()
  if (dom === 1) day.topInfo = '1st'
  if (dom === 15) day.topInfo = '15th'
  if (dow === 0 || dow === 6) day.bottomInfo = 'off'
  return day
}
</script>

Readonly Mode

  • Set isReadonly to true to make the calendar display-only without responding to taps.
html
<see-calendar :model-value="value" is-readonly />

Custom Title and Button Text

  • Use title / subtitle to set the header texts.
  • Use confirmText / confirmDisabledText to customize the bottom button label (the latter is shown when selection is incomplete).
html
<see-calendar
  v-model="value"
  mode="range"
  title="Pick leave dates"
  subtitle="At least 1 day"
  confirm-text="Submit leave"
  confirm-disabled-text="Pick start and end"
  :months-count="2"
/>

API

Props

PropDescriptionTypeDefault
modelValuev-model value. A single date in single mode; an array in multiple/range modeDate | string | number | Array''
modeSelection mode'single' | 'multiple' | 'range''single'
minDateMinimum selectable dateDate | string | number-
maxDateMaximum selectable dateDate | string | number-
defaultDateInitial month to display (when modelValue is empty)Date | string | numbertoday
firstDayOfWeekFirst day of week (0 = Sun, 1 = Mon, ..., 6 = Sat)0 | 1 | 2 | 3 | 4 | 5 | 60
formatterCustomize each day cell(day: CalendarDay) => CalendarDay-
maxRangeMax days for range mode (0 = unlimited)number0
allowSameDayAllow same start and end day in range modebooleanfalse
rowHeightRow height of day cells (rpx)number | string128
isShowMarkWhether to show the month watermarkbooleantrue
isShowTitleWhether to show the header titlebooleantrue
isShowSubtitleWhether to show the weekday headerbooleantrue
isReadonlyReadonly modebooleanfalse
nameForm field name (for SeeForm integration)string''
titleHeader title textstring'Pick date'
subtitleHeader subtitle textstring''
confirmTextConfirm button textstring'Confirm'
confirmDisabledTextConfirm button text when range is incompletestring'Confirm'
isShowConfirmWhether to show the confirm buttonbooleantrue
monthsCountNumber of months to render forwardnumber6

Events

EventDescriptionCallback
update:modelValuev-model update (fired immediately for single/multiple when isShowConfirm=false, otherwise on Confirm)Date | Date[]
onSelectSelection changed (fires on every non-disabled day tap)Date | Date[]
onConfirmConfirm button tappedDate | Date[]
onClickDayAny day cell tapped (including disabled)CalendarDay
onOverRangeRange selection exceeded maxRange-
onMonthShowScrolled to a specific month (reserved API){ year: number; month: number }

Slots

NameDescriptionScoped params
titleCustomize the header title-
subtitleCustomize the subtitle-
footerCustomize the footer area (replaces the confirm button){ value }

Expose

MethodDescriptionParams
resetClear the current selection-
getValueGet current selected dates as an array-

TypeScript

ts
interface CalendarDay {
  date: Date | null
  text: string | number
  topInfo?: string
  bottomInfo?: string
  className?: string
  isDisabled?: boolean
  isToday?: boolean
  type?: '' | 'selected' | 'start' | 'middle' | 'end' | 'disabled' | 'placeholder' | 'start-end'
}

type CalendarMode = 'single' | 'multiple' | 'range'
type FirstDayOfWeek = 0 | 1 | 2 | 3 | 4 | 5 | 6

Liao ICP No. 2025070134