PlCalendar
popup 안이 아니라 페이지 위의 한 달입니다. PlDatePicker가 여는 바로 그 grid에서 trigger와 popup을 걷어낸 것입니다.
import { PlCalendar } from 'plass-ui';
<PlCalendar value={day} onValueChange={setDay} />;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 | 3 | 1 | 그림자 깊이. 0은 그림자 없음 |
| value | Date | null | — | 고른 날. 제어하려면 onValueChange와 함께 |
| defaultValue | Date | null | — | 제어하지 않을 때 시작하는 날 |
| onValueChange | (value: Date | null) => void | — | 날이 골렸을 때 |
| precision | 'day' | 'month' | 'year' | 'day' | 되돌려주는 가장 작은 단위. 시작 화면이 아니라 바닥이며, 값은 그 단위의 시작으로 정규화됩니다 |
| month | Date | — | 화면에 있는 달. onMonthChange와 함께 쓰면 제어됩니다 |
| defaultMonth | Date | — | 처음 보여 줄 달. 기본은 값의 달, 값이 없으면 이번 달 |
| onMonthChange | (month: Date) => void | — | 화면의 달이 바뀌었을 때 |
| minDate | Date | null | — | 이 날 이전은 고를 수 없습니다. calendar의 precision으로 읽습니다 |
| maxDate | Date | null | — | 이 날 이후는 고를 수 없습니다. calendar의 precision으로 읽습니다 |
| shouldDisableDate | (date: Date) => boolean | — | 개별 날짜를 막습니다 — 주말, 공휴일, 이미 찬 날. 일 단위라 month/year에서는 참조하지 않습니다 |
| locale | string | — | 월 이름 · 요일 머리글자 · 주의 첫날이 나오는 BCP 47 태그. 기본은 페이지의 로케일 |
| weekStartsOn | 0 | 1 | 2 | 3 | 4 | 5 | 6 | — | 주가 시작하는 요일. Date가 세는 방식이라 일요일이 0입니다. 없으면 locale에서 정합니다 |
| showOutsideDays | boolean | true | 이웃한 달에 속한 앞뒤 날들을 그립니다 |
| autoFocus | boolean | false | 마운트할 때 focus를 가져갑니다. 페이지 안의 calendar는 popup이 아니므로 기본은 꺼짐 |
| disabled | boolean | false | 전체를 흐리게 하고 inert로 탭 순서에서 뺍니다. readOnly는 없습니다 |
| name | string | — | 폼과 함께 제출합니다. 표기는 precision을 따릅니다 — YYYY-MM-DD, YYYY-MM, YYYY |
| labels | Partial<PlPickerLabels> | — | Intl이 의견을 갖지 않는 문자열들 — 버튼과 제목 |
| Prop | 타입 | 기본값 | 설명 |
|---|---|---|---|
| value * | DateTime? | — | 고른 날, 또는 없으면 null. 패키지의 다른 모든 입력과 마찬가지로 controlled입니다 |
| onChanged | ValueChanged<DateTime?>? | — | 고른 날과 함께 호출됩니다. null이면 calendar가 비활성입니다 |
| precision | PlCalendarPrecision | PlCalendarPrecision.day | 되돌려주는 가장 작은 단위. 시작 화면이 아니라 바닥이며, 값은 그 단위의 시작으로 정규화됩니다 |
| month | DateTime? | — | 화면에 있는 달. onMonthChange와 함께 쓰면 제어됩니다 |
| defaultMonth | DateTime? | — | 처음 보여 줄 달. 기본은 값의 달, 값이 없으면 이번 달 |
| onMonthChanged | ValueChanged<DateTime>? | — | 화면의 달이 바뀌었을 때 |
| minDate | DateTime? | — | 이 날 이전은 고를 수 없습니다. calendar의 precision으로 읽습니다 |
| maxDate | DateTime? | — | 이 날 이후는 고를 수 없습니다. calendar의 precision으로 읽습니다 |
| shouldDisableDate | bool Function(DateTime)? | — | 개별 날짜를 막습니다 — 주말, 공휴일, 이미 찬 날. 일 단위라 month/year에서는 참조하지 않습니다 |
| weekStartsOn | PlassWeekday? | — | 주가 시작하는 요일. Date가 세는 방식이라 일요일이 0입니다. 없으면 locale에서 정합니다 |
| names | PlDateNames | PlDateNames.english | calendar가 그리는 말들 — 월, 요일. React의 locale 문자열에 해당합니다 |
| labels | PlPickerLabels | PlPickerLabels.english | calendar가 자기 자신에 대해 말하는 것 — 스테퍼, 제목 |
| showOutsideDays | bool | true | 이웃한 달에 속한 앞뒤 날들을 그립니다 |
| autofocus | bool | false | 마운트할 때 focus를 가져갑니다. 페이지 안의 calendar는 popup이 아니므로 기본은 꺼짐 |
| disabled | bool | false | 전체를 흐리게 하고 inert로 탭 순서에서 뺍니다. readOnly는 없습니다 |
| variant공통 | PlassVariant | PlassVariant.glass | 시트의 재질. 이미 시트를 그리는 것 안에 넣는다면 ghost |
| size공통 | PlassSize | PlassSize.md | 셀 · 반경 · 타입 스케일이 함께 움직입니다. density는 없습니다 |
| color공통 | PlassColor | PlassColor.primary | 고른 날, 오늘 표시, focus ring이 쓰는 색 역할 |
| elevation공통 | int | 1 | 그림자 깊이. 0은 그림자 없음 |
| semanticLabel | String? | — | 스크린 리더가 grid 전체에 주는 이름 |
네이티브 <div> 속성은 그대로 통과합니다. label도 description도 error도 없습니다. 이것은 field가 아니라서 둘러싼 텍스트가 없습니다. 설명이 필요하면 PlFieldset 안에 넣으세요.
label도 description도 error도 없습니다. 이것은 field가 아니라서 둘러싼 텍스트가 없습니다. 설명이 필요하면 PlFieldset 안에 넣으세요.
React 빌드와 다른 점 둘은, 이 패키지의 모든 날짜 컴포넌트가 갖는 그 둘입니다. names와 labels가 locale 문자열 대신 말 자체를 받습니다. 프레임워크에 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일이지, 커서가 마침 얹혀 있던 날이 아닙니다.
minDate, maxDate, shouldDisableDate
두 경계는 calendar 자신의 precision으로 읽습니다. 그래서 month calendar에서 7월 15일의 minDate는 7월을 고를 수 있게 남겨 둡니다. shouldDisableDate는 일 단위이며 나머지 둘에서는 아예 참조되지 않습니다.
variant
기본은 glass이고, PlCard가 가진 시트와 elevation을 씁니다. 이미 시트를 그리는 것 안에 calendar가 들어간다면 ghost를 쓰세요. 사각형 안의 두 번째 테두리 사각형은 두 번째 사각형입니다.
화면의 달을 제어하기
month와 onMonthChange는 무엇이 선택됐는지와 무관하게 화면에 보이는 달을 제어합니다. calendar 두 개를 한 달 간격으로 유지할 때 필요한 것입니다.
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-MM과 YYYY. 같은 모양의 네이티브 input이 제출하는 형식입니다.
<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는 그렇지 않습니다.