Demos
How to import
<script setup lang="ts">
import { TimePicker } from '@fibrous/semi-ui-vue';
</script>
Basic Usage
Click TimePicker, and then you can select or enter a time in the floating layer.
Code
<script setup lang="ts">
import { TimePicker } from '@fibrous/semi-ui-vue';
</script>
<template>
<TimePicker />
</template>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
<script setup lang="ts">
import { TimePicker } from '@fibrous/semi-ui-vue';
</script>
<template>
<TimePicker :scrollItemProps="{ mode: 'wheel', cycled: true }" />
</template>Controlled Component
Use v-model as a controlled component, and defaultValue for the initial value. null is a controlled empty value and undefined means uncontrolled; when a controlled value goes back to undefined the input is cleared and the picker becomes uncontrolled. After clearing, v-model receives undefined (single) or an empty array (range).
Code
<script setup lang="ts">
import { ref } from 'vue';
import { TimePicker } from '@fibrous/semi-ui-vue';
const value = ref<Date | (Date | undefined)[] | null | undefined>(null);
const onChange = (time: unknown) => console.log(time);
</script>
<template>
<TimePicker v-model="value" @change="onChange" />
</template>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
<script setup lang="ts">
import { TimePicker } from '@fibrous/semi-ui-vue';
</script>
<template>
<TimePicker defaultValue="10:24" format="HH:mm" />
</template>Set Panel Header and Footer
Disable Time Selection
Code
<script setup lang="ts">
import { TimePicker } from '@fibrous/semi-ui-vue';
</script>
<template>
<TimePicker defaultValue="12:08:23" disabled />
</template>Set Step Length
Available Hour Step, Minute Step, Second Step Show the optional minutes and seconds by step.
Code
<script setup lang="ts">
import { TimePicker } from '@fibrous/semi-ui-vue';
</script>
<template>
<TimePicker :minuteStep="15" :secondStep="10" />
</template>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
<script setup lang="ts">
import { TimePicker } from '@fibrous/semi-ui-vue';
</script>
<template>
<div>
<TimePicker use12Hours />
<br />
<br />
<TimePicker format="a h:mm" use12Hours />
</div>
</template>Time Range
Pass type = "timeRange" to enable time range selection.
Code
<script setup lang="ts">
import { TimePicker } from '@fibrous/semi-ui-vue';
</script>
<template>
<div>
<TimePicker :defaultValue="['10:23:15', '12:38:32']" type="timeRange" />
<br />
<br />
<TimePicker :defaultValue="['上午 08:11', '下午 11:21']" format="a h:mm" type="timeRange" use12Hours />
</div>
</template>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
<script setup lang="ts">
import { TimePicker } from '@fibrous/semi-ui-vue';
const range = (length: number) => Array.from({ length }, (_, i) => i);
// The right panel disables everything earlier than the start time picked on the left
const disabledTime = (value: (Date | undefined)[], panelType: 'left' | 'right') => {
const start = value[0];
if (panelType === 'right' && start) {
const h = start.getHours();
const m = start.getMinutes();
return {
disabledHours: () => range(h),
disabledMinutes: (hour: number) => (hour === h ? range(m) : []),
};
}
return {};
};
</script>
<template>
<TimePicker :disabledTime="disabledTime" type="timeRange" />
</template>Custom Trigger
By default we use the Input component as the trigger for the TimePicker component. You can customize this trigger with the #trigger scoped slot, whose parameters are { value, inputValue, placeholder, disabled, componentProps, onChange }. The unpicked side of value is undefined, and onChange updates the input text as typing would.
Code
<script setup lang="ts">
import { ref } from 'vue';
import * as dateFns from 'date-fns';
import { IconTimePicker } from '@fibrous/semi-icons-vue/lab';
import { Tag, TimePicker } from '@fibrous/semi-ui-vue';
const formatToken = 'HH:mm:ss';
const time = ref<Date | (Date | undefined)[] | undefined>(new Date(2024, 0, 1, 10, 30, 0));
</script>
<template>
<TimePicker v-model="time" :format="formatToken">
<template #trigger="{ placeholder }">
<Tag color="cyan" shape="circle" size="large" :style="{ padding: '12px', paddingRight: '16px', fontSize: '14px' }" type="light">
<template #prefixIcon>
<IconTimePicker />
</template>
{{ time instanceof Date ? dateFns.format(time, formatToken) : placeholder }}
</Tag>
</template>
</TimePicker>
</template>TimeZone Config
Semi All configuration about time zone is converged in ConfigProvider
Select Time Zone:
TimePicker:
Code
<script setup lang="ts">
import { ref } from 'vue';
import { ConfigProvider, Select, TimePicker } from '@fibrous/semi-ui-vue';
const timeZone = ref('GMT+08:00');
const defaultTimestamp = 1581599305265;
const gmtList: string[] = [];
for (let hourOffset = -11; hourOffset <= 14; hourOffset++) {
const prefix = hourOffset >= 0 ? '+' : '-';
gmtList.push(`GMT${prefix}${String(Math.abs(hourOffset)).padStart(2, '0')}:00`);
}
const onChange = (date: unknown, dateString: string | string[]) => console.log('DatePicker changed: ', date, dateString);
</script>
<template>
<ConfigProvider :timeZone="timeZone">
<div :style="{ width: '300px' }">
<h5 :style="{ margin: '10px' }">Select Time Zone:</h5>
<Select aria-label="时区" :modelValue="timeZone" placeholder="请选择时区" showClear :style="{ width: '300px' }" @select="timeZone = String($event)">
<Select.Option v-for="gmt in gmtList" :key="gmt" :value="gmt">{{ gmt }}</Select.Option>
</Select>
<br />
<br />
<h5 :style="{ margin: '10px' }">TimePicker:</h5>
<TimePicker :defaultValue="defaultTimestamp" @change="onChange" />
</div>
</ConfigProvider>
</template>API Reference
Props
| Property | Description | Type | Default |
|---|---|---|---|
| modelValue | Current time, used with v-model; an array when type is timeRange. null is a controlled empty value, and undefined means uncontrolled. | TimePickerValue | (TimePickerValue | undefined)[] | null | undefined |
| defaultValue | Initial time when uncontrolled, in the same forms as modelValue. | TimePickerValue | (TimePickerValue | undefined)[] | semiGlobalDefault("TimePicker", "defaultValue") |
| open | Whether the panel is open, used with v-model:open; undefined means uncontrolled. | boolean | undefined |
| defaultOpen | Whether the panel is open by default when uncontrolled. | boolean | semiDefault("TimePicker", "defaultOpen", false) |
| type | Selection type: time for a single time, timeRange for a range. | TimePickerType | semiDefault("TimePicker", "type", strings.DEFAULT_TYPE) |
| format | Display format, following date-fns format. Defaults to a h:mm:ss with use12Hours, else HH:mm:ss. | string | semiGlobalDefault("TimePicker", "format") |
| use12Hours | Uses the 12-hour clock. | boolean | semiDefault("TimePicker", "use12Hours", false) |
| hourStep | Interval of the hour options; a positive integer. | number | semiGlobalDefault("TimePicker", "hourStep") |
| minuteStep | Interval of the minute options; a positive integer. | number | semiGlobalDefault("TimePicker", "minuteStep") |
| secondStep | Interval of the second options; a positive integer. | number | semiGlobalDefault("TimePicker", "secondStep") |
| disabled | Disables all interaction. | boolean | semiDefault("TimePicker", "disabled", false) |
| disabledHours | Returns the hours that cannot be selected. | Type(() => number[]) | undefined |
| disabledMinutes | Returns the minutes that cannot be selected for the selected hour. | Type((selectedHour: number) => number[]) | undefined |
| disabledSeconds | Returns the seconds that cannot be selected for the selected hour and minute. | Type((selectedHour: number, selectedMinute: number) => number[]) | undefined |
| disabledTime | Range mode only: returns the disabled rules of the left and right panel from the current value and the panel. The unpicked side of value is undefined; a returned disabledHours, disabledMinutes or disabledSeconds overrides the prop of the same name, and one left out falls back to it. | Type((value: (Date | undefined)[], panelType: PanelType) => DisabledTimeFns) | undefined |
| hideDisabledOptions | Hides the options that cannot be selected. | boolean | semiDefault("TimePicker", "hideDisabledOptions", false) |
| placeholder | Hint shown without a value; defaults to the locale text of type. | string | semiGlobalDefault("TimePicker", "placeholder") |
| rangeSeparator | Separator between the two times of a range. | string | TypesemiDefault("TimePicker", "rangeSeparator", strings.DEFAULT_RANGE_SEPARATOR) |
| size | Size of the input. | Size | semiDefault("TimePicker", "size", "default") |
| borderless | Borderless mode. | boolean | semiDefault("TimePicker", "borderless", false) |
| showClear | Whether to show the clear button. | boolean | semiDefault("TimePicker", "showClear", true) |
| inputReadOnly | Makes the input read-only, which avoids opening the virtual keyboard on mobile devices. | boolean | semiDefault("TimePicker", "inputReadOnly", false) |
| validateStatus | Validation status. | "default" | "error" | "warning" | "success" | semiGlobalDefault("TimePicker", "validateStatus") |
| insetLabelId | id of the insetLabel, referenced through aria-labelledby. | string | undefined |
| inputStyle | Style of the input's root element. | StyleValue | semiGlobalDefault("TimePicker", "inputStyle") |
| autofocus | Focuses the input on mount, which opens the panel. | boolean | semiDefault("TimePicker", "autofocus", false) |
| focusOnOpen | Focuses the input and selects its content once mounted, which opens the panel. | boolean | semiDefault("TimePicker", "focusOnOpen", false) |
| preventScroll | Whether the browser should scroll the document to show the newly focused element; applies to the focus call inside the component. | boolean | semiGlobalDefault("TimePicker", "preventScroll") |
| motion | Whether the popup animates. | boolean | semiDefault("TimePicker", "motion", true) |
| autoAdjustOverflow | Whether to flip the popup automatically when it is clipped. | boolean | semiDefault("TimePicker", "autoAdjustOverflow", true) |
| position | Popup position. Defaults to bottom when type is timeRange, and bottomLeft when it is time. | Type"top" | "bottom" | "left" | "right" | "topLeft" | "topRight" | "leftTop" | "leftBottom" | "rightTop" | "rightBottom" | "bottomLeft" | "bottomRight" | "leftTopOver" | "rightTopOver" | "leftBottomOver" | "rightBottomOver" | semiGlobalDefault("TimePicker", "position") |
| popupClassName | Class name of the popup. | string | semiGlobalDefault("TimePicker", "popupClassName") |
| popupStyle | Style of the popup. | StyleValue | semiGlobalDefault("TimePicker", "popupStyle") |
| stopPropagation | Whether to stop click events on the popup from bubbling. | boolean | semiDefault("TimePicker", "stopPropagation", true) |
| timeZone | Time zone; falls back to the timeZone of ConfigProvider, then to the global default. | string | number | undefined |
| scrollItemProps | Props passed to the columns; only cycled, mode, motion and transform, as on the ScrollItem of ScrollList. | TimePickerScrollItemProps | semiGlobalDefault("TimePicker", "scrollItemProps") |
Events
| Event | Description | Callback parameters |
|---|---|---|
| update:modelValue | Emitted when the time changes, for v-model to write back. Cleared, it is undefined (single) or an empty array (range); the unpicked side of a range is undefined. | [value: Date | (Date | undefined)[] | undefined] |
| change | Emitted when the time changes, with (Date value, formatted string); both are arrays in range mode. | Type[value: Date | (Date | undefined)[] | undefined, str: string | string[]] |
| update:open | Emitted when the panel opens or closes, for v-model:open to write back. | [open: boolean] |
| openChange | Emitted when the panel opens or closes. | [open: boolean] |
| focus | Emitted when the input's root element gains focus; moving focus between the input and the clear button does not emit it. | [event: FocusEvent] |
| blur | Emitted when a click outside closes the panel, with the native event of that mousedown; leaving the input does not emit it. | [event: MouseEvent] |
Slots
| Slot | Description | Scope parameters |
|---|---|---|
| trigger | Custom trigger that replaces the default input; a click anywhere in it opens the panel. Receives value (the unpicked side undefined), inputValue, placeholder, disabled, componentProps and onChange (updates the input text, as typing would). | TimePickerTriggerSlotProps |
| panelHeader | Content above the panel; index is the panel's position (0 for time, 0 or 1 for timeRange). Without it, a range shows the locale's start and end text. | TimePickerPanelSlotProps |
| panelFooter | Content below the panel; index is the panel's position. | TimePickerPanelSlotProps |
| panel | Range mode only: used as both the header and the footer of panel index, taking precedence over panelHeader and panelFooter while it has content. | TimePickerPanelSlotProps |
| prefix | Prefix content of the input. | any |
| insetLabel | Inset label of the input. | any |
| clearIcon | Custom clear icon; effective when showClear is true. | any |
Exposes
| Name | Description | Type |
|---|---|---|
| focus | Focuses the input, which opens the panel; does nothing with a custom trigger. | Type() => void |
| blur | Removes focus from the input; does nothing with a custom trigger. | Type() => void |
Among undeclared attributes, class and style land on the root element, and the rest (id, title, aria-*, data-*, event listeners and so on) land on the inner input; with a custom #trigger all of them land on the root element, whose role is group when aria-label or aria-labelledby is passed. focus and blur are declared component events, so @focus and @blur receive only the component events, not the native events bubbling up.
focus() and blur() are available through a ref and do nothing with a custom trigger.
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) | 时间范围选择器菜单阴影 |