Time picker
사용자가 특정 시간 및 시간의 범위를 지정 및 선택할 수 있도록 도움을 주는 요소입니다.
사용자가 YYYY. MM. DD순으로 날짜를 입력할 수 있는 폼을 제공합니다.
- locale, timezone을 지정할 수 있습니다.
- 기본적으로 TextField 컴포넌트를 사용합니다.
- 항상 유효한 Date 값을 가지고 있지는 않습니다. Invalid date 상태를 가질 수 있습니다.
import { TimePicker } from '@wanteddev/wds';
const Demo = () => {
return (
<TimePicker width="40%" />
)
}
export default Demo;input에 시간이 표시되는 format 을 지정할 수 있습니다. 아래 format을 모두 사용할 수 있습니다.
- H, HH, h, hh
- m, mm
- s, ss
- A, a
- YYYY, YY
- M, MM, MMM, MMMM
- D, DD
12시간 형식일 경우 a 또는 A와 h 또는 hh를 함께 사용해야하며
24시간 형식일 경우 H 또는 HH만 사용합니다.
import { TimePicker, FlexBox } from '@wanteddev/wds';
const Demo = () => {
return (
<FlexBox flexDirection="column" alignItems="center" gap="20px" sx={{ width: '100%' }}>
<TimePicker width="40%" format="a hh:mm:ss" />
<TimePicker width="40%" format="a h:m:s" />
<TimePicker width="40%" format="HH:mm:ss" />
<TimePicker width="40%" format="H:m:s" />
<TimePicker width="40%" format="mm:ss" />
<TimePicker width="40%" format="m:s" />
</FlexBox>
)
}
export default Demo;- Locale
- 기본적으로 locale은
ko-KR으로 지정되어 있습니다. - Intl API 에서 지원하는 언어를 모두 import 없이 사용할 수 있습니다.
- 기본적으로 locale은
- Timezone
- 기본적으로 timezone은 사용자의 환경에 따라 결정됩니다.
- dayjs 에서 지원하는 timezone과
UTC를 모두 import 없이 사용할 수 있습니다.
import { TimePicker, FlexBox } from '@wanteddev/wds';
const Demo = () => {
return (
<FlexBox flexDirection="column" alignItems="center" gap="20px" sx={{ width: '100%' }}>
<TimePicker width="40%" defaultValue={new Date()} locale="ko-KR" timezone="Asia/Seoul" />
<TimePicker width="40%" defaultValue={new Date()} locale="en-US" timezone="UTC" />
</FlexBox>
)
}
export default Demo;views, defaultView, view, onViewChange 로 선택 UI를 조정할 수 있습니다.
'meridiem' | 'hour' | 'minute' | 'second' 를 지원합니다.
import { TimePicker, FlexBox } from '@wanteddev/wds';
const Demo = () => {
return (
<FlexBox flexDirection="column" alignItems="center" gap="20px" sx={{ width: '100%' }}>
<TimePicker
width="40%"
format="mm:ss"
views={['minute', 'second']}
/>
<TimePicker
width="40%"
format="hh a"
views={['hour', 'meridiem']}
/>
</FlexBox>
)
}
export default Demo;PickerActionArea 를 사용하여 하단 영역의 버튼을 커스텀 할 수 있습니다.
총 4가지 variant를 사용할 수 있습니다.
- now
- accept
- cancel
- reset
Checkbox 컴포넌트와 함께 사용할 때에는 disableLastUnitClickClose prop 을 사용하여 더욱 자연스러운 동작을 구현할 수 있
import { TimePicker, FlexBox, PickerActionArea, PickerActionAreaButton, FormField, FormControl, FormLabel, Checkbox } from '@wanteddev/wds';
const Demo = () => {
return (
<FlexBox flexDirection="column" alignItems="center" gap="20px" sx={{ width: '100%' }}>
<TimePicker
width="40%"
placeholder="현재, 확인"
actionArea={
<PickerActionArea>
<PickerActionAreaButton variant="now">현재</PickerActionAreaButton>
<PickerActionAreaButton variant="accept">확인</PickerActionAreaButton>
</PickerActionArea>
}
/>
<TimePicker
width="40%"
placeholder="취소, 초기화"
actionArea={
<PickerActionArea>
<PickerActionAreaButton variant="cancel">취소</PickerActionAreaButton>
<PickerActionAreaButton variant="reset">초기화</PickerActionAreaButton>
</PickerActionArea>
}
/>
<TimePicker
width="40%"
placeholder="checkbox, 확인"
disableLastUnitClickClose
actionArea={
<PickerActionArea>
<FormField
gap="8px"
flexDirection="row"
>
<FormControl>
<Checkbox size="medium" />
</FormControl>
<FormLabel
sx={{ padding: "1px 0px" }}
>
텍스트
</FormLabel>
</FormField>
<PickerActionAreaButton variant="accept">확인</PickerActionAreaButton>
</PickerActionArea>
}
/>
</FlexBox>
)
}
export default Demo;min,maxprop 을 사용하여 최소값과 최대값을 설정할 수 있습니다.- 키보드 조작을 통해서는 범위를 벗어나는 값을 입력할 수 있습니다.
- Invalid date 상태를 가질 수 있습니다.
import { TimePicker, FlexBox, FormErrorMessage, FormField, FormLabel, FormControl } from '@wanteddev/wds';
import { Controller, useForm } from 'react-hook-form';
const minTime = new Date(new Date().setHours(10, 0, 0));
const maxTime = new Date(new Date().setHours(17, 30, 0));
const Demo = () => {
const form = useForm({
defaultValues: {
time: new Date(),
},
mode: 'onChange'
});
return (
<FlexBox as="form" justifyContent="center" gap="20px" sx={{ width: '100%' }}>
<Controller
control={form.control}
name="time"
rules={{
validate: (value) => {
if (isNaN(new Date(value).getTime())) {
return '유효한 날짜를 입력해주세요.';
}
if (new Date(value).getTime() < minTime.getTime()) {
return '최소 시간은 10시 이상이어야 합니다.';
}
if (new Date(value).getTime() > maxTime.getTime()) {
return '최대 시간은 17시 30분 이하이어야 합니다.';
}
return true;
},
}}
render={({ field, formState }) => (
<FormField sx={{ width: '40%' }}>
<FormLabel>시간</FormLabel>
<FormControl>
<TimePicker
width="100%"
format="HH시 mm분"
minTime={minTime}
maxTime={maxTime}
inputRef={field.ref}
value={field.value}
onChange={field.onChange}
invalid={!!formState.errors.time}
/>
</FormControl>
<FormErrorMessage>{formState.errors.time?.message}</FormErrorMessage>
</FormField>
)}
/>
</FlexBox>
)
}
export default Demo;Form과 관련된 컴포넌트와 함께 사용할 수 있습니다.
FormFieldFormControlFormLabelFormMessageFormErrorMessage
import { FlexBox, FormField, FormControl, FormLabel, FormMessage, FormErrorMessage, TimePicker } from '@wanteddev/wds';
const Demo = () => {
return (
<FlexBox justifyContent="center" sx={{ width: '100%' }}>
<FormField sx={{ width: '40%' }}>
<FormLabel required sx={{ padding: '1px 0px' }}>Label</FormLabel>
<FormControl>
<TimePicker width="100%" />
</FormControl>
<FormMessage>Helper Message</FormMessage>
</FormField>
</FlexBox>
)
}
export default Demo;TextField 컴포넌트 대신 커스텀 컴포넌트를 사용할 수 있습니다.
react 18.3 미만의 버전을 사용 중이라면,
forwardRef를 필수로 작성해주세요.
import { TimePicker, TimePickerFieldProps, Chip, FlexBox } from '@wanteddev/wds';
import { forwardRef, useState } from 'react';
const CustomChipField = forwardRef<HTMLDivElement, TimePickerFieldProps>(
({ value, onClick, inputRef, invalid, ...props }, ref) => {
return (
<Chip ref={ref} onClick={onClick}>
{value || 'YYYY.MM.DD'}
</Chip>
)
}
)
const CustomFieldField = forwardRef<HTMLDivElement, TimePickerFieldProps>(
({ trailingContent, inputRef, invalid, ...props }, ref) => {
return (
<FlexBox ref={ref} gap="10px" alignItems="center">
<input ref={inputRef} {...props} />
{trailingContent}
</FlexBox>
)
}
)
const Demo = () => {
const [open1, setOpen1] = useState(false);
const [open2, setOpen2] = useState(false);
return (
<FlexBox flexDirection="column" gap="12px" alignItems="center" sx={{ width: '100%' }}>
<TimePicker
width="40%"
input={CustomChipField}
open={open1}
onOpenChange={setOpen1}
onClick={() => setOpen1(true)}
/>
<TimePicker
width="40%"
input={CustomFieldField}
open={open2}
onOpenChange={setOpen2}
/>
</FlexBox>
)
}
export default Demo;기본적으로 비제어 컴포넌트로 동작합니다.
value, onChange prop 을 사용하면 제어 컴포넌트로 동작합니다.
제어 컴포넌트와 비제어 컴포넌트는 React 공식 문서 를 참조해주세요.
import { TimePicker, FlexBox } from '@wanteddev/wds';
import { useState } from 'react';
const Demo = () => {
const [value, setValue] = useState(new Date());
return (
<FlexBox alignItems="center" flexDirection="column" gap="12px" alignItems="center" sx={{ width: '100%' }}>
<TimePicker defaultValue={new Date()} width="40%" />
<TimePicker value={value} onChange={setValue} width="40%" />
</FlexBox>
)
}
export default Demo;WAI-ARIA Datepicker dialog 패턴 대부분을 지원합니다.
- Form Field 와 함께 사용할 때 더욱 명확한 접근성 속성을 주입할 수 있습니다.
