본문으로 건너뛰기

PlCalendar

popup 안이 아니라 페이지 위의 한 달입니다. PlDatePicker가 여는 바로 그 grid에서 trigger와 popup을 걷어낸 것입니다.

React
tsx
import { PlCalendar } from 'plass-ui';

<PlCalendar value={day} onValueChange={setDay} />;
dart
import 'package:plass_ui/plass_ui.dart';

PlCalendar(
  value: day,
  onChanged: (DateTime? next) => setState(() => day = next),
);

Props

Prop타입기본값설명
variant공통'solid' | 'glass' | 'ghost''glass'시트의 재질. 이미 시트를 그리는 것 안에 넣는다면 ghost
size공통'xs' | 'sm' | 'md' | 'lg' | 'xl''md'셀 · 반경 · 타입 스케일이 함께 움직입니다. density는 없습니다
color공통'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info''primary'고른 날, 오늘 표시, focus ring이 쓰는 색 역할
elevation공통0 | 1 | 2 | 31그림자 깊이. 0은 그림자 없음
valueDate | null고른 날. 제어하려면 onValueChange와 함께
defaultValueDate | null제어하지 않을 때 시작하는 날
onValueChange(value: Date | null) => void날이 골렸을 때
precision'day' | 'month' | 'year''day'되돌려주는 가장 작은 단위. 시작 화면이 아니라 바닥이며, 값은 그 단위의 시작으로 정규화됩니다
monthDate화면에 있는 달. onMonthChange와 함께 쓰면 제어됩니다
defaultMonthDate처음 보여 줄 달. 기본은 값의 달, 값이 없으면 이번 달
onMonthChange(month: Date) => void화면의 달이 바뀌었을 때
minDateDate | null이 날 이전은 고를 수 없습니다. calendar의 precision으로 읽습니다
maxDateDate | null이 날 이후는 고를 수 없습니다. calendar의 precision으로 읽습니다
shouldDisableDate(date: Date) => boolean개별 날짜를 막습니다 — 주말, 공휴일, 이미 찬 날. 일 단위라 month/year에서는 참조하지 않습니다
localestring월 이름 · 요일 머리글자 · 주의 첫날이 나오는 BCP 47 태그. 기본은 페이지의 로케일
weekStartsOn0 | 1 | 2 | 3 | 4 | 5 | 6주가 시작하는 요일. Date가 세는 방식이라 일요일이 0입니다. 없으면 locale에서 정합니다
showOutsideDaysbooleantrue이웃한 달에 속한 앞뒤 날들을 그립니다
autoFocusbooleanfalse마운트할 때 focus를 가져갑니다. 페이지 안의 calendar는 popup이 아니므로 기본은 꺼짐
disabledbooleanfalse전체를 흐리게 하고 inert로 탭 순서에서 뺍니다. readOnly는 없습니다
namestring폼과 함께 제출합니다. 표기는 precision을 따릅니다 — YYYY-MM-DD, YYYY-MM, YYYY
labelsPartial<PlPickerLabels>Intl이 의견을 갖지 않는 문자열들 — 버튼과 제목
Prop타입기본값설명
value * DateTime?고른 날, 또는 없으면 null. 패키지의 다른 모든 입력과 마찬가지로 controlled입니다
onChangedValueChanged<DateTime?>?고른 날과 함께 호출됩니다. null이면 calendar가 비활성입니다
precisionPlCalendarPrecisionPlCalendarPrecision.day되돌려주는 가장 작은 단위. 시작 화면이 아니라 바닥이며, 값은 그 단위의 시작으로 정규화됩니다
monthDateTime?화면에 있는 달. onMonthChange와 함께 쓰면 제어됩니다
defaultMonthDateTime?처음 보여 줄 달. 기본은 값의 달, 값이 없으면 이번 달
onMonthChangedValueChanged<DateTime>?화면의 달이 바뀌었을 때
minDateDateTime?이 날 이전은 고를 수 없습니다. calendar의 precision으로 읽습니다
maxDateDateTime?이 날 이후는 고를 수 없습니다. calendar의 precision으로 읽습니다
shouldDisableDatebool Function(DateTime)?개별 날짜를 막습니다 — 주말, 공휴일, 이미 찬 날. 일 단위라 month/year에서는 참조하지 않습니다
weekStartsOnPlassWeekday?주가 시작하는 요일. Date가 세는 방식이라 일요일이 0입니다. 없으면 locale에서 정합니다
namesPlDateNamesPlDateNames.englishcalendar가 그리는 말들 — 월, 요일. React의 locale 문자열에 해당합니다
labelsPlPickerLabelsPlPickerLabels.englishcalendar가 자기 자신에 대해 말하는 것 — 스테퍼, 제목
showOutsideDaysbooltrue이웃한 달에 속한 앞뒤 날들을 그립니다
autofocusboolfalse마운트할 때 focus를 가져갑니다. 페이지 안의 calendar는 popup이 아니므로 기본은 꺼짐
disabledboolfalse전체를 흐리게 하고 inert로 탭 순서에서 뺍니다. readOnly는 없습니다
variant공통PlassVariantPlassVariant.glass시트의 재질. 이미 시트를 그리는 것 안에 넣는다면 ghost
size공통PlassSizePlassSize.md셀 · 반경 · 타입 스케일이 함께 움직입니다. density는 없습니다
color공통PlassColorPlassColor.primary고른 날, 오늘 표시, focus ring이 쓰는 색 역할
elevation공통int1그림자 깊이. 0은 그림자 없음
semanticLabelString?스크린 리더가 grid 전체에 주는 이름

네이티브 <div> 속성은 그대로 통과합니다. labeldescriptionerror도 없습니다. 이것은 field가 아니라서 둘러싼 텍스트가 없습니다. 설명이 필요하면 PlFieldset 안에 넣으세요.

labeldescriptionerror도 없습니다. 이것은 field가 아니라서 둘러싼 텍스트가 없습니다. 설명이 필요하면 PlFieldset 안에 넣으세요.

React 빌드와 다른 점 둘은, 이 패키지의 모든 날짜 컴포넌트가 갖는 그 둘입니다. nameslabelslocale 문자열 대신 말 자체를 받습니다. 프레임워크에 Intl이 없기 때문입니다. 기본은 영어이고, 이미 package:intl을 쓰는 앱은 세 줄로 PlDateNames를 만듭니다. 그리고 name이 없습니다. Dart의 폼은 HTML의 폼이 아니므로 제출할 hidden input도 없고, 값을 보내는 것은 호출자의 몫입니다.

density는 없습니다. 정사각형 마흔두 개짜리 grid에 padding을 더하는 것은 그것들이 정사각형이기를 그만두게 하는 일입니다. 대신 size가 사다리 전체를 함께 움직입니다. 공유 축이 라이브러리 전체에서 무엇을 뜻하는지는 prop 규약에 있습니다.

PlCalendar와 PlDatePicker 중 고르기

PlDatePicker는 calendar를 여는 field입니다. 폼 안에서 다른 field 옆에 놓이고, 열기 전까지 그 답은 텍스트 한 줄입니다. 이 컴포넌트는 field를 대신하고 있지 않은 calendar입니다. 예약 페이지, 예약 가능 현황, 대시보드의 날짜 레일. grid가 폼을 채우는 방법이 아니라 인터페이스 그 자체입니다.

답이 다른 input들 옆 폼 안에 놓인다면 picker를 쓰세요.

Examples

precision

시작 화면이 아니라 바닥입니다. month에서는 월 grid가 마지막 grid이고 거기서 셀을 누르면 그것이 답입니다. 그 아래에 일 grid가 아예 없습니다. 카드 만료일은 월이고, 2027년 12월의 며칠이냐를 답하게 만드는 컨트롤은 잘못 답하게 될 컨트롤입니다.

값은 고른 것의 시작으로 정규화됩니다. 그달의 1일, 1월 1일이지, 커서가 마침 얹혀 있던 날이 아닙니다.

React

minDate, maxDate, shouldDisableDate

두 경계는 calendar 자신의 precision으로 읽습니다. 그래서 month calendar에서 7월 15일의 minDate는 7월을 고를 수 있게 남겨 둡니다. shouldDisableDate는 일 단위이며 나머지 둘에서는 아예 참조되지 않습니다.

React

variant

기본은 glass이고, PlCard가 가진 시트와 elevation을 씁니다. 이미 시트를 그리는 것 안에 calendar가 들어간다면 ghost를 쓰세요. 사각형 안의 두 번째 테두리 사각형은 두 번째 사각형입니다.

React

화면의 달을 제어하기

monthonMonthChange는 무엇이 선택됐는지와 무관하게 화면에 보이는 달을 제어합니다. calendar 두 개를 한 달 간격으로 유지할 때 필요한 것입니다.

tsx
const [month, setMonth] = useState(startOfMonth(new Date()));

<PlCalendar month={month} onMonthChange={setMonth} value={day} onValueChange={setDay} />;

제어하지 않으면 달은 값을 따라갑니다. 뒤 주의 날을 고르면 grid가 그 날의 달로 옮겨 갑니다. 화면에 없는 달에서의 선택은 아무도 볼 수 없는 선택이기 때문입니다.

폼 안에서

name은 hidden input을 답니다. 표기는 precision을 따릅니다. YYYY-MM-DD, 그다음 YYYY-MMYYYY. 같은 모양의 네이티브 input이 제출하는 형식입니다.

tsx
<form action={book}>
  <PlCalendar name="departure" />
</form>

더할 것이 없습니다. Dart의 폼은 HTML의 폼이 아니므로 hidden input도, 거기 줄 이름도 없습니다. 값은 onChanged로 오고, 그것을 보내는 것은 호출자의 몫입니다.

disabled

calendar를 흐리게 하고 inert 속성으로 손이 닿지 않게 합니다. 셀 마흔두 개에 disabled를 다는 대신 속성 하나입니다.

옆에 readOnly가 없고, 빠뜨린 것이 아닙니다. read-only field는 여전히 사용자가 선택하고 복사할 값을 보여 주지만, calendar에는 복사할 것이 없습니다. 전부가 아니라 일부 날짜만 막으려면 shouldDisableDate를 쓰세요.

Accessibility

  • 진짜 role="grid"이며 roving tab stop 하나입니다. 그래서 Tab은 셀 마흔두 개를 걷는 대신 calendar를 빠져나갑니다. ARIA date-picker practice가 기술하는 패턴이고, 어떤 셀도 disabled 버튼이 아닌 이유입니다. 막힌 날은 aria-disabled이고 여전히 닿을 수 있어서, 키보드 사용자가 그것이 막혔다는 사실을 알 수 있습니다.
  • 화살표 키는 셀 하나씩, PageUp/PageDown은 한 달씩(Shift와 함께면 한 해씩), Home/End는 주의 양끝으로 움직입니다. 가장자리를 넘어가면 멈추는 대신 calendar가 한 칸 넘어갑니다.
  • 각 셀의 accessible name은 calendar의 locale로 쓴 전체 날짜입니다. 그래서 스크린 리더가 "27"이 아니라 "2026년 7월 27일 월요일"을 읽습니다.
  • autoFocus는 picker와 반대로 기본이 꺼짐입니다. popup은 그 안으로 들어가려는 사람이 방금 연 것이고, 페이지 안의 calendar는 그렇지 않습니다.

Released under the MIT License