본문으로 건너뛰기
Amineslab UI

Component

DateRangePicker

시작·종료 날짜와 시간을 함께 관리하는 기간 입력입니다.

Playground

옵션을 조절하며 화면과 사용 코드를 함께 확인하세요.

PC 1280px
Controls

트리거 높이와 여백

비어 있을 때 안내 문구

showTime을 켜면 시간 표시 형식에 적용됩니다.

오류 상태

Code
import { useState } from 'react'

import { DateRangePicker, type ControlSize } from '@amineslab/ui'

function RangeExample({ size = 'md', placeholder = '기간 선택', opaque = false, variant = 'filled', showTime = false, hourCycle = '24', inline = false, numberOfMonths = '1', disabled = false, invalid = false, }) {
    const [value, setValue] = useState({ from: '', to: '' });
    return (<div className="grid w-full gap-3">
      <DateRangePicker size={size as ControlSize} placeholder={placeholder} opaque={opaque} variant={variant === 'outline' ? 'outline' : 'filled'} value={value} onValueChange={setValue} showTime={showTime} hourCycle={hourCycle === '12' ? 12 : 24} inline={inline} numberOfMonths={numberOfMonths === '2' ? 2 : 1} disabled={disabled} invalid={invalid} aria-label="조회 기간"/>
    </div>);
}

export default function ExamplePreview() {
  return (<RangeExample {...({"size":"md","placeholder":"기간 선택","opaque":false,"variant":"filled","showTime":false,"hourCycle":"24","inline":false,"numberOfMonths":"1","disabled":false,"invalid":false} as const)}/>)
}

Props

@amineslab/ui에서 DateRangePicker를 가져옵니다.

import { DateRangePicker } from '@amineslab/ui'

DateRangePicker

NameTypeDefaultDescription
size'xs' | 'sm' | 'md' | 'lg' | 'xl''md'Button과 같은 트리거 높이·여백입니다. 모바일은 높이에 8px을 더합니다.
value*{ from: string; to: string }-YYYY-MM-DD 또는 YYYY-MM-DDTHH:mm. 미선택 끝점은 빈 문자열입니다.
onValueChange*(range: DateRange) => void-시작·종료 변경값을 전달합니다. 외부에서 값을 교체하면 시간 표시도 동기화합니다.
showTimebooleanfalse시작·종료 TimeInput 인라인 선택을 균등한 두 열에 표시합니다.
numberOfMonths1 | 21PC Popover에서 나란히 표시할 월 수. 모바일과 인라인은 한 달입니다.
inlinebooleanfalse트리거·오버레이 없이 달력을 직접 표시합니다.
aria-label / aria-labelledbystring-인라인 달력 그룹의 접근 가능한 이름입니다.
hourCycle12 | 2424시간 표시 형식. 12시간제는 오전/오후와 01~12, 24시간제는 00~23을 표시합니다. value/onChange의 시간은 항상 24시간 HH:mm입니다.
placeholderstring-미선택 트리거 문구이자 모바일 시트의 제목입니다.
disabledbooleanfalse트리거를 비활성화합니다.
invalidbooleanfalse오류 테두리와 aria-invalid를 적용합니다.
variant'filled' | 'outline''filled'입력 표면을 선택합니다.
id / classNamestring-트리거 식별자와 스타일을 전달합니다. 인라인 기간 선택에서는 그룹에 적용합니다.
aria-describedby / aria-invalidstring / AriaAttributes["aria-invalid"]-폼 설명·오류 메시지와 실제 트리거를 연결합니다.
aria-requiredAriaAttributes["aria-required"]-필수 입력 상태를 실제 트리거에 전달합니다.
onBlurFocusEventHandler<HTMLButtonElement>-트리거가 포커스를 잃을 때 호출합니다. RHF touched 처리에 사용합니다.
opaquebooleanfalseelevation 레이어 아래 불투명한 테마 바탕을 추가합니다. hover·focus·invalid 표현은 유지합니다.

Examples

자주 쓰는 조합을 살펴보고, 필요한 예시의 코드를 펼쳐 확인하세요.

공통 필드 표면

variant는 filled·outline 표현을, opaque는 elevation 아래의 불투명 바탕을 정합니다. focus와 hover는 중립 elevation을 사용하고 invalid 테두리는 포커스 중에도 유지합니다. NumberInput·PhoneInput·PasswordInput은 Input의 아이콘·문자열·ReactNode 슬롯을 상속합니다. SelectField에서는 같은 표면 props를 직접 지정하거나 triggerProps로 세부 설정할 수 있습니다.

투명 바탕
불투명 바탕
Outline + 불투명 바탕
<DateRangePicker value={range} onValueChange={setRange} />

<DateRangePicker value={range} onValueChange={setRange} opaque />

<DateRangePicker value={range} onValueChange={setRange} variant="outline" opaque />

기간 프리셋

이번 달·지난 달·올해·전체를 같은 날짜 계약으로 적용합니다. matchDateRangePreset으로 현재 범위의 프리셋도 판정할 수 있습니다.

import { useState } from 'react'

import { Button, resolveDateRangePreset, DateRangePicker } from '@amineslab/ui'

function PresetRangeExample() {
    const [range, setRange] = useState({ from: '', to: '' });
    return (<div className="grid w-full gap-3">
      <div className="flex flex-wrap gap-2">
        <Button variant="outline" onClick={() => setRange(resolveDateRangePreset('thisMonth'))}>
          이번 달
        </Button>
        <Button variant="outline" onClick={() => setRange(resolveDateRangePreset('lastMonth'))}>
          지난 달
        </Button>
        <Button variant="outline" onClick={() => setRange(resolveDateRangePreset('all'))}>
          전체
        </Button>
      </div>
      <DateRangePicker value={range} onValueChange={setRange}/>
    </div>);
}

export default function ExamplePreview() {
  return (<PresetRangeExample />)
}

PC 두 달 · 모바일 한 달

넓은 Popover는 두 달을 나란히 보여주고, 모바일 시트는 한 달로 줄입니다. 시작·종료 시간은 HH:mm 입력으로 각각 편집합니다.

import { useState } from 'react'

import { DateRangePicker, type ControlSize } from '@amineslab/ui'

function RangeExample({ size = 'md', placeholder = '기간 선택', opaque = false, variant = 'filled', showTime = false, hourCycle = '24', inline = false, numberOfMonths = '1', disabled = false, invalid = false, }) {
    const [value, setValue] = useState({ from: '', to: '' });
    return (<div className="grid w-full gap-3">
      <DateRangePicker size={size as ControlSize} placeholder={placeholder} opaque={opaque} variant={variant === 'outline' ? 'outline' : 'filled'} value={value} onValueChange={setValue} showTime={showTime} hourCycle={hourCycle === '12' ? 12 : 24} inline={inline} numberOfMonths={numberOfMonths === '2' ? 2 : 1} disabled={disabled} invalid={invalid} aria-label="조회 기간"/>
    </div>);
}

export default function ExamplePreview() {
  return (<RangeExample numberOfMonths="2" showTime/>)
}

인라인 달력

오버레이 없이 폼에 달력을 직접 배치합니다. 접근 가능한 그룹 이름을 제공합니다.

import { useState } from 'react'

import { DateRangePicker, type ControlSize } from '@amineslab/ui'

function RangeExample({ size = 'md', placeholder = '기간 선택', opaque = false, variant = 'filled', showTime = false, hourCycle = '24', inline = false, numberOfMonths = '1', disabled = false, invalid = false, }) {
    const [value, setValue] = useState({ from: '', to: '' });
    return (<div className="grid w-full gap-3">
      <DateRangePicker size={size as ControlSize} placeholder={placeholder} opaque={opaque} variant={variant === 'outline' ? 'outline' : 'filled'} value={value} onValueChange={setValue} showTime={showTime} hourCycle={hourCycle === '12' ? 12 : 24} inline={inline} numberOfMonths={numberOfMonths === '2' ? 2 : 1} disabled={disabled} invalid={invalid} aria-label="조회 기간"/>
    </div>);
}

export default function ExamplePreview() {
  return (<RangeExample inline/>)
}

DateRangeField로 사용하기

DateRangeField는 기본 입력에 label·required·description·error를 함께 제공합니다. FormStack 안에 직접 넣으며 FormField로 다시 감싸지 않습니다.

라벨·설명·필수 표시를 Field가 함께 처리합니다.

import { useState } from 'react'

import { type DateRange, DateRangeField } from '@amineslab/ui'

const fieldDescription = '라벨·설명·필수 표시를 Field가 함께 처리합니다.';

function DateRangeFieldExample() {
    const [value, setValue] = useState<DateRange>({ from: '', to: '' });
    return (<DateRangeField label="기간" description={fieldDescription} required value={value} onValueChange={setValue}/>);
}

export default function ExamplePreview() {
  return (<DateRangeFieldExample />)
}

사용 기준

권장하는 사용
  • PC는 1·2개월 Popover, 모바일은 한 달 Bottomsheet입니다.
  • 기간 선택은 즉시 반영합니다.
  • 시작·종료의 업무 규칙과 시간까지 포함한 역전 검증은 소비 폼에서 처리합니다.
피해야 할 사용
  • 겉모양만으로 사용을 결정하지 마세요.
  • 의미와 키보드 동작, 모바일에서의 흐름을 함께 확인하세요.

접근성

화면에 맞는 이름을 제공하고, 키보드만으로 작업을 마칠 수 있는지 확인하세요.

이 컴포넌트에는 별도의 키보드 조작이 필요하지 않습니다.