DatePicker / RangePicker
- 组件说明:日期选择组件 —
DatePicker用于单日期选择,RangePicker用于日期范围选择。两者均封装内部 Calendar 组件,通过 Popover 弹出日历面板。 - 尺寸基线:Trigger 高 32px,日历面板宽 332px(RangePicker 双月并排),日期单元格 36×36px,圆角 5px。
- 实现约定:Trigger 使用
<button>模拟输入框外观。日历面板在 Popover 中展示,选中后自动关闭。零外部运行时依赖。 - DatePicker Figma 规范 / RangePicker Figma 规范
DatePicker
基础用法
点击触发器打开日历面板,选中日期后面板关闭,触发器显示格式化后的日期。
结果
Loading...
实时编辑器
const Demo = () => { const [date, setDate] = useState(undefined) return ( <div style={{ padding: '40px 0' }}> <DatePicker className="w-62" value={date} onChange={setDate} placeholder="选择日期" /> </div> ) } render(<Demo />)
状态
禁用
结果
Loading...
实时编辑器
const Demo = () => { return ( <div style={{ display: 'flex', gap: 16, padding: '40px 0' }}> <DatePicker className="w-62" disabled placeholder="禁用(空)" /> <DatePicker className="w-62" disabled value={new Date(2026, 3, 20)} /> </div> ) } render(<Demo />)
有值(可清除)
鼠标悬停在触发器上时显示清除按钮。
结果
Loading...
实时编辑器
const Demo = () => { const [date, setDate] = useState(new Date(2026, 3, 20)) return ( <div style={{ padding: '40px 0' }}> <DatePicker className="w-62" value={date} onChange={setDate} /> </div> ) } render(<Demo />)
禁用日期
使用 disabledDate 限制可选日期范围。例如禁用所有过去的日期:
结果
Loading...
实时编辑器
const Demo = () => { const [date, setDate] = useState(undefined) return ( <div style={{ padding: '40px 0' }}> <DatePicker className="w-62" value={date} onChange={setDate} disabledDate={{ before: new Date() }} placeholder="不可选过去日期" /> </div> ) } render(<Demo />)
自定义格式
结果
Loading...
实时编辑器
const Demo = () => { const [date, setDate] = useState(new Date(2026, 3, 20)) const format = (d) => d.toLocaleDateString('zh-CN', { year: 'numeric', month: 'long', day: 'numeric' }) return ( <div style={{ padding: '40px 0' }}> <DatePicker className="w-62" value={date} onChange={setDate} formatDate={format} /> </div> ) } render(<Demo />)
DatePicker Props
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
value | Date | — | 选中日期 |
onChange | (date: Date | undefined) => void | — | 选中回调 |
placeholder | string | 'Select date' | 触发器占位文本 |
formatDate | (date: Date) => string | YYYY/MM/DD | 日期格式化函数 |
disabled | boolean | false | 禁用 |
allowClear | boolean | true | 悬停时显示清除按钮 |
open | boolean | — | 受控打开状态 |
defaultOpen | boolean | false | 默认打开 |
onOpenChange | (open: boolean) => void | — | 打开状态变更回调 |
disabledDate | Matcher | Matcher[] | — | 日历禁用条件 |
fromDate | Date | — | 最早可选日期 |
toDate | Date | — | 最晚可选日期 |
defaultMonth | Date | — | 默认展示月份 |
className | string | — | 触发器自定义 class |
RangePicker
基础用法
点击触发器打开双月日历面板。先选择起始日期,再选择结束日期,范围完成后面板自动关闭。
结果
Loading...
实时编辑器
const Demo = () => { const [range, setRange] = useState(undefined) return ( <div style={{ padding: '40px 0' }}> <RangePicker className="w-85" value={range} onChange={setRange} /> </div> ) } render(<Demo />)
状态
禁用
结果
Loading...
实时编辑器
const Demo = () => { return ( <div style={{ display: 'flex', flexDirection: 'column', gap: 16, padding: '40px 0' }}> <RangePicker className="w-85" disabled /> <RangePicker className="w-85" disabled value={{ from: new Date(2026, 3, 17), to: new Date(2026, 4, 1) }} /> </div> ) } render(<Demo />)
有值(可清除)
鼠标悬停在触发器上时显示清除按钮。
结果
Loading...
实时编辑器
const Demo = () => { const [range, setRange] = useState({ from: new Date(2026, 3, 17), to: new Date(2026, 4, 1) }) return ( <div style={{ padding: '40px 0' }}> <RangePicker className="w-85" value={range} onChange={setRange} /> </div> ) } render(<Demo />)
禁用日期
结果
Loading...
实时编辑器
const Demo = () => { const [range, setRange] = useState(undefined) return ( <div style={{ padding: '40px 0' }}> <RangePicker className="w-85" value={range} onChange={setRange} disabledDate={{ before: new Date() }} startPlaceholder="从今天起" endPlaceholder="到..." /> </div> ) } render(<Demo />)
自定义分隔符
结果
Loading...
实时编辑器
const Demo = () => { const [range, setRange] = useState(undefined) return ( <div style={{ padding: '40px 0' }}> <RangePicker className="w-85" value={range} onChange={setRange} separator="~" /> </div> ) } render(<Demo />)
RangePicker Props
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
value | DateRange | — | 选中范围 { from: Date; to?: Date } |
onChange | (range: DateRange | undefined) => void | — | 选中回调 |
startPlaceholder | string | 'Start date' | 起始日期占位文本 |
endPlaceholder | string | 'End date' | 结束日期占位文本 |
formatDate | (date: Date) => string | YYYY/MM/DD | 日期格式化函数 |
separator | ReactNode | '–' | 起止日期之间的分隔符 |
disabled | boolean | false | 禁用 |
allowClear | boolean | true | 悬停时显示清除按钮 |
open | boolean | — | 受控打开状态 |
defaultOpen | boolean | false | 默认打开 |
onOpenChange | (open: boolean) => void | — | 打开状态变更回调 |
disabledDate | Matcher | Matcher[] | — | 日历禁用条件 |
fromDate | Date | — | 最早可选日期 |
toDate | Date | — | 最晚可选日期 |
defaultMonth | Date | — | 默认展示月份 |
className | string | — | 触发器自定义 class |
Token 表
| 元素 | 属性 | Token / 值 |
|---|---|---|
| 触发器 | 边框(默认) | Separators/Emphasized#CCCCCC |
| 触发器 | 边框(激活) | Grays/Black#000000 |
| 触发器 | 背景 | Backgrounds/Primary#FFFFFF |
| 触发器(禁用) | 背景 | Grays/Gray-1#EBEBEB |
| 值文本 | 颜色 | Labels/Primary#000000 |
| 占位文本 | 颜色 | Labels/Tertiary#757575 |
| 分隔符(RangePicker) | 颜色 | Labels/Tertiary#757575 |
| 图标 | 颜色 | Labels/Secondary#3D3D3D |
| 面板 | 背景 | Backgrounds/Primary#FFFFFF |
| 面板 | 阴影 | Effects/Shadow/Defaultrgba(0,0,0,0.1) |
| 面板 | 边框 | Separators/Default#EBEBEB |
| 范围中间 | 背景 | Grays/Gray-1#EBEBEB |
尺寸规范
| 维度 | 值 |
|---|---|
| 触发器高度 | 32px |
| 触发器水平内边距 | Spacing_16 (16px) |
| 触发器圆角 | Radius_5 (5px) |
| 触发器字体 | Body/Regular (14px) |
| 日历面板宽度(DatePicker) | 332px |
| 日历面板(RangePicker) | 双月并排 |
| 日期单元格尺寸 | 36×36px |
| 弹出偏移量 | 4px |
变更记录
2026-04-14 — 首次发布
新增组件:DatePicker(单日期选择)和 RangePicker(双月日历范围选择)。支持可清除值、禁用状态、受控打开模式和自定义日期格式化。