Skip to content
Lenso UI

DatePicker 日期选择器

基于 React Aria DatePicker,通过 DateField 与 Calendar 组合的可组合日期选择器

用法

import { DatePicker, DateField, Calendar, Label } from '@lenso/ui';

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";
/** Adapted from the pinned HeroUI v3.2.6 basic.json. Copyright NextUI Inc. Apache-2.0. Local RAC label and StyleX replace source Label and utility classes. */import { Calendar, DateField, DatePicker } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";
const styles = stylex.create({ field: { width: 288 } });export function Basic() {  return (    <DatePicker xstyle={styles.field} name="date">      <DatePicker.Label>Date</DatePicker.Label>      <DateField.Group fullWidth>        <DateField.Input>{(segment) => <DateField.Segment segment={segment} />}</DateField.Input>        <DateField.Suffix>          <DatePicker.Trigger>            <DatePicker.TriggerIndicator />          </DatePicker.Trigger>        </DateField.Suffix>      </DateField.Group>      <DatePicker.Popover>        <Calendar aria-label="Event date">          <Calendar.Header>            <Calendar.YearPickerTrigger>              <Calendar.YearPickerTriggerHeading />              <Calendar.YearPickerTriggerIndicator />            </Calendar.YearPickerTrigger>            <Calendar.NavButton slot="previous" />            <Calendar.NavButton slot="next" />          </Calendar.Header>          <Calendar.Grid>            <Calendar.GridHeader>              {(day) => <Calendar.HeaderCell>{day}</Calendar.HeaderCell>}            </Calendar.GridHeader>            <Calendar.GridBody>{(date) => <Calendar.Cell date={date} />}</Calendar.GridBody>          </Calendar.Grid>          <Calendar.YearPickerGrid>            <Calendar.YearPickerGridBody>              {({ year }) => <Calendar.YearPickerCell year={year} />}            </Calendar.YearPickerGridBody>          </Calendar.YearPickerGrid>        </Calendar>      </DatePicker.Popover>    </DatePicker>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

组件结构

DatePicker 采用组合优先 API。显式组合 DateField 与 Calendar 以控制结构与样式。

import {Calendar, DateField, DatePicker, Label} from '@lenso/ui';
export default () => (  <DatePicker>    <Label />    <DateField.Group>      <DateField.Input>        {(segment) => <DateField.Segment segment={segment} />}      </DateField.Input>      <DateField.Suffix>        <DatePicker.Trigger>          <DatePicker.TriggerIndicator />        </DatePicker.Trigger>      </DateField.Suffix>    </DateField.Group>    <DatePicker.Popover>      <Calendar aria-label="Choose date">        <Calendar.Header>          <Calendar.YearPickerTrigger>            <Calendar.YearPickerTriggerHeading />            <Calendar.YearPickerTriggerIndicator />          </Calendar.YearPickerTrigger>          <Calendar.NavButton slot="previous" />          <Calendar.NavButton slot="next" />        </Calendar.Header>        <Calendar.Grid>          <Calendar.GridHeader>            {(day) => <Calendar.HeaderCell>{day}</Calendar.HeaderCell>}          </Calendar.GridHeader>          <Calendar.GridBody>{(date) => <Calendar.Cell date={date} />}</Calendar.GridBody>        </Calendar.Grid>      </Calendar>    </DatePicker.Popover>  </DatePicker>)

示例

禁用

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";/** HeroUI v3.2.6 adapted example. Copyright NextUI Inc. Apache-2.0. */export { Disabled } from "./scenarios";

Local adaptation source above. Derived from HeroUI v3.2.6 source.

受控组件

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";/** HeroUI v3.2.6 adapted example. Copyright NextUI Inc. Apache-2.0. */export { Controlled } from "./scenarios";

Local adaptation source above. Derived from HeroUI v3.2.6 source.

表单校验

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";/** HeroUI v3.2.6 adapted example. Copyright NextUI Inc. Apache-2.0. */export { WithValidation } from "./scenarios";

Local adaptation source above. Derived from HeroUI v3.2.6 source.

格式选项

使用 granularity、hourCycle、hideTimeZone、shouldForceLeadingZeros 等 props 控制 DatePicker 值的显示方式。

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";/** Adapted from HeroUI v3.2.6 format-options.json. Copyright NextUI Inc. Apache-2.0. */import { DatePicker, TimeField } from "@lenso/ui";import {  getLocalTimeZone,  parseDate,  parseZonedDateTime,  type DateValue,} from "@internationalized/date";import { useMemo, useState } from "react";import * as stylex from "@stylexjs/stylex";import { PickerCalendar, PickerInput } from "./parts";import { FormatControls, formatStyles, type Granularity, type HourCycle } from "./format-controls";
export function FormatOptions() {  const [granularity, setGranularity] = useState<Granularity>("minute");  const [hourCycle, setHourCycle] = useState<HourCycle>(12);  const [hideTimeZone, setHideTimeZone] = useState(false);  const [shouldForceLeadingZeros, setShouldForceLeadingZeros] = useState(false);  const timeGranularity = granularity !== "day" ? granularity : undefined;  const defaultValue = useMemo<DateValue>(    () =>      granularity === "day"        ? parseDate("2026-02-03")        : parseZonedDateTime(`2026-02-03T08:45:00[${getLocalTimeZone()}]`),    [granularity],  );  return (    <div {...stylex.props(formatStyles.stack)}>      <DatePicker        key={granularity}        xstyle={formatStyles.field}        defaultValue={defaultValue}        granularity={granularity}        hourCycle={hourCycle}        hideTimeZone={hideTimeZone}        shouldForceLeadingZeros={shouldForceLeadingZeros}        name="date"      >        {({ state }) => (          <>            <DatePicker.Label>Date and time</DatePicker.Label>            <PickerInput />            <DatePicker.Popover xstyle={formatStyles.popover}>              <PickerCalendar />              {timeGranularity && (                <div {...stylex.props(formatStyles.timeRow)}>                  <span {...stylex.props(formatStyles.label)}>Time</span>                  <TimeField                    aria-label="Time"                    granularity={timeGranularity}                    hourCycle={hourCycle}                    hideTimeZone={hideTimeZone}                    name="time"                    shouldForceLeadingZeros={shouldForceLeadingZeros}                    value={state.timeValue}                    onChange={(value) => {                      if (value) state.setTimeValue(value);                    }}                  >                    <TimeField.Group variant="secondary">                      <TimeField.Input>                        {(segment) => <TimeField.Segment segment={segment} />}                      </TimeField.Input>                    </TimeField.Group>                  </TimeField>                </div>              )}            </DatePicker.Popover>          </>        )}      </DatePicker>      <FormatControls        {...{          granularity,          setGranularity,          hourCycle,          setHourCycle,          hideTimeZone,          setHideTimeZone,          shouldForceLeadingZeros,          setShouldForceLeadingZeros,        }}      />    </div>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

表单示例

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";/** HeroUI v3.2.6 adapted example. Copyright NextUI Inc. Apache-2.0. */export { FormExample } from "./scenarios";

Local adaptation source above. Derived from HeroUI v3.2.6 source.

自定义指示器

未提供 children 时,DatePicker.TriggerIndicator 渲染默认 IconCalendar。传入 children 可替换。

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";/** HeroUI v3.2.6 adapted example. Copyright NextUI Inc. Apache-2.0. */export { WithCustomIndicator } from "./scenarios";

Local adaptation source above. Derived from HeroUI v3.2.6 source.

渲染函数

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";/** Adapted from HeroUI v3.2.6 render-function.json. Copyright NextUI Inc. Apache-2.0. RAC 1.21 native DOM render functions preserve props, refs and input semantics. */import { DateField, DatePicker } from "@lenso/ui";import { PickerCalendar, styles } from "./parts";
export function RenderFunction() {  return (    <DatePicker      xstyle={styles.field}      name="date"      render={(props) => <div {...props} data-custom="date-picker" />}    >      <DatePicker.Label render={(props) => <span {...props} data-custom="date-picker-label" />}>        Date      </DatePicker.Label>      <DateField.Group        fullWidth        render={(props) => <div {...props} data-custom="date-field-group" />}      >        <DateField.Input render={(props) => <div {...props} data-custom="date-field-input" />}>          {(segment) => (            <DateField.Segment              render={(props) => <span {...props} data-custom="date-field-segment" />}              segment={segment}            />          )}        </DateField.Input>        <DateField.Suffix>          <DatePicker.Trigger            render={(props) => <button {...props} data-custom="date-picker-trigger" />}          >            <DatePicker.TriggerIndicator />          </DatePicker.Trigger>        </DateField.Suffix>      </DateField.Group>      <DatePicker.Popover>        <PickerCalendar />      </DatePicker.Popover>    </DatePicker>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

国际化日历

默认情况下,DatePicker 使用用户 locale 的日历系统显示日期。可用 I18nProvider 包裹并设置 Unicode 日历 locale 扩展 覆盖。

以下示例展示印度日历系统:

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";/** HeroUI v3.2.6 adapted example. Copyright NextUI Inc. Apache-2.0. */export { InternationalCalendar } from "./scenarios";

Local adaptation source above. Derived from HeroUI v3.2.6 source.

Note: 无论显示的 locale 如何,onChange 事件始终返回与 value 或 defaultValue 相同日历系统的日期(未提供 value 时为 Gregorian)。这确保应用逻辑在单一日历系统下一致运行,同时仍可按用户偏好格式显示日期。

完整支持的日历系统及其标识符列表请参阅:

自定义样式

Tailwind CSS

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";/** HeroUI v3.2.6 adapted example. Copyright NextUI Inc. Apache-2.0. */export { CustomStyles } from "./scenarios";

Local adaptation source above. Derived from HeroUI v3.2.6 source.

全局 CSS

使用 @layer components 自定义 DatePicker 基础类。

@layer components {  .date-picker {    @apply inline-flex flex-col gap-1;  }
  .date-picker__trigger {    @apply inline-flex items-center justify-between;  }
  .date-picker__trigger-indicator {    @apply text-muted;  }
  .date-picker__popover {    @apply min-w-[var(--trigger-width)] p-0;  }}

样式参考

HeroUI 遵循 BEM 命名以便复用自定义。

CSS 类

DatePicker 在 packages/styles/components/date-picker.css 中使用以下类:

  • .date-picker - 根包裹层
  • .date-picker__trigger - 打开 popover 的触发器部分
  • .date-picker__trigger-indicator - 默认/自定义指示器 slot
  • .date-picker__popover - Popover 内容包裹层

交互状态

DatePicker 支持 React Aria data 属性与伪状态:

  • Open:触发器上 [data-open="true"]
  • Disabled:触发器上 [data-disabled="true"] 或 [aria-disabled="true"]
  • Focus visible:触发器上 :focus-visible 或 [data-focus-visible="true"]
  • Hover:触发器上 :hover 或 [data-hovered="true"]

API 参考

DatePicker

DatePicker 继承 React Aria DatePicker 的所有 props。

Prop类型默认值描述
valueDateValue | null-受控选中日期值
defaultValueDateValue | null-非受控模式下的默认选中值
onChange(value: DateValue | null) => void-选中日期变化时调用
isOpenboolean-受控 popover 打开状态
defaultOpenbooleanfalse初始 popover 打开状态
onOpenChange(isOpen: boolean) => void-popover 打开状态变化时调用
isDisabledbooleanfalse禁用日期选择与触发器交互
isInvalidboolean-标记字段为无效以显示校验状态
minValueDateValue-最小可选日期
maxValueDateValue-最大可选日期
namestring-HTML 表单提交时使用的 name
childrenReactNode | (values: DatePickerRenderProps) => ReactNode-组合内容或 render 函数
renderDOMRenderFunction<keyof React.JSX.IntrinsicElements, DatePickerRenderProps>-使用自定义 render 函数覆盖默认 DOM 元素

Composition Parts

ComponentDescription
DatePicker.Root根 date picker 容器与状态所有者
DatePicker.Trigger触发按钮,通常渲染在 DateField.Suffix 内
DatePicker.TriggerIndicator带默认日历图标的指示器 slot
DatePicker.PopoverCalendar 内容的 Popover 包裹层
  • @internationalized/date — 所有日期组件使用的日期类型(CalendarDate、CalendarDateTime、ZonedDateTime)与工具
  • I18nProvider — 为子树覆盖 locale
  • useLocale — 读取当前 locale 与布局方向

相关组件