跳到主要内容

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

属性类型默认值说明
valueDate选中日期
onChange(date: Date | undefined) => void选中回调
placeholderstring'Select date'触发器占位文本
formatDate(date: Date) => stringYYYY/MM/DD日期格式化函数
disabledbooleanfalse禁用
allowClearbooleantrue悬停时显示清除按钮
openboolean受控打开状态
defaultOpenbooleanfalse默认打开
onOpenChange(open: boolean) => void打开状态变更回调
disabledDateMatcher | Matcher[]日历禁用条件
fromDateDate最早可选日期
toDateDate最晚可选日期
defaultMonthDate默认展示月份
classNamestring触发器自定义 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

属性类型默认值说明
valueDateRange选中范围 { from: Date; to?: Date }
onChange(range: DateRange | undefined) => void选中回调
startPlaceholderstring'Start date'起始日期占位文本
endPlaceholderstring'End date'结束日期占位文本
formatDate(date: Date) => stringYYYY/MM/DD日期格式化函数
separatorReactNode'–'起止日期之间的分隔符
disabledbooleanfalse禁用
allowClearbooleantrue悬停时显示清除按钮
openboolean受控打开状态
defaultOpenbooleanfalse默认打开
onOpenChange(open: boolean) => void打开状态变更回调
disabledDateMatcher | Matcher[]日历禁用条件
fromDateDate最早可选日期
toDateDate最晚可选日期
defaultMonthDate默认展示月份
classNamestring触发器自定义 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(双月日历范围选择)。支持可清除值、禁用状态、受控打开模式和自定义日期格式化。