Demos
How to import
import { TimePicker } from '@fibrous/semi-ui-react';
Basic Usage
Click TimePicker, and then you can select or enter a time in the floating layer.
Code
import { TimePicker } from '@fibrous/semi-ui-react';
export default function TimePickerDemo() {
return <TimePicker />;
}Infinite Scroll
Starting from version V2.22.0, we changed the default mode of ScrollItem in TimePicker from wheel to normal. If you want to apply the effect of infinite scrolling back, please refer to the following example.
Code
import { TimePicker } from '@fibrous/semi-ui-react';
export default function TimePickerDemo() {
return <TimePicker scrollItemProps={{ mode: 'wheel', cycled: true }} />;
}Controlled Component
When using value And not. defaultValue When used as a controlled component.value and onChange It needs to be used in conjunction.
Code
import { useState } from 'react';
import { TimePicker } from '@fibrous/semi-ui-react';
export default function TimePickerDemo() {
const [value, setValue] = useState<Date | Date[] | null>(null);
const onChange = (time: Date | Date[]) => {
console.log(time);
setValue(time);
};
return <TimePicker value={value} onChange={onChange} />;
}Different Format
The columns in the TimePicker float will follow format Change, when omitted format At some point, the corresponding column in the floating layer will also disappear.
NOTE: format Follow the date-fns v4 format Format. https://date-fns.org/docs/format
Code
import { TimePicker } from '@fibrous/semi-ui-react';
export default function TimePickerDemo() {
return <TimePicker format="HH:mm" defaultValue="10:24" />;
}Set Panel Header and Footer
Disable Time Selection
Code
import { TimePicker } from '@fibrous/semi-ui-react';
export default function TimePickerDemo() {
return <TimePicker defaultValue="12:08:23" disabled />;
}Set Step Length
Available Hour Step, Minute Step, Second Step Show the optional minutes and seconds by step.
Code
import { TimePicker } from '@fibrous/semi-ui-react';
export default function TimePickerDemo() {
return <TimePicker minuteStep={15} secondStep={10} />;
}12-hour System
12-hour time selector, default format for a h:mm:ss, an incoming format The format must be in dateFns date formatWithin range.
For example, the default 12-hour format string is:
a h:mm:ss, if passed inA h:mm:ssThis will result in an inability to format correctly.
Code
import { TimePicker } from '@fibrous/semi-ui-react';
export default function TimePickerDemo() {
return (
<div>
<TimePicker use12Hours />
<br />
<br />
<TimePicker use12Hours format="a h:mm" />
</div>
);
}Time Range
Pass type = "timeRange" to enable time range selection.
Code
import { TimePicker } from '@fibrous/semi-ui-react';
export default function TimePickerDemo() {
return (
<div>
<TimePicker type="timeRange" defaultValue={['10:23:15', '12:38:32']} />
<br />
<br />
<TimePicker type="timeRange" use12Hours format="a h:mm" defaultValue={['上午 08:11', '下午 11:21']} />
</div>
);
}Disable left/right panels in Range mode (disabledTime)
When type="timeRange", you can use disabledTime(value, panelType) to apply different disabled rules for the left/right panel.
value: the currently selected times, the unpicked sideundefined(e.g.[date, undefined]); an empty array when there is no value, and length 1 whenvalue,defaultValueor the input holds a single timepanelType:'left' | 'right', representing start/end panel
In the following demo, after selecting a start time, the right (end) panel will disable options earlier than the start time.
Code
import { TimePicker } from '@fibrous/semi-ui-react';
export default function TimePickerDemo() {
return (
<TimePicker
type="timeRange"
disabledTime={(value, panelType) => {
const start = Array.isArray(value) ? value[0] : value;
if (panelType === 'right' && start instanceof Date) {
const h = start.getHours();
const m = start.getMinutes();
return {
disabledHours: () => Array.from({ length: h }, (_, i) => i),
disabledMinutes: (hour) => (hour === h ? Array.from({ length: m }, (_, i) => i) : []),
};
}
return {};
}}
/>
);
}Custom Trigger
By default we use the Input component as the trigger for the TimePicker component. You can customize this trigger by passing the triggerRender method.
Code
import { useState } from 'react';
import * as dateFns from 'date-fns';
import { IconTimePicker } from '@fibrous/semi-icons-react/lab';
import { TimePicker, Tag } from '@fibrous/semi-ui-react';
export default function TimePickerDemo() {
const formatToken = 'HH:mm:ss';
const [time, setTime] = useState(() => new Date(2019, 6, 23, 10, 32, 18));
return (
<TimePicker
value={time}
format={formatToken}
onChange={(time: Date | Date[]) => setTime(time as Date)}
triggerRender={({ placeholder }) => (
<Tag color="cyan" size="large" shape="circle" style={{ padding: 12, paddingRight: 16, fontSize: 14 }} type="light" prefixIcon={<IconTimePicker />}>
{time ? dateFns.format(time, formatToken) : placeholder}
</Tag>
)}
/>
);
}TimeZone Config
Semi All configuration about time zone is converged in ConfigProvider
Select Time Zone:
TimePicker:
Code
import { useMemo, useState } from 'react';
import { ConfigProvider, Select, TimePicker } from '@fibrous/semi-ui-react';
export default function TimePickerDemo() {
const [timeZone, setTimeZone] = useState('GMT+08:00');
const defaultTimestamp = 1581599305265;
const gmtList = useMemo(() => {
const list: string[] = [];
for (let hourOffset = -11; hourOffset <= 14; hourOffset++) {
const prefix = hourOffset >= 0 ? '+' : '-';
const hOffset = Math.abs(hourOffset);
list.push(`GMT${prefix}${String(hOffset).padStart(2, '0')}:00`);
}
return list;
}, []);
return (
<ConfigProvider timeZone={timeZone}>
<div style={{ width: 300 }}>
<h5 style={{ margin: 10 }}>Select Time Zone:</h5>
<Select aria-label="时区" placeholder="请选择时区" style={{ width: 300 }} value={timeZone} showClear onSelect={(value) => setTimeZone(String(value))}>
{gmtList.map((gmt) => (
<Select.Option key={gmt} value={gmt}>
{gmt}
</Select.Option>
))}
</Select>
<br />
<br />
<h5 style={{ margin: 10 }}>TimePicker:</h5>
<TimePicker defaultValue={defaultTimestamp} onChange={(date, dateString) => console.log('DatePicker changed: ', date, dateString)} />
</div>
</ConfigProvider>
);
}API Reference
Props
| Property | Description | Type | Default |
|---|---|---|---|
| autoAdjustOverflow | Whether to flip the popup automatically when it is clipped. | boolean | true |
| autoFocus | Focuses the input once mounted; passed through to the input's autoFocus. | boolean | - |
| borderless | Borderless mode. | boolean | false |
| className | Class name of the root element. | string | "" |
| clearIcon | Custom clear icon; effective when showClear is true. | React.ReactNode | - |
| defaultOpen | Whether the panel is open by default when uncontrolled. | boolean | - |
| defaultValue | Initial time when uncontrolled, in the same forms as value; an array when type is timeRange. | BaseValueType | BaseValueType[] | - |
| disabled | Disables all interaction. | boolean | - |
| disabledHours | Returns the hours that cannot be selected. | Type() => number[] | Type(): number[] => [] |
| disabledMinutes | Returns the minutes that cannot be selected for the selected hour. | Type(selectedHour: number) => number[] | Type(): number[] => [] |
| disabledSeconds | Returns the seconds that cannot be selected for the selected hour and minute. | Type(selectedHour: number, selectedMinute: number) => number[] | Type(): number[] => [] |
| disabledTime | Range mode only: returns the rules of each panel from value and panelType (left or right); value is an empty array with no value, length 1 with a single time, and undefined on the unpicked side. A returned disabledHours and the like overrides the top-level prop of the same name, one left out falls back to it, and a function returning [] switches off a top-level rule for that panel; ignored in single mode. | Type( value: Date[], panelType: PanelType ) => { disabledHours?: () => number[]; disabledMinutes?: (selectedHour: number) => number[]; disabledSeconds?: (selectedHour: number, selectedMinute: number) => number[]; } | - |
| focusOnOpen | Focuses the input and selects its content once mounted, which opens the panel. | boolean | false |
| format | Display format, following date-fns format. Defaults to a h:mm:ss with use12Hours, else HH:mm:ss. | string | - |
| hideDisabledOptions | Hides the options that cannot be selected. | boolean | false |
| hourStep | Interval of the hour options; a positive integer, 1 when unset. | number | - |
| id | id of the input. | string | - |
| inputReadOnly | Makes the input read-only, which avoids opening the virtual keyboard on mobile devices; the clear button stays usable. | boolean | false |
| inputStyle | Style of the input; an object with camelCase keys. | React.CSSProperties | - |
| insetLabel | Prefix label shown inside the input. | React.ReactNode | - |
| insetLabelId | id of the insetLabel, referenced through aria-labelledby and similar attributes. | string | - |
| minuteStep | Interval of the minute options; a positive integer, 1 when unset. | number | - |
| motion | Whether the popup animates. | boolean | true |
| onBlur | Callback when a click outside closes the panel, with the native event of that mousedown. | Type(e: MouseEvent) => void | - |
| onChange | Callback when the time changes. With type time it gets (Date, formatted string); with timeRange both are arrays. | Type((value: Date, str: string) => void) | ((value: Date[], str: string[]) => void) | - |
| onFocus | Callback when the input gains focus. | TypeReact.FocusEventHandler<HTMLDivElement> | - |
| onOpenChange | Callback when the panel opens or closes, with whether it is open. | Type(open: boolean) => void | - |
| open | Whether the panel is open; a controlled property, and undefined means uncontrolled. | boolean | - |
| panelFooter | Content below the panel. In range mode an array, whose item i is used for panel i. | React.ReactNode | React.ReactNode[] | - |
| panelHeader | Content above the panel. In range mode an array, whose item i is used for panel i; when unset, range mode shows the begin and end locale texts. | React.ReactNode | React.ReactNode[] | - |
| panels | Range mode only: item i is both the header and the footer of panel i, taking precedence over panelHeader and panelFooter. Ignored in single mode. | React.ReactNode[] | - |
| placeholder | Hint shown without a value; defaults to the locale text of type. | string | - |
| popupClassName | Class name of the popup. | string | "" |
| popupStyle | Style of the popup; an object with camelCase keys. | React.CSSProperties | - |
| position | Popup position. Unset, it is bottom for timeRange and bottomLeft for time; bottomRight under RTL. | Position | - |
| prefixCls | Prefix of the class names. | string | "semi-timepicker" |
| preventScroll | Whether focusing prevents the browser from scrolling the document; passed directly as the preventScroll option of focus(), for the focus calls inside the component. | boolean | - |
| rangeSeparator | Separator between the two times of a range. | string | " ~ " |
| ref | Reference to the component handle; its methods are listed under Methods. | TypeReact.Ref<TimePickerHandle> | - |
| scrollItemProps | Props passed to the columns; only cycled, mode, motion and transform, as on the ScrollItem of ScrollList. | TypePick<ScrollItemProps<any>, 'cycled' | 'mode' | 'motion' | 'transform'> | - |
| secondStep | Interval of the second options; a positive integer, 1 when unset. | number | - |
| showClear | Whether to show the clear button. | boolean | true |
| size | Size of the input: large, default or small. | InputSize | "default" |
| stopPropagation | Whether to stop click events on the popup from bubbling. | boolean | true |
| style | Style of the root element. | React.CSSProperties | {} |
| timeZone | Time zone: a number is the hour offset from UTC, a string is an IANA time zone name; defaults to the timeZone of ConfigProvider. | string | number | - |
| triggerRender | Renders a custom trigger. The argument has disabled, placeholder, value (an array of Date, the unpicked side undefined), inputValue, componentProps (the props of the TimePicker, without ref) and onChange (updates the input text, as typing would). | Type(props: TimePickerTriggerRenderProps) => React.ReactNode | - |
| type | Selection type: time for a single time, timeRange for a time range. | Type | "time" |
| use12Hours | Uses the 12-hour clock; with true, format defaults to a h:mm:ss. | boolean | false |
| validateStatus | Validation status, which only affects the display style. | ValidateStatus | - |
| value | Current time, as a Date, a timestamp or a string; an array when type is timeRange. null is a controlled empty value, and undefined means uncontrolled. | BaseValueType | BaseValueType[] | null | - |
Methods
| Method | Description | Type |
|---|---|---|
| blur | Removes focus from the input. | Type() => void |
| focus | Focuses the input, which opens the panel; preventScroll applies. | Type() => void |
Undeclared native attributes, such as title, data-*, aria-label and onKeyDown, land on the inner input, and prefix is shown as the input's prefix content; with a triggerRender custom trigger none of these land on any element, and they are available through componentProps.
With a custom trigger, focus() and blur() act on the first input inside the trigger, and do nothing when there is none.
Accessibility
ARIA
- The input has the role
comboboxwitharia-haspopup="dialog", anaria-expandedthat follows the panel, andaria-controlspointing at the panel - The hour, minute, second and AM/PM columns are
listboxlists named "Hour", "Minute", "Second" and "AM/PM"
Keyboard and Focus
- Focusing the input opens the panel; once it is open,
Down Arrowmoves focus into the first column - Each column is one Tab stop:
Up Arrow,Down Arrow,Home,Endand typed characters select its value Esccloses the panel; focus inside the panel returns to the input
Content Guidelines
- The time selector includes at least hours and minutes, such as: 11:30, which can be adapted to 12-hour or 24-hour format during localization
- When 12-hour clock is selected, it needs to be used together with AM/PM
Design Tokens
| Sass variable | Value | Usage |
|---|---|---|
| $color-timePicker_range_picker_panel_split-border | var(--semi-color-border) | 时间选择器菜单分割线颜色 |
| $color-timePicker_range_panel-border | rgba(0, 0, 0, 0.1) | 时间选择器描边颜色 |
| $width-timePicker_range_panel-border | 1px | 时间选择器菜单分割线宽度 |
| $height-timePicker_panel_body | 252px | 时间选择器菜单高度 |
| $width-timePicker_panel_list_ampm | 72px | 时间选择器菜单中列宽度 - 上午下午 |
| $width-timePicker_panel_list_hour | 64px | 时间选择器菜单中列宽度 - 小时 |
| $width-timePicker_panel_list_minute | 64px | 时间选择器菜单中列宽度 - 分钟 |
| $width-timePicker_panel_list_second | 64px | 时间选择器菜单中列宽度 - 秒 |
| $width-timePicker_range_panel_scrolllist_body-border | 2px | 时间范围选择器双排菜单中间分割线宽度 |
| $spacing-timePicker_range_panel_scrolllist_header_body-padding | 0 | 时间范围选择器菜单header与内容内边距 |
| $radius-timePicker_range_panel | var(--semi-border-radius-medium) | 时间范围选择器菜单圆角 |
| $radius-timePicker_input | var(--semi-border-radius-small) | 时间范围选择器圆角 |
| $shadow-timePicker_range_panel | var(--semi-shadow-elevated) | 时间范围选择器菜单阴影 |