用途
Date Range 组件用于让用户选择开始日期和结束日期,定义一个连续的时间段。它扩展了 Date Picker 模式,引入范围可视化(高亮两个选中日期之间的天数)以及范围专属校验(结束日期必须晚于开始日期、最小/最大范围长度)。
主要能力
- 双输入对:两个独立日期字段,带联动校验。
- 单日历面板或双面板 UI:用户选择时进行可视化范围高亮。
- 范围校验:开始日期、最小/最大范围强制约束,并对两个选中日期进行无障碍播报。
使用方式
实现工作流:
- 在复制示例前,先确认该模式与问题及约束匹配。
- 从 references/pattern.md 中的结构与示例入手,然后选择最小可行的变体。
- 在叠加视觉打磨之前,先应用无障碍、性能和交互防护措施。
- 使用测试指南验证键盘、屏幕阅读器、响应式及失败场景下的行为。
键盘交互模式:
| 按键 | 操作 |
|---|---|
| Tab | 在开始输入框、结束输入框和日历触发器之间移动 |
| Enter / Space | 在输入框或触发器上打开选择器;确认悬停日期 |
| Arrow Right | 将焦点移到日历中的下一天 |
| Arrow Left | 将焦点移到前一天 |
| Arrow Down | 将焦点移到下周同一天 |
| Arrow Up | 将焦点移到上周同一天 |
| Page Up | 导航到上一个月 |
性能防护指标:
- 选择器打开时间:双面板日历 < 150ms
- 悬停预览:悬停期间每帧 < 16ms
- 范围提交(选择结束日期):更新 UI < 50ms
- 预设范围选择:应用日期 < 30ms
- 内存占用:双面板日期范围选择器 < 30KB
适用场景
- 酒店/旅行预订——入住和退房日期选择。
- 活动时长——活动或营销活动的开始和结束日期。
- 报告周期——分析仪表盘的日期筛选(“最近 7 天”、自定义范围)。
- 租赁和预订系统——租车、设备租赁周期。
- 请假与休假申请——带最小/最大天数的假期日期选择。
限制与应避免的场景
- 单日期选择——使用 Date Picker。
- 开放式筛选——“仅起始日期”或“仅结束日期”——使用两个独立的日期输入。
- 超长日期范围——跨多年的范围更适合用月份/年份选择器。
- 开始和结束可为同一天时——需在 UX 文案中明确说明。
常见错误
开始日期变化时重置结束日期
问题:当用户调整开始日期(例如从 3 月 12 日改为 3 月 15 日)时,自动清空结束日期会让只想把范围平移几天的用户感到沮丧。
修复方法:如果新的开始日期早于现有结束日期,保留结束日期。仅当新的开始日期晚于结束日期时才清空。
function onStartDateChange(newStart) {
if (endDate && newStart < endDate) {
// Keep end date — range is still valid
} else {
setEndDate(null); // Only clear if invalid
}
setStartDate(newStart);
}
没有进行中的视觉反馈
问题:用户点击开始日期后,日历看起来没有变化——没有提示系统正在等待选择结束日期。
修复方法:显示说明文字,并对潜在范围进行悬停预览。
calendar.addEventListener('mouseover', (e) => {
if (selectingEndDate && e.target.matches('.calendar__day-btn')) {
const hoverDate = getDateFromCell(e.target);
if (hoverDate > startDate) {
highlightRange(startDate, hoverDate, 'preview');
}
}
});
忽略最小/最大范围约束
问题:租赁和预订系统通常有最短入住要求。如果不在视觉上强制(通过禁用开始日期最小范围内的单元格),用户就能选择无效范围。
修复方法:选择开始日期后,禁用最小范围内的所有单元格。
function getDisabledDatesForEndSelection(startDate, minDays) {
const disabled = [];
for (let i = 1; i < minDays; i++) {
const d = new Date(startDate);
d.setDate(d.getDate() + i);
disabled.push(d);
}
return disabled;
}
相关模式
- https://uxpatterns.dev/patterns/forms/date-input
- https://uxpatterns.dev/patterns/forms/date-picker
- https://uxpatterns.dev/patterns/forms/selection-input
完整实现细节、示例和测试说明,请参见 references/pattern.md。
模式页面:https://uxpatterns.dev/patterns/forms/date-range