生态产品多个设计器现已发布正式版

查看生态总览
跳转到内容

DateField 日期字段 ​

按年、月、日逐段输入日期,适合已经知道目标日期、无需浏览日历的场景。

用法 ​

输入日期

截止日期
yyyy
/
mm
/
dd

组件结构 ​

加粗的是必需部件。

data-scope="date-field":root · label · control · segment-group · segment · clear-trigger · hidden-input

示例 ​

地区格式 ​

根据 locale 调整日期顺序

中文格式
2026
年
07
月
28
日
美国格式
07
/
28
/
2026

日期范围 ​

限制可输入日期

有效日期(2020—2030)
2026
年
07
月
28
日
早于最小日期
2019
年
05
月
01
日

状态 ​

禁用、只读与校验失败

禁用
2026
年
07
月
28
日
只读
2026
年
07
月
28
日
校验失败
2026
年
07
月
28
日

变体 ​

设置输入框外观

outline
2026
年
07
月
28
日
subtle
2026
年
07
月
28
日
ghost
2026
年
07
月
28
日

日期与时间 ​

输入精确到分钟的日期

发布时间
2026
年
07
月
28
日 
13
:
45

12 小时制 ​

hourCycle=12 时小时段收 1-12,分钟段之后多出上下午段(按 a / p 切换),值仍是 24 小时制的 ISO 串

Departure
07
/
28
/
2026
 
09
:
05
 
PM
当前值:2026-07-28T21:05

设计指引 ​

何时使用 ​

  • 用户已知确切日期,例如生日或证件有效期。
  • 需要使用键盘快速逐段输入。

何时不用 ​

特性 ​

  • locale 决定日期段的顺序和分隔方式。
  • 不写结构时按标准结构铺出标题、段组与清空按钮、表单影子(Vue 不写默认插槽、React 不给 children、Web Components 不写部件或只写 root),三端出自同一个结构函数:段按当前段序铺,段与段之间的分隔符从 locale 现取(zh-CN 是 2026/07/28,en-US 到分钟是 07/28/2026, 13:45),label 给标题文字。Web Components 里标题可以写在宿主的直接子节点上接管:slot="label"。
  • min 与 max 限制可输入范围。
  • placeholder 给对象是逐段的占位串;给字符串是整条占位,一段都没填、焦点也不在段上时段位与分隔符让位给这句文字,焦点一进来就换回段位。
  • granularity 支持日期或精确到分钟的日期时间;hourCycle={12} 时小时段收 1-12,时刻段后面多出上下午段,值仍是 24 小时制的 ISO 串。
  • year + week 段集使用 ISO 周历,固定周一到周日,不随显示语言改变。
  • 不提供 formatOptions,也不解析 YYYY/MM/DD 这类格式串。能用 Intl.DateTimeFormat 选项表达的显示差异已经各有归口:段序与分隔符随 locale,由哪几段组成随 granularity / segments,小时制随 hourCycle。其余选项要么改变值的含义(两位年份还原不出唯一的世纪,era 需要另一套纪年),要么改变编辑方式(month: 'long' 的文字月份要按字母跳选,逐段键入与上下键加减都对不上)。格式串绕开 locale 的段序,还得自带一套解析器,同一个值在别的语言下会被写成对方读不懂的顺序。只是要换一种写法展示选中值时,用时间戳或 Intl.DateTimeFormat 另外格式化。
  • 标准组合包含标签、输入框、日期段和隐藏表单输入;支持受控值与原生表单提交。
  • 聚焦只强调正在编辑的日期段,错误段使用独立的危险色反馈。
  • 清空按钮默认收起,输入任一段后出现;点按后回到第一段,聚焦边界平滑过渡。

组合 ​

  • 日期选择器与日期范围选择器的输入区就是这一套逐段输入,只是多了日历浮层。
  • 日期与时间分开录入时与时间字段并排;只用一个字段时通过 granularity 精确到分钟。
  • 在表单中以 ISO 日期字符串参与校验与提交。

最佳实践 ​

  • 使用清晰的字段标签。
  • 给参与表单提交的字段设置 name,并渲染隐藏输入部件。
  • 有业务范围限制时设置 min 与 max。
  • 对外统一使用 ISO 日期字符串。

反模式 ​

  • 使用普通文本输入接收日期并自行解析。

API 参考 ​

产物 ​

层值
自定义元素<xh-date-field>
Vue 组件XhDateFieldClearTrigger XhDateFieldControl XhDateFieldHiddenInput XhDateFieldLabel XhDateFieldRoot XhDateFieldSegment XhDateFieldSegmentGroup
组合式函数useDateField
状态机dateFieldMachine
皮肤@xihan-ui/styles/date-field.css

Props ​

属性类型必填说明
labelledboolean作者渲染了 label 部件时置真,由适配器统计而不是判断标题文字是否有值。 为假时可聚焦部件不把 label 的 id 写进 aria-labelledby:指向未渲染的 id 是无效引用,作者写在控件上的 aria-label 也会被它压住。
ariaLabelstring不显示出来的名字,写成 aria-label 落在与字段标签同一个部件上。 放进字段(字段接线)或渲染了 label 部件时名字以它们为准,aria-labelledby 盖过它。
valuestring | null受控值,ISO 串('2026-07-28' / '2026-07-28T13:45');null 表示空。提供即受控。
defaultValuestring | null非受控初值,同样是 ISO 串。
minstring下界,ISO 串。参与各段区间的收窄,并决定 outOfRange。
maxstring上界,ISO 串。
localestringBCP 47 语言标记,决定年月日三段的先后。未提供时按宿主语言,宿主也没有时按 en-US(月日年)排列。
timeZonestringIANA 时区名,只用于取今天:空段上按上下键时从今天的对应位起步。
granularityDateGranularity精度,默认 day(只有年月日三段)。提供 segments 时它不再生效。
hourCycleDateHourCycle时刻段的小时制,默认 24,不随 locale 推断。12 时小时段收 1-12,时刻段后面多出上下午段(按 a / p 或上下键切换); 只在按 granularity 铺段且精度到时以下时生效,提供 segments 时由段集里有没有 dayPeriod 决定。值仍是 24 小时制的 ISO 串。
segmentsDateSegmentSet段集:该控件由哪几段组成,提供后以它为准,granularity 让位。写 ['year', 'quarter'] 得到「2026 Q2」、['year', 'week'] 得到「2026 33」。归一后为空(如 [])视同未提供。 值仍是 ISO 日期(时间)串,因此段集中必须有 year,否则段位可编辑但无法拼出值。
disabledboolean
readOnlyboolean
invalidboolean
requiredboolean
namestring表单字段名;提供后隐藏输入才带 name,ISO 串随表单一并提交。
placeholderstring | DateSegmentPlaceholders占位。给对象是逐段的占位串,覆盖内置默认(yyyy / mm / dd / hh / mm / ss)。 给字符串是整条占位:一段都没填、焦点也不在段上时,段位与分隔符让位给这句文字(「请选择生效时间」), 焦点一进来就换回段位,段位仍显示内置的逐段占位。
translationsDateFieldTranslations各段的读屏名字,逐段覆盖内置默认。段是 spinbutton,没有名字时读屏只能朗读一串数字。
variantControlVariant形态:outline / subtle / ghost,决定底色与描边的绘制方式。默认 outline。
toneTone语气:brand / neutral / success / warning / danger / info,决定聚焦与强调使用哪族颜色。
sizeSize尺寸:sm / md / lg。
onValueChange(details: DateFieldValueChangeDetails) => void
onClear() => void用户按清空钮(clear-trigger)清掉了值;先发值变化,再发它。程序化的 clear() 不发。

事件 ​

自定义元素将载荷放在 detail;Vue 使用同名 emit。

事件载荷说明
value-changeDateFieldValueChangeDetails值变化;detail 为 { value: string | null }
clear``用户按清空钮(clear-trigger)清掉了值;先发值变化,再发它。程序化的 clear() 不发。

插槽 ​

仅列出带载荷的插槽。

Vue 组件插槽载荷说明
XhDateFieldRootdefaultDateFieldRootSlotProps
XhDateFieldRootlabel—
XhDateFieldSegmentdefaultDateFieldSegmentSlotProps

React 适配器 props ​

只列各组件自己声明的那些:继承自 ComponentPropsWithRef 的 DOM 属性不在其中,根组件上与上面 Props 表同名的也不重复列。Vue 的对应物是上面的插槽表。

React 组件属性类型必填说明
XhDateFieldRootlabelReactNode标题。不给 children 时铺 label 部件。
XhDateFieldRootchildrenSlotChildren<DateFieldRootSlotProps>
XhDateFieldSegmentindexnumber | string下标由作者声明,对应哪一段由 locale 与段集计算;兼收字符串。
XhDateFieldSegmentsegmentDateSegmentType按段名声明该格。段集中没有该段时它收起;与 index 二选一,两个都写时按段名计算。
XhDateFieldSegmentchildrenSlotChildren<DateFieldSegmentSlotProps>

状态 ​

以下名称仅用于内部状态机。

状态:idle

事件:VALUE.SET · VALUE.CLEAR · SEGMENT.STEP · SEGMENT.TYPE · SEGMENT.CLEAR · SEGMENT.PERIOD · SEGMENT.FOCUS · SEGMENT.BLUR · FORM.RESET · PRESS.START · PRESS.END

判据:canEdit · canPress

connect API ​

getXxxProps() 返回对应部件的宿主属性。

成员类型说明
valuestring | nullISO 串;段位未填齐时为 null。
valueAsDateDate | null同一个值的原生 Date;空值或无法计算时为 null。按 timeZone 换算。
segmentsDateFieldSegmentState[]逐段投影,文档序即当前的段序(提供 segments 时是其归一后的顺序,否则由 locale 排列)。
completeboolean段位已填齐(value 非 null)。
emptyboolean没有任何段已填。
outOfRangeboolean已填齐但落在 min / max 之外。
disabledboolean
readOnlyboolean
invalidboolean
focusedSegmentDateSegmentType | null焦点所在的段;焦点在组外时为 null。
localestring
granularityDateGranularity
setValue(next: string | null) => void直接写整份值;传 null 等于清空。
clear() => void清空全部段位;disabled / readOnly 下不生效。
canClearboolean清空按钮当前是否可用:有段已填值、且可编辑。
getRootProps() => T['element']
getLabelProps() => T['element']标题不是原生 label(段位是 div,不可被 label 标注),点击它由连接层代为把焦点送进首段。
getControlProps() => T['element']role=group 的分段容器。
getSegmentGroupProps() => T['element']段位与分隔符的外壳:占满盒内剩余宽度,把清空按钮推到框内末端。
segmentOf(props: DateFieldSegmentProps) => DateFieldSegmentState | undefined作者的声明落在哪一段上;段集中没有该段(或下标越界)时缺席。文字由适配器按它渲染。
getSegmentProps(props: DateFieldSegmentProps) => T['element']
getClearTriggerProps() => T['button']清空按钮:不占 Tab 位,无值或不可编辑时收起;点击后焦点回到首段。
getHiddenInputProps() => T['input']表单出口:一份 type=hidden 的原生输入,值是 ISO 串。

无障碍 ​

键盘 ​

规格出处:W3C APG

按键生效条件行为
ArrowUpfocus in a segment, not disabled/readOnly本段加一,到区间上界回绕到下界;空段则落到今天的对应位
ArrowDownfocus in a segment, not disabled/readOnly本段减一,到区间下界回绕到上界;空段则落到今天的对应位
ArrowRightfocus in a segment, not disabled焦点移到下一段(跳过收起的段);已在末段则不动,不回绕
ArrowLeftfocus in a segment, not disabled焦点移到上一段;已在首段则不动,不回绕
Homefocus in a segment, not disabled焦点移到首段
Endfocus in a segment, not disabled焦点移到末段
Backspacefocus in a segment, not disabled/readOnly清掉本段,焦点不动;整份值随之变成 null
0 / 1 / 2 / 3 / 4 / 5 / 6 / 7 / 8 / 9focus in a segment, not disabled/readOnly往本段补一位数字;补满(再补一位必溢出或位数用尽)即自动跳下一段。上下午段没有数字位,不收数字
Enter / Spaceheld in clear-trigger, 填了哪怕一段, not disabled/readOnly按住期间清空按钮投影 data-pressed,与指针 :active 同一副按压面;抬起或失焦撤下,段位清空后按钮藏起一并撤下。清空按钮不占 Tab 位,键盘这一路只在焦点落到它身上时有面
a / pfocus in 上下午段, not disabled/readOnly直接指定上午 / 下午;上下键在两者之间翻面

ARIA ​

以下属性由 connect 生成。

部件属性值
controlaria-disabled'true' | 'false'
controlaria-labelprops.ariaLabel
controlaria-labelledbylabel 部件的 id | undefined
controlrole'group'
segmentaria-disabledundefined | 'true' | 'false'
segmentaria-invalidundefined | 'true' | 'false'
segmentaria-labelitem?.label
segmentaria-readonlyundefined | 'true' | 'false'
segmentaria-requiredundefined | 'true' | 'false'
segmentaria-valuemaxundefined | String(item.max)
segmentaria-valueminundefined | String(item.min)
segmentaria-valuenowundefined | String(item.value)
segmentaria-valuetextitem?.text
segmentroleundefined | 'spinbutton'
clear-triggeraria-labeltranslations.clearTrigger

样式参考 ​

皮肤 ​

@xihan-ui/styles/date-field.css 按 [data-scope="date-field"][data-part="root"] 部件选择器书写,发布产物以挂载类 .xh-scope-date-field 代替其中的 data-scope(特异性相同),位于 xihan.components 层。覆盖样式使用 xihan.overrides,部件选择器照常可用。

forced-colors: active 下另有一套规则:颜色交给系统,边框与状态标记改用系统色关键字。

数据属性 ​

由 connect 生成;条件不成立时不输出无值属性。

部件属性值
rootdata-complete''(条件成立时才出现)
rootdata-disabled''(条件成立时才出现)
rootdata-empty''(条件成立时才出现)
rootdata-invalid''(条件成立时才出现)
rootdata-out-of-range''(条件成立时才出现)
rootdata-readonly''(条件成立时才出现)
rootdata-sizeprops.size
rootdata-toneprops.tone
rootdata-variantprops.variant
labeldata-disabled''(条件成立时才出现)
controldata-disabled''(条件成立时才出现)
controldata-invalid''(条件成立时才出现)
controldata-readonly''(条件成立时才出现)
controldata-variantprops.variant
controldata-xh-action-owner''
controldata-xh-field-chrome''
controldata-xh-field-sizeprops.size
segment-groupdata-disabled''(条件成立时才出现)
segment-groupdata-invalid''(条件成立时才出现)
segment-groupdata-placeholder-shown''(条件成立时才出现)
segment-groupdata-placeholder-textprops.placeholder | undefined
segment-groupdata-readonly''(条件成立时才出现)
segmentdata-disabled''(条件成立时才出现)
segmentdata-focus''(条件成立时才出现)
segmentdata-indexString(index) | undefined
segmentdata-invalid''(条件成立时才出现)
segmentdata-placeholder''(条件成立时才出现)
segmentdata-readonly''(条件成立时才出现)
segmentdata-segmentitem?.type
clear-triggerdata-pressed''(条件成立时才出现)
clear-triggerdata-xh-action-control''
clear-triggerdata-xh-action-display'has-value'
clear-triggerdata-xh-action-has-value''(条件成立时才出现)
clear-triggerdata-xh-action-profile'field-inset'
clear-triggerdata-xh-action-sizeprops.size
clear-triggerdata-xh-action-variant'ghost'

CSS 变量 ​

本组件公开覆盖槽由独立皮肤的实际消费位生成;默认来源、作用部件和状态均与 CSS 同源。

变量部件CSS 属性状态默认来源说明
--xh-date-field-action-bgclear-trigger--xh-ink-surface
background-color
default
xh-ink-surface
--xh-_action-variant-bg-restdate-field 的 clear-trigger 部件 --xh-ink-surface、background-color 覆盖槽。
--xh-date-field-action-bg-activeclear-triggerbackground-colordisabled
is(:active, [data-pressed])
loading
not([data-disabled])
not([data-loading])
pressed
--xh-_action-variant-bg-presseddate-field 的 clear-trigger 部件 background-color 覆盖槽。
--xh-date-field-action-bg-hoverclear-triggerbackground-colordisabled
hover
loading
not([data-disabled])
not([data-loading])
--xh-_action-variant-bg-hoverdate-field 的 clear-trigger 部件 background-color 覆盖槽。
--xh-date-field-action-fgclear-triggercolordefault--xh-fg-field-cleardate-field 的 clear-trigger 部件 color 覆盖槽。
--xh-date-field-action-fg-hoverclear-triggercolordisabled
hover
loading
not([data-disabled])
not([data-loading])
--xh-fg-defaultdate-field 的 clear-trigger 部件 color 覆盖槽。
--xh-date-field-action-font-sizeclear-triggerfont-sizedefault--xh-text-secondary-sizedate-field 的 clear-trigger 部件 font-size 覆盖槽。
--xh-date-field-action-radiusclear-triggerborder-radiusdefault--xh-shape-circledate-field 的 clear-trigger 部件 border-radius 覆盖槽。
--xh-date-field-action-sizeclear-triggerblock-size
inline-size
min-inline-size
default
xh-action-profile=field-inset
--xh-_action-profile-visual-sizedate-field 的 clear-trigger 部件 block-size、inline-size、min-inline-size 覆盖槽。
--xh-date-field-control-bgcontrolbackground-colorxh-field-chrome--xh-_field-variant-bg-restdate-field 的 control 部件 background-color 覆盖槽。
--xh-date-field-control-bg-disabledcontrolbackground-colordisabled
xh-field-chrome
--xh-_field-variant-bg-disableddate-field 的 control 部件 background-color 覆盖槽。
--xh-date-field-control-bg-hovercontrolbackground-colordisabled
hover
invalid
loading
not(:focus-within)
not([data-disabled])
not([data-invalid])
not([data-loading])
not([data-readonly])
readonly
xh-field-chrome
--xh-_field-variant-bg-hoverdate-field 的 control 部件 background-color 覆盖槽。
--xh-date-field-control-bg-readonlycontrolbackground-colorreadonly
xh-field-chrome
--xh-_field-variant-bg-read-onlydate-field 的 control 部件 background-color 覆盖槽。
--xh-date-field-control-bordercontrolborderxh-field-chrome--xh-_field-variant-border-restdate-field 的 control 部件 border 覆盖槽。
--xh-date-field-control-border-focuscontrolborder-color
box-shadow
disabled
focus-within
not([data-disabled])
xh-field-chrome
--xh-_field-variant-border-focusdate-field 的 control 部件 border-color、box-shadow 覆盖槽。
--xh-date-field-control-border-hovercontrolborder-colordisabled
hover
invalid
loading
not(:focus-within)
not([data-disabled])
not([data-invalid])
not([data-loading])
not([data-readonly])
readonly
xh-field-chrome
--xh-_field-variant-border-hoverdate-field 的 control 部件 border-color 覆盖槽。
--xh-date-field-control-border-invalidcontrolborder-colorinvalid
xh-field-chrome
--xh-_field-variant-border-invaliddate-field 的 control 部件 border-color 覆盖槽。
--xh-date-field-control-fgcontrolcolorxh-field-chrome--xh-fg-defaultdate-field 的 control 部件 color 覆盖槽。
--xh-date-field-control-gapcontrolgapxh-field-chrome--xh-_date-field-gapdate-field 的 control 部件 gap 覆盖槽。
--xh-date-field-control-hcontrolblock-size
min-block-size
has([data-xh-field-input][data-xh-field-layout='multi-tag'])
has([data-xh-field-input][data-xh-field-layout='single-line'])
has([data-xh-field-input][data-xh-field-layout='textarea'])
xh-field-chrome
xh-field-input
xh-field-layout=multi-tag
xh-field-layout=single-line
xh-field-layout=textarea
--xh-_date-field-control-hdate-field 的 control 部件 block-size、min-block-size 覆盖槽。
--xh-date-field-control-min-wcontrol
root
min-inline-sizedefault
xh-field-chrome
--xh-control-min-wdate-field 的 control、root 部件 min-inline-size 覆盖槽。
--xh-date-field-control-pxcontrolpadding-inlinexh-field-chrome--xh-_date-field-control-pxdate-field 的 control 部件 padding-inline 覆盖槽。
--xh-date-field-control-radiuscontrolborder-radiusxh-field-chrome--xh-shape-controldate-field 的 control 部件 border-radius 覆盖槽。
--xh-date-field-control-shadowcontrolbox-shadowxh-field-chromenonedate-field 的 control 部件 box-shadow 覆盖槽。
--xh-date-field-control-wrootinline-size
min-inline-size
default--xh-control-wdate-field 的 root 部件 inline-size、min-inline-size 覆盖槽。
--xh-date-field-font-sizecontrolfont-sizedefault--xh-_date-field-font-sizedate-field 的 control 部件 font-size 覆盖槽。
--xh-date-field-gaplabel
root
gap
margin-block-end
default--xh-space-1date-field 的 label、root 部件 gap、margin-block-end 覆盖槽。
--xh-date-field-icon-sizecontrol
root
--xh-icon-sizedefault
size=lg
size=sm
xh-field-chrome
--xh-_field-size-glyph-size
--xh-glyph-size-lg
--xh-glyph-size-md
--xh-glyph-size-sm
date-field 的 control、root 部件 --xh-icon-size 覆盖槽。
--xh-date-field-label-fglabelcolordefault--xh-fg-muteddate-field 的 label 部件 color 覆盖槽。
--xh-date-field-label-fg-disabledlabelcolordisabled--xh-fg-muteddate-field 的 label 部件 color 覆盖槽。
--xh-date-field-label-font-sizelabelfont-sizedefault--xh-text-label-sizedate-field 的 label 部件 font-size 覆盖槽。
--xh-date-field-label-font-weightlabelfont-weightdefault--xh-text-label-weightdate-field 的 label 部件 font-weight 覆盖槽。
--xh-date-field-label-gaplabelmargin-block-enddefault--xh-space-2date-field 的 label 部件 margin-block-end 覆盖槽。
--xh-date-field-literal-fgsegment-groupcolornot([data-scope])--xh-fg-subtledate-field 的 segment-group 部件 color 覆盖槽。
--xh-date-field-placeholder-fgsegment
segment-group
colorplaceholder
placeholder-shown
--xh-fg-subtledate-field 的 segment、segment-group 部件 color 覆盖槽。
--xh-date-field-segment-bg-focussegmentbackgroundfocus
focus-visible
--xh-_date-field-segment-bgdate-field 的 segment 部件 background 覆盖槽。
--xh-date-field-segment-bg-invalid-focussegmentbackgroundfocus
invalid
is([data-focus], :focus-visible)
--xh-bg-subtledate-field 的 segment 部件 background 覆盖槽。
--xh-date-field-segment-fg-focussegmentcolorfocus
focus-visible
placeholder
--xh-_date-field-segment-fgdate-field 的 segment 部件 color 覆盖槽。
--xh-date-field-segment-fg-invalidsegmentcolorinvalid--xh-fg-dangerdate-field 的 segment 部件 color 覆盖槽。
--xh-date-field-segment-fg-invalid-focussegmentcolorfocus
invalid
is([data-focus], :focus-visible)
--xh-fg-dangerdate-field 的 segment 部件 color 覆盖槽。
--xh-date-field-segment-pxsegmentpadding-inlinedefault--xh-space-0_5date-field 的 segment 部件 padding-inline 覆盖槽。
--xh-date-field-segment-pysegmentpadding-blockdefault--xh-space-0date-field 的 segment 部件 padding-block 覆盖槽。
--xh-date-field-segment-radiussegmentborder-radiusdefault--xh-shape-insetdate-field 的 segment 部件 border-radius 覆盖槽。

动效 ​

动效角色:按压 · 状态 · 出现(见动效规范)。

共享关键帧 xh-fade-in 由 family/motion.css 提供,皮肤 @import 它,单独引入仍成立;background-color · color · opacity · visibility 走 transition 过渡。时长与缓动读动效令牌,改令牌即改全局节奏。

系统开启减弱动效时由令牌层统一收敛,皮肤不另作判断。

RTL ​

皮肤用逻辑属性排布(inline-start 一族),dir="rtl" 下自动镜像。

Released under The MIT License