Prisma
Live Preview
February 2026
Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28

Date Picker Component

Skill này hướng dẫn tạo component Date Picker — calendar popup cho chọn ngày, khoảng ngày, tháng, năm.

1. Mục tiêu (Objective)

Tạo Date Picker: calendar popup, date range selection, month/year navigation. Hỗ trợ locale, validation, manual input.

2. AI Context & Intent (Ngữ cảnh cho AI)

Khi nào dùng Date Picker?

  • Chọn ngày cụ thể: Ngày sinh, ngày hẹn, deadline
  • Chọn khoảng ngày: Check-in / check-out, report period
  • Chọn tháng/năm: Period selector, billing cycle

⚠️ Phân biệt Date Picker vs Input vs Select (QUAN TRỌNG)

Tiêu chí Date Picker Text Input Select
Bản chất Calendar popup Free-text field Dropdown list
Best for Ngày gần (1–90 days) Ngày biết chính xác Predefined options
UX Visual calendar grid Fast typing DD/MM/YYYY Scroll through list
Ví dụ Book appointment Enter birth date (known) Select month

Decision Tree cho AI

text
Cần chọn date/time?
├─ Chọn 1 ngày → Date Picker (single)
│   ├─ Ngày gần (hẹn lịch, deadline) → Calendar popup
│   └─ Ngày xa (ngày sinh) → Text input + calendar fallback
│
├─ Chọn khoảng ngày → Date Picker (range)
│   ├─ Check-in/out, leave request → Range mode
│   └─ Report period (tháng/quý) → Month picker
│
├─ Chỉ cần tháng → Date Picker (month mode)
├─ Chỉ cần năm → Date Picker (year mode)
├─ Cần date + time → Date Picker + Time Picker (composite)
└─ Predefined periods ("Last 7 days") → Select/Dropdown

3. Anatomy

text
┌───────────────────────────┐
│  📅 Select a date...   ▼  │ ← Trigger (Input + icon)
└───────────────────────────┘
        │ click
        ▼
┌───────────────────────────┐
│  ◀  March 2026  ▶        │ ← Header nav (month/year)
├───────────────────────────┤
│  Mo Tu We Th Fr Sa Su     │ ← Weekday labels
├───────────────────────────┤
│              1  2  3  4   │ ← Day cells (--surface bg)
│  5  6  7  8 [9] 10 11    │ ← Selected: --primary bg
│  12 13 14 15 16 17 18    │ ← Today: --primary border
│  19 20 21 22 23 24 25    │ ← Hover: --state-layer-hover
│  26 27 28 29 30 31       │
│                           │
│       [ Today ]           │ ← Quick action (optional)
└───────────────────────────┘ ← Panel: --surface, level-2

4. Platform Mapping

Platform Component Key Difference
Web Calendar popup dropdown Month grid, click to select
iOS UIDatePicker Wheel picker (compact), inline calendar
Android (M3) DatePicker / DateRangePicker Modal calendar, text input option
Carbon DatePicker Text input + calendar flyout

Cross-platform note: UX rất khác! Web dùng dropdown calendar, iOS dùng wheel, Android dùng modal. Token file covers the calendar grid pattern.

5. Modes

Mode Mô tả
single Chọn 1 ngày
range Chọn khoảng ngày (from → to)
month Chọn tháng
year Chọn năm

5.4. Slot Map (Figma ↔ Code)

📎 Source: slot-manifest.jsondate-picker · Layer: surface

Figma Slot data-slot CSS Class Required Accepts
Root date-picker .date-picker
Trigger date-picker-trigger input-with-calendar-icon
Content date-picker-content calendar-grid
Header date-picker-header month/year nav
Grid date-picker-grid day cells
Footer date-picker-footer action buttons

6. Token Mapping

📦 Atomic Mapping: Xem ATOMIC-MAPPING.md → mục date-picker — UI Layer: Surface (dropdown panel), Density Tier: section (panel) + comp (cells).

Panel dùng --surface, selected cell dùng --primary / --primary-foreground, today indicator dùng --primary border. Component token JSON files đã deprecated.

7. Props & API

typescript
interface DatePickerProps {
  value?: Date | [Date, Date];
  mode?: 'single' | 'range' | 'month' | 'year';
  minDate?: Date;
  maxDate?: Date;
  disabledDates?: Date[] | ((date: Date) => boolean);
  locale?: string;
  firstDayOfWeek?: 0 | 1;  // 0=Sunday, 1=Monday
  placeholder?: string;
  onChange: (date: Date | [Date, Date]) => void;
}

8. Accessibility (a11y)

  • Trigger: role="combobox", aria-haspopup="dialog".
  • Calendar: role="grid", days = role="gridcell".
  • Selected: aria-selected="true", today: aria-current="date".
  • Keyboard: Arrow keys navigate grid, Enter selects, Escape closes.
  • Page Up/Down: Previous/next month.

9. Best Practices & Rules

  • Locale-aware: Respect firstDayOfWeek, month/weekday names.
  • Manual input: Allow typing date (DD/MM/YYYY) with validation.
  • Today button: Quick action to jump to today.
  • Outside days: Show dimmed days from adjacent months.
  • Icon: Calendar icon (calendar) CHỈ dùng Lucide icon từ assets/icons/. CẤM dùng text emoji. Xem icon.md mục 10.

10. Example Usage

jsx
{/* Single date selection */}
<DatePicker
  mode="single"
  value={selectedDate}
  placeholder="Chọn ngày..."
  minDate={new Date()}
  onChange={setSelectedDate}
/>

{/* Date range for booking */}
<DatePicker
  mode="range"
  value={[checkIn, checkOut]}
  placeholder="Check-in → Check-out"
  minDate={new Date()}
  disabledDates={bookedDates}
  onChange={([from, to]) => { setCheckIn(from); setCheckOut(to); }}
/>

{/* Month picker for reports */}
<DatePicker
  mode="month"
  value={reportMonth}
  placeholder="Chọn tháng báo cáo"
  onChange={setReportMonth}
/>