跳到内容

范围日历

Alpha
呈现一个适合选择日期范围的日历视图。
事件日期,2024 年 10 月
2024 年 10 月
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
vue
<script setup lang="ts">
import { Icon } from '@iconify/vue'
import type { DateValue } from '@internationalized/date'
import { RangeCalendarCell, RangeCalendarCellTrigger, RangeCalendarGrid, RangeCalendarGridBody, RangeCalendarGridHead, RangeCalendarGridRow, RangeCalendarHeadCell, RangeCalendarHeader, RangeCalendarHeading, RangeCalendarNext, RangeCalendarPrev, RangeCalendarRoot } from 'radix-vue'

function isDateUnavailable(date: DateValue) {
  return date.day === 17 || date.day === 18
}
</script>

<template>
  <RangeCalendarRoot
    v-slot="{ weekDays, grid }"
    :is-date-unavailable="isDateUnavailable"
    class="rounded-xl bg-white p-4 shadow-xl"
    fixed-weeks
  >
    <RangeCalendarHeader class="flex items-center justify-between">
      <RangeCalendarPrev
        class="inline-flex items-center cursor-pointer text-black justify-center rounded-[9px] bg-transparent w-8 h-8 hover:bg-black hover:text-white active:scale-98 active:transition-all focus:shadow-[0_0_0_2px] focus:shadow-black"
      >
        <Icon
          icon="radix-icons:chevron-left"
          class="w-6 h-6"
        />
      </RangeCalendarPrev>
      <RangeCalendarHeading class="text-[15px] text-black font-medium" />
      <RangeCalendarNext
        class="inline-flex items-center cursor-pointer justify-center text-black rounded-[9px] bg-transparent w-8 h-8 hover:bg-black hover:text-white active:scale-98 active:transition-all focus:shadow-[0_0_0_2px] focus:shadow-black"
      >
        <Icon
          icon="radix-icons:chevron-right"
          class="w-6 h-6"
        />
      </RangeCalendarNext>
    </RangeCalendarHeader>
    <div
      class="flex flex-col space-y-4 pt-4 sm:flex-row sm:space-x-4 sm:space-y-0"
    >
      <RangeCalendarGrid
        v-for="month in grid"
        :key="month.value.toString()"
        class="w-full border-collapse select-none space-y-1"
      >
        <RangeCalendarGridHead>
          <RangeCalendarGridRow class="mb-1 grid w-full grid-cols-7">
            <RangeCalendarHeadCell
              v-for="day in weekDays"
              :key="day"
              class="rounded-md text-xs text-green8"
            >
              {{ day }}
            </RangeCalendarHeadCell>
          </RangeCalendarGridRow>
        </RangeCalendarGridHead>
        <RangeCalendarGridBody class="grid">
          <RangeCalendarGridRow
            v-for="(weekDates, index) in month.rows"
            :key="`weekDate-${index}`"
            class="grid grid-cols-7"
          >
            <RangeCalendarCell
              v-for="weekDate in weekDates"
              :key="weekDate.toString()"
              :date="weekDate"
            >
              <RangeCalendarCellTrigger
                :day="weekDate"
                :month="month.value"
                class="relative flex items-center justify-center rounded-full whitespace-nowrap text-sm font-normal text-black w-8 h-8 outline-none focus:shadow-[0_0_0_2px] focus:shadow-black data-[disabled]:text-black/30 data-[selected]:!bg-green10 data-[selected]:text-white hover:bg-green5 data-[highlighted]:bg-green5 data-[unavailable]:pointer-events-none data-[unavailable]:text-black/30 data-[unavailable]:line-through before:absolute before:top-[5px] before:hidden before:rounded-full before:w-1 before:h-1 before:bg-white data-[today]:before:block data-[today]:before:bg-green9 "
              />
            </RangeCalendarCell>
          </RangeCalendarGridRow>
        </RangeCalendarGridBody>
      </RangeCalendarGrid>
    </div>
  </RangeCalendarRoot>
</template>

致谢

此组件的构建灵感来自于 melt-ui 中的实现。

功能

  • 完整的键盘导航
  • 可以是受控或不受控的
  • 焦点完全管理
  • 本地化支持
  • 高度可组合

前言

该组件依赖于 @internationalized/date 包,该包解决了在 JavaScript 中处理日期和时间时遇到的许多问题。

我们强烈建议您通读该包的文档,以全面了解其工作原理,并且您需要将其安装到您的项目中才能使用与日期相关的组件。

安装

安装日期包。

sh
$ npm add @internationalized/date

从您的命令行安装该组件。

sh
$ npm add radix-vue

解剖

导入所有部分并将它们组合在一起。

vue
<script setup>
import {
  RangeCalendarCell,
  RangeCalendarCellTrigger,
  RangeCalendarGrid,
  RangeCalendarGridBody,
  RangeCalendarGridHead,
  RangeCalendarGridRow,
  RangeCalendarHeadCell,
  RangeCalendarHeader,
  RangeCalendarHeading,
  RangeCalendarNext,
  RangeCalendarPrev,
  RangeCalendarRoot
} from 'radix-vue'
</script>

<template>
  <RangeCalendarRoot>
    <RangeCalendarHeader>
      <RangeCalendarPrev />
      <RangeCalendarHeading />
      <RangeCalendarNext />
    </RangeCalendarHeader>
    <RangeCalendarGrid>
      <RangeCalendarGridHead>
        <RangeCalendarGridRow>
          <RangeCalendarHeadCell />
        </RangeCalendarGridRow>
      </RangeCalendarGridHead>
      <RangeCalendarGridBody>
        <RangeCalendarGridRow>
          <RangeCalendarCell>
            <RangeCalendarCellTrigger />
          </RangeCalendarCell>
        </RangeCalendarGridRow>
      </RangeCalendarGridBody>
    </RangeCalendarGrid>
  </RangeCalendarRoot>
</template>

API 参考

包含日历的所有部分

道具默认类型
as
'div'
AsTag | 组件

此组件应渲染成的元素或组件。可以通过 asChild 覆盖

asChild
布尔值

将默认渲染的元素更改为作为子元素传递的元素,合并其属性和行为。

阅读我们的 组合 指南以了解更多详细信息。

calendarLabel
字符串

日历的可访问标签

defaultPlaceholder
DateValue

默认占位符日期

defaultValue
{ start: undefined, end: undefined }
DateRange

日历的默认值

dir
'ltr' | 'rtl'

日历适用的阅读方向。
如果省略,则从 ConfigProvider 全局继承或假设 LTR(从左到右)阅读模式。

disabled
false
布尔值

日历是否禁用

fixedWeeks
false
布尔值

是否始终在日历中显示 6 周

initialFocus
false
布尔值

如果为真,日历将根据日历安装时可见的内容,聚焦选定的日期、当天或本月的第一天

isDateDisabled
Matcher

一个返回日期是否禁用的函数

isDateUnavailable
Matcher

一个返回日期是否不可用的函数

locale
'en'
字符串

用于格式化日期的区域设置

maxValue
DateValue

可以选择的最大日期

minValue
DateValue

可以选择的最早日期

modelValue
DateRange

日历的受控选中状态。可以绑定为 v-model

nextPage
((placeholder: DateValue) => DateValue)

一个返回日历下一页的函数。它接收组件内部的当前占位符作为参数。

numberOfMonths
1
数字

要一次显示的月份数

pagedNavigation
false
布尔值

此属性会导致上一个和下一个按钮按一次显示的月份数进行导航,而不是一个月

placeholder
DateValue

占位符日期,用于确定未选择日期时显示哪个月。当用户浏览日历时,它会更新,可用于以编程方式控制日历视图

preventDeselect
false
布尔值

是否阻止用户在不先选择另一个日期的情况下取消选择日期

prevPage
((placeholder: DateValue) => DateValue)

一个返回日历上一页的函数。它接收组件内部的当前占位符作为参数。

readonly
false
布尔值

日历是否只读

weekdayFormat
'narrow'
'narrow' | 'short' | 'long'

通过 weekdays 插槽道具提供的星期几字符串使用的格式

weekStartsOn
0
0 | 1 | 2 | 3 | 4 | 5 | 6

日历开始的星期几

发射有效载荷
update:modelValue
[date: DateRange]

每当模型值发生变化时调用的事件处理程序

update:placeholder
[date: DateValue]

每当占位符值发生变化时调用的事件处理程序

update:startValue
[date: DateValue]

每当开始值发生变化时调用的事件处理程序

插槽(默认)有效载荷
date
DateValue

占位符的当前日期

grid
Grid<DateValue>[]

日期网格

weekDays
字符串[]

一周中的日子

weekStartsOn
0 | 1 | 2 | 3 | 4 | 5 | 6

一周的开始

locale
字符串

日历区域设置

fixedWeeks
布尔值

是否始终在日历中显示 6 周

数据属性价值
[data-readonly]只读时出现
[data-disabled]禁用时出现
[data-invalid]无效时出现

包含导航按钮和标题段。

道具默认类型
as
'div'
AsTag | 组件

此组件应渲染成的元素或组件。可以通过 asChild 覆盖

asChild
布尔值

将默认渲染的元素更改为作为子元素传递的元素,合并其属性和行为。

阅读我们的 组合 指南以了解更多详细信息。

上一个按钮

日历导航按钮。它根据当前日历视图,将日历向前导航一个月/一年/十年。

数据属性价值
[data-disabled]禁用时出现
道具默认类型
as
'button'
AsTag | 组件

此组件应渲染成的元素或组件。可以通过 asChild 覆盖

asChild
布尔值

将默认渲染的元素更改为作为子元素传递的元素,合并其属性和行为。

阅读我们的 组合 指南以了解更多详细信息。

prevPage
((placeholder: DateValue) => DateValue)

用于上一个页面的函数。覆盖了在 RangeCalendarRoot 上设置的 prevPage 函数。

step
'month' | 'year'

要前进的日历单位

下一个按钮

日历导航按钮。它根据当前日历视图,将日历向后导航一个月/一年/十年。

道具默认类型
as
'button'
AsTag | 组件

此组件应渲染成的元素或组件。可以通过 asChild 覆盖

asChild
布尔值

将默认渲染的元素更改为作为子元素传递的元素,合并其属性和行为。

阅读我们的 组合 指南以了解更多详细信息。

nextPage
((placeholder: DateValue) => DateValue)

用于下一页的函数。覆盖了在 RangeCalendarRoot 上设置的 nextPage 函数。

step
'month' | 'year'

要前进的日历单位

数据属性价值
[data-disabled]禁用时出现

标题

用于显示当前月份和年份的标题。

道具默认类型
as
'div'
AsTag | 组件

此组件应渲染成的元素或组件。可以通过 asChild 覆盖

asChild
布尔值

将默认渲染的元素更改为作为子元素传递的元素,合并其属性和行为。

阅读我们的 组合 指南以了解更多详细信息。

插槽(默认)有效载荷
headingValue
字符串

当前月份和年份

数据属性价值
[data-disabled]禁用时出现

网格

用于包装日历网格的容器。

道具默认类型
as
'table'
AsTag | 组件

此组件应渲染成的元素或组件。可以通过 asChild 覆盖

asChild
布尔值

将默认渲染的元素更改为作为子元素传递的元素,合并其属性和行为。

阅读我们的 组合 指南以了解更多详细信息。

数据属性价值
[data-readonly]只读时出现
[data-disabled]禁用时出现

网格头

用于包装网格头的容器。

道具默认类型
as
'thead'
AsTag | 组件

此组件应渲染成的元素或组件。可以通过 asChild 覆盖

asChild
布尔值

将默认渲染的元素更改为作为子元素传递的元素,合并其属性和行为。

阅读我们的 组合 指南以了解更多详细信息。

网格主体

用于包装网格主体的容器。

道具默认类型
as
'tbody'
AsTag | 组件

此组件应渲染成的元素或组件。可以通过 asChild 覆盖

asChild
布尔值

将默认渲染的元素更改为作为子元素传递的元素,合并其属性和行为。

阅读我们的 组合 指南以了解更多详细信息。

网格行

用于包装网格行的容器。

道具默认类型
as
'tr'
AsTag | 组件

此组件应渲染成的元素或组件。可以通过 asChild 覆盖

asChild
布尔值

将默认渲染的元素更改为作为子元素传递的元素,合并其属性和行为。

阅读我们的 组合 指南以了解更多详细信息。

头部单元格

用于包装头部单元格的容器。用于显示星期几。

道具默认类型
as
'th'
AsTag | 组件

此组件应渲染成的元素或组件。可以通过 asChild 覆盖

asChild
布尔值

将默认渲染的元素更改为作为子元素传递的元素,合并其属性和行为。

阅读我们的 组合 指南以了解更多详细信息。

单元格

用于包装日历单元格的容器。

道具默认类型
as
'td'
AsTag | 组件

此组件应渲染成的元素或组件。可以通过 asChild 覆盖

asChild
布尔值

将默认渲染的元素更改为作为子元素传递的元素,合并其属性和行为。

阅读我们的 组合 指南以了解更多详细信息。

date*
DateValue
数据属性价值
[data-disabled]禁用时出现

单元格触发器

用于显示单元格日期的可交互容器。点击它可以选择日期。

道具默认类型
as
'div'
AsTag | 组件

此组件应渲染成的元素或组件。可以通过 asChild 覆盖

asChild
布尔值

将默认渲染的元素更改为作为子元素传递的元素,合并其属性和行为。

阅读我们的 组合 指南以了解更多详细信息。

day*
DateValue
month*
DateValue
插槽(默认)有效载荷
dayValue
字符串

当前日期

数据属性价值
[data-selected]选中时出现
[data-value]日期的 ISO 字符串值。
[data-disabled]禁用时出现
[data-unavailable]不可用时出现
[data-today]当天时出现
[data-outside-view]日期不在其显示的当前月份中时出现。
[data-outside-visible-view]日期不在日历上可见的月份中时出现。
[data-selection-start]日期是选择的开始时出现。
[data-selection-end]日期是选择的结束时出现。
[data-highlighted]用户在选择范围时突出显示日期时出现。
[data-highlighted-start]日期是用户突出显示的范围的开始时出现。
[data-highlighted-end]日期是用户突出显示的范围的结束时出现。
[data-focused]聚焦时出现

无障碍

键盘交互

按键描述
Tab
当焦点移动到日历时,聚焦第一个导航按钮。
空格
当焦点在 `CalendarNext` 或 `CalendarPrev` 上时,它会导航日历。否则,它会选择日期。
回车
当焦点在 `CalendarNext` 或 `CalendarPrev` 上时,它会导航日历。否则,它会选择日期。
左箭头右箭头上箭头下箭头
当焦点在 `CalendarCellTrigger` 上时,它会导航日期,必要时会更改月份/年份/十年。