DatePicker
Sana va sanalar oralig'ini tanlash: qo'lda yozish, o'zbekcha kalendar, tayyor variantlar.
Yakshanba — dam olish kuni
'use client';
import { formatDate } from '@akhatmirzo/core';
import { DatePicker, Field } from '@akhatmirzo/ui';
import { useState } from 'react';
const isSunday = (date: Date) => date.getDay() === 0;
export default function DatePickerBasic() {
const [date, setDate] = useState<Date | null>(null);
return (
<div className="w-full max-w-xs">
<Field
label="Yetkazish sanasi"
description={date ? formatDate(date, 'd MMMM yyyy, EEEE') : 'Yakshanba — dam olish kuni'}
>
<DatePicker
value={date}
onValueChange={setDate}
minDate={new Date()}
disabledDates={isSunday}
presets
clearable
/>
</Field>
</div>
);
}
Import
import { Calendar, DatePicker, DateRangePicker } from '@akhatmirzo/ui';Uchta komponent bitta kalendar ustida qurilgan:
| Komponent | Vazifasi |
|---|---|
DatePicker | Bitta sana: Input ko'rinishidagi maydon + Popover'da kalendar |
DateRangePicker | Sanalar oralig'i: tugma-trigger + ikki oylik kalendar |
Calendar | Popover'siz kalendar — sahifaga yoki o'z oynangizga joylashtiriladi |
Qachon ishlatish
- Aniq kun kerak bo'lsa — yetkazish sanasi, uchrashuv, muddat. Faqat oy yoki yil kerak bo'lsa, oddiy Select yetarli.
- Tug'ilgan sana kabi uzoq sanalar uchun ham
DatePickerqulay: sanani klaviaturada yozib qo'yish mumkin, kalendar sarlavhasi bosilsa oy va yil tanlanadi. - Hisobot davri, ta'til, filtrlar —
DateRangePicker. Tayyor variantlar (presets) eng ko'p ishlatiladigan oraliqlarni bir bosishda beradi. - Cheklovlarni oldindan bering:
minDate,maxDate,disabledDates. Foydalanuvchi tanlab bo'lmaydigan kunni ko'radi, lekin bosa olmaydi — keyin xato chiqargandan ko'ra yaxshi. - Label uchun maydonni Field ichiga qo'ying —
id,aria-describedbyva xato holati avtomatik ulanadi.
Qo'lda yozish
Maydonga to'g'ridan-to'g'ri yozish mumkin: __.__.____ niqobi nuqtalarni o'zi qo'yadi, oxirgi
raqam kiritilganda sana tekshiriladi. Mavjud bo'lmagan sana (31.02.2026) — invalid, cheklovga
tushmaydigan sana — unavailable xatosi. Xato turini onErrorChange orqali olasiz.
Sinab ko'ring: 31022026
Qiymat: null
'use client';
import { formatDate } from '@akhatmirzo/core';
import { DatePicker, Field, type DatePickerError } from '@akhatmirzo/ui';
import { useState } from 'react';
const errorText: Record<DatePickerError, string> = {
invalid: "Bunday sana yo'q",
unavailable: "O'tgan sanani tanlab bo'lmaydi",
};
export default function DatePickerTyping() {
const [date, setDate] = useState<Date | null>(null);
const [error, setError] = useState<DatePickerError | null>(null);
return (
<div className="flex w-full max-w-xs flex-col gap-3">
<Field
label="Uchrashuv sanasi"
required
error={error ? errorText[error] : undefined}
description="Sinab ko'ring: 31022026"
>
<DatePicker
value={date}
onValueChange={setDate}
onErrorChange={setError}
minDate={new Date()}
/>
</Field>
<p className="text-sm text-text-muted">
Qiymat: <code>{date ? formatDate(date, 'yyyy-MM-dd') : 'null'}</code>
</p>
</div>
);
}
Xato matni bitta joyda
Standart holatda DatePicker xatoni o'zi, maydon ostida ko'rsatadi. Agar Field ga error
berilgan bo'lsa (yoki invalid), ichki xato qatori yashiriladi — ikki qator xato chiqmasligi
uchun. Bu xatti-harakatni showError bilan majburan yoqish yoki o'chirish mumkin.
Niqob faqat raqamli shablonlarda ishlaydi (dd.MM.yyyy, MM/dd/yyyy). format="d MMMM yyyy"
kabi so'zli shablonda maydon oddiy matn sifatida tahlil qilinadi.
Oy va yilni tanlash
Kalendar sarlavhasini ("Oktabr 2026") bosing — oylar, keyin yillar ko'rinishiga o'tiladi. Bu
tug'ilgan sana kabi uzoq sanalarga tez yetib borish uchun. minDate va maxDate dan tashqaridagi
oylar va yillar o'chirilgan bo'ladi.
Sarlavhani bosing — oy va yilni tanlash
'use client';
import { DatePicker, Field } from '@akhatmirzo/ui';
import { useState } from 'react';
export default function DatePickerBirthday() {
const [birthday, setBirthday] = useState<Date | null>(new Date(1995, 4, 17));
return (
<div className="w-full max-w-xs">
<Field label="Tug'ilgan sana" description="Sarlavhani bosing — oy va yilni tanlash">
<DatePicker
value={birthday}
onValueChange={setBirthday}
minDate={new Date(1920, 0, 1)}
maxDate={new Date()}
/>
</Field>
</div>
);
}
Tayyor variantlar
presets — kalendar ostidagi tezkor tugmalar. true bersangiz: "Bugun", "Ertaga", "Bir haftadan
keyin". O'zingizniki uchun DatePreset[] bering:
import { DatePicker, type DatePreset } from '@akhatmirzo/ui';
const presets: DatePreset[] = [
{
label: '3 kundan keyin',
date: (today) => new Date(today.getFullYear(), today.getMonth(), today.getDate() + 3),
},
{ label: 'Yangi yil', date: new Date(2027, 0, 1) },
];
<DatePicker presets={presets} />;Agar variant sanasi cheklovga tushmasa (masalan, yakshanba yopiq), eng yaqin ruxsat etilgan keyingi kun tanlanadi (31 kungacha qidiriladi).
O'lchamlar
sm, md, lg — 32, 40 va 48px. Balandliklar Input bilan bir xil.
'use client';
import { DatePicker } from '@akhatmirzo/ui';
export default function DatePickerSizes() {
const today = new Date();
return (
<div className="flex w-full max-w-xs flex-col gap-3">
<DatePicker size="sm" aria-label="Kichik" defaultValue={today} />
<DatePicker size="md" aria-label="O'rta" defaultValue={today} />
<DatePicker size="lg" aria-label="Katta" defaultValue={today} />
</div>
);
}
Holatlar
disabled, readOnly, xato va boshqa format. readOnly maydonda kalendar ochilmaydi.
Sanani tanlang
d MMMM yyyy
'use client';
import { DatePicker, Field } from '@akhatmirzo/ui';
export default function DatePickerStates() {
const today = new Date();
return (
<div className="grid w-full max-w-2xl gap-4 sm:grid-cols-2">
<Field label="O'chirilgan" disabled>
<DatePicker defaultValue={today} />
</Field>
<Field label="Faqat o'qish">
<DatePicker defaultValue={today} readOnly />
</Field>
<Field label="Muddat" error="Sanani tanlang" required>
<DatePicker />
</Field>
<Field label="Boshqa format" description="d MMMM yyyy">
<DatePicker format="d MMMM yyyy" defaultValue={today} />
</Field>
</div>
);
}
DateRangePicker
Oraliq ikkinchi kun bosilganda tasdiqlanadi. Birinchi kundan keyin kursor bilan yurganingizda
oraliq oldindan ko'rinadi. Kompyuterda ikki oy, telefonda bitta oy ko'rsatiladi. presets uchun
standart variantlar: "Bugun", "Oxirgi 7 kun", "Shu oy", "O'tgan oy".
16 Okt – 22 Okt 2026
'use client';
import { formatDate } from '@akhatmirzo/core';
import { DateRangePicker, Field, type DateRangeValue } from '@akhatmirzo/ui';
import { useState } from 'react';
const daysAgo = (n: number) => {
const d = new Date();
return new Date(d.getFullYear(), d.getMonth(), d.getDate() - n);
};
export default function DateRangePickerBasic() {
const [range, setRange] = useState<DateRangeValue | null>({ from: daysAgo(6), to: daysAgo(0) });
return (
<div className="w-full max-w-sm">
<Field
label="Hisobot davri"
description={
range?.from && range.to
? `${formatDate(range.from, 'd MMM')} – ${formatDate(range.to, 'd MMM yyyy')}`
: 'Davr tanlanmagan'
}
>
<DateRangePicker value={range} onValueChange={setRange} presets maxDate={new Date()} />
</Field>
</div>
);
}
onValueChange faqat to'liq oraliq (from va to ikkalasi bor) bilan yoki tozalanganda null
bilan chaqiriladi — yarim tanlangan oraliq tashqariga chiqmaydi.
O'z variantlaringiz va forma
DateRangePreset da range — obyekt yoki today ni oladigan funksiya. name bersangiz, formaga
ikkita yashirin maydon qo'shiladi: ${name}From va ${name}To (yyyy-MM-dd).
Yakshanbalar yopiq
'use client';
import { DateRangePicker, Field, type DateRangeValue } from '@akhatmirzo/ui';
import { useState } from 'react';
const addDays = (d: Date, n: number) => new Date(d.getFullYear(), d.getMonth(), d.getDate() + n);
export default function DateRangePickerPresets() {
const [vacation, setVacation] = useState<DateRangeValue | null>(null);
return (
<div className="w-full max-w-sm">
<Field label="Ta'til" description="Yakshanbalar yopiq">
<DateRangePicker
value={vacation}
onValueChange={setVacation}
minDate={new Date()}
disabledDates={(d) => d.getDay() === 0}
clearable
name="tatil"
presets={[
{ label: 'Bir hafta', range: (t) => ({ from: addDays(t, 1), to: addDays(t, 7) }) },
{ label: 'Ikki hafta', range: (t) => ({ from: addDays(t, 1), to: addDays(t, 14) }) },
]}
/>
</Field>
</div>
);
}
Qo'lda yozish faqat DatePicker'da
DateRangePicker ning trigger'i — tugma, unga matn yozilmaydi. Klaviatura bilan Enter, Space
yoki ↓ bosing — kalendar ochiladi va fokus darhol kunga o'tadi.
Calendar
Kalendarni Popover'siz, to'g'ridan-to'g'ri sahifada ishlatish mumkin — masalan bron qilish
sahifasida. mode="range" bilan oraliq tanlanadi.
| Du | Se | Ch | Pa | Ju | Sh | Ya |
|---|---|---|---|---|---|---|
'use client';
import { formatDate } from '@akhatmirzo/core';
import { Calendar } from '@akhatmirzo/ui';
import { useState } from 'react';
export default function CalendarInline() {
const [date, setDate] = useState<Date | null>(new Date());
return (
<div className="flex flex-col items-center gap-2">
<Calendar
value={date}
onValueChange={setDate}
disabledDates={(d) => d.getDay() === 0}
className="rounded-xl border border-border bg-surface p-3"
/>
<span className="text-sm text-text-muted">
{date ? formatDate(date, 'd MMMM yyyy, EEEE') : 'Sana tanlanmagan'}
</span>
</div>
);
}
| Du | Se | Ch | Pa | Ju | Sh | Ya |
|---|---|---|---|---|---|---|
| Du | Se | Ch | Pa | Ju | Sh | Ya |
|---|---|---|---|---|---|---|
'use client';
import { Calendar, type DateRangeValue } from '@akhatmirzo/ui';
import { useState } from 'react';
const addDays = (d: Date, n: number) => new Date(d.getFullYear(), d.getMonth(), d.getDate() + n);
export default function CalendarRange() {
const today = new Date();
const [range, setRange] = useState<DateRangeValue>({
from: addDays(today, -3),
to: addDays(today, 4),
});
return (
<div className="flex flex-col items-center gap-2">
<Calendar
mode="range"
numberOfMonths={2}
value={range}
onValueChange={setRange}
className="rounded-xl border border-border bg-surface p-3"
/>
<span className="text-sm text-text-muted">
{range.from && !range.to ? 'Tugash sanasini tanlang' : 'Oraliq tanlandi'}
</span>
</div>
);
}
Props
DatePicker
Qolgan <input> atributlarini (name, id, placeholder, required, readOnly, disabled,
aria-* ...) va ref ni qabul qiladi. className — ildiz elementga, inputClassName — ichki
<input> ga. name berilsa, forma uchun yashirin maydon qo'shiladi (yyyy-MM-dd).
| Prop | Tip | Standart | Tavsif |
|---|---|---|---|
value | Date | null | — | Tanlangan sana (boshqariladigan) |
defaultValue | Date | null | — | Boshlang'ich qiymat |
onValueChange | (value: Date | null) => void | — | Sana tanlanganda, to'g'ri yozilganda yoki tozalanganda |
format | string | 'dd.MM.yyyy' | Ko'rsatish va yozish shabloni (core formatDate tokenlari) |
minDate | Date | — | Eng erta ruxsat etilgan sana |
maxDate | Date | — | Eng kech ruxsat etilgan sana |
disabledDates | (date: Date) => boolean | — | true qaytarsa — kunni tanlab bo'lmaydi |
presets | boolean | DatePreset[] | — | Kalendar ostidagi tayyor variantlar |
size | 'sm' | 'md' | 'lg' | 'md' | Balandlik |
invalid | boolean | — | Xato holati (Field ichida error bo'lsa avtomatik) |
clearable | boolean | false | Qiymat bo'lsa ✕ tugmasi |
open | boolean | — | Kalendar ochiqmi (boshqariladigan) |
defaultOpen | boolean | false | |
onOpenChange | (open: boolean) => void | — | |
today | Date | — | Bugungi sana (standart — new Date()) |
numberOfMonths | number | 1 | Ko'rsatiladigan oylar |
onErrorChange | (error: DatePickerError | null) => void | — | Yozilgan matn xatosi o'zgarganda: 'invalid' yoki 'unavailable' |
showError | boolean | — | Ichki xato matni. Standart — tashqi xato bo'lmasa ko'rinadi |
labels | DatePickerLabels | — | Matnlar (pastda) |
inputClassName | string | — | Ichki <input> klassi |
contentClassName | string | — | Popover paneli klassi |
DateRangePicker
Qolgan <button> atributlarini qabul qiladi (trigger'ga). className — ildizga,
triggerClassName — tugmaga.
| Prop | Tip | Standart | Tavsif |
|---|---|---|---|
value | DateRangeValue | null | — | { from, to } (boshqariladigan) |
defaultValue | DateRangeValue | null | — | |
onValueChange | (value: DateRangeValue | null) => void | — | Faqat to'liq oraliq yoki tozalanganda null bilan |
format | string | 'dd.MM.yyyy' | |
minDate | Date | — | |
maxDate | Date | — | |
disabledDates | (date: Date) => boolean | — | |
presets | boolean | DateRangePreset[] | — | true — Bugun, Oxirgi 7 kun, Shu oy, O'tgan oy |
numberOfMonths | 1 | 2 | — | Standart — 2, telefonda (< 640px) 1 |
size | 'sm' | 'md' | 'lg' | 'md' | |
invalid | boolean | — | |
clearable | boolean | false | |
open | boolean | — | |
defaultOpen | boolean | false | |
onOpenChange | (open: boolean) => void | — | |
today | Date | — | |
name | string | — | Forma uchun `${name}From` va `${name}To` yashirin maydonlari |
labels | DateRangePickerLabels | — | |
triggerClassName | string | — | |
contentClassName | string | — |
Calendar
Qolgan <div> atributlarini qabul qiladi. mode ga qarab value turi o'zgaradi.
| Prop | Tip | Standart | Tavsif |
|---|---|---|---|
mode | 'single' | 'range' | 'single' | Bitta sana yoki oraliq |
value | Date | null / DateRangeValue | null | — | single / range |
defaultValue | Date | null / DateRangeValue | null | — | |
onValueChange | (value: Date | null) => void / (value: DateRangeValue) => void | — | |
minDate | Date | — | |
maxDate | Date | — | |
disabledDates | (date: Date) => boolean | — | |
numberOfMonths | number | 1 | |
month | Date | — | Ko'rsatilayotgan oy (boshqariladigan) |
defaultMonth | Date | — | |
onMonthChange | (month: Date) => void | — | |
view | 'days' | 'months' | 'years' | — | Ko'rinish (boshqariladigan) |
defaultView | 'days' | 'months' | 'years' | 'days' | |
onViewChange | (view: CalendarView) => void | — | |
today | Date | — | |
showOutsideDays | boolean | — | Qo'shni oylar kunlari. Standart — bitta oyda true, bir nechtasida false |
autoFocus | boolean | false | Tanlangan (yoki bugungi) kunga fokus |
footer | ReactNode | — | Kalendar ostidagi kontent |
labels | CalendarLabels | — |
Tiplar
interface DateRangeValue {
from: Date | null;
to: Date | null; // null — oraliq hali tugallanmagan
}
interface DatePreset {
label: string;
date: Date | ((today: Date) => Date);
}
interface DateRangePreset {
label: string;
range: DateRangeValue | ((today: Date) => DateRangeValue);
}isDateSelectable(date, { minDate, maxDate, disabledDates }) ham eksport qilinadi — o'z
validatsiyangizda xuddi shu qoidani ishlatish uchun.
Matnlar (labels)
Barcha matnlar o'zbekcha standart qiymatga ega. Boshqa tilga o'tkazish uchun kerakli kalitlarni bering — qolganlari standartda qoladi:
<DatePicker
labels={{
placeholder: 'dd.mm.yyyy',
openCalendar: 'Open calendar',
clear: 'Clear',
invalidDate: 'Invalid date',
months: ['January', 'February' /* ... */],
weekdaysShort: ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'],
}}
/>CalendarLabels: previousMonth, nextMonth, previousYear, nextYear, previousYears,
nextYears, chooseMonth, chooseYear, monthsGrid, yearsGrid, navigation, today,
selected, months, monthsShort, weekdays, weekdaysShort (hafta dushanbadan).
DatePickerLabels bularga qo'shimcha: placeholder, openCalendar, calendar, clear,
presets, invalidDate, unavailableDate, today, tomorrow, inAWeek.
DateRangePickerLabels: placeholder, calendar, clear, presets, pickEnd, separator,
today, last7Days, thisMonth, lastMonth.
Data atributlari
| Atribut | Element | Qiymat |
|---|---|---|
data-size | maydon konteyneri | sm · md · lg |
data-state | maydon konteyneri | open · closed |
data-invalid | maydon konteyneri | xato bo'lganda mavjud |
data-disabled | maydon konteyneri | disabled bo'lganda mavjud |
data-readonly | DatePicker maydoni | readOnly bo'lganda mavjud |
Klaviatura
| Tugma | Harakat |
|---|---|
↓ (maydon/trigger) | Kalendarni ochadi va fokusni kunga o'tkazadi |
Enter (maydonda) | Yozilgan sanani tekshiradi va tasdiqlaydi |
← → | ±1 kun |
↑ ↓ | ±1 hafta |
PageUp / PageDown | ±1 oy (Shift bilan — ±1 yil) |
Home / End | Hafta boshi / oxiri |
Enter / Space | Kunni tanlash |
Esc | Kalendarni yopadi; oy/yil ko'rinishida — kunlarga qaytaradi |
Oy va yil to'rida: strelkalar bilan yuriladi (↑ ↓ — bir qator), Home / End — birinchi va
oxirgi element.
Accessibility
- Maydon — oddiy
<input type="text">:aria-haspopup="dialog",aria-expandedva ochiq paytdaaria-controlskalendar paneliga ishora qiladi. Raqamli shablonda mobil klaviatura raqamli bo'ladi (inputMode="numeric"). - Kalendar paneli
aria-label="Kalendar"bilan nomlangan; ochilganda fokus maydonda qoladi,↓yoki kalendar tugmasi bilan kunga o'tadi. Yopilganda fokus maydonga qaytadi. - Xato
aria-invalidbilan belgilanadi, xato matniaria-describedbyorqali maydonga bog'langan vaaria-live="polite"hududida e'lon qilinadi. - Kun tugmalari ekran o'quvchi uchun to'liq nom oladi: bugungi kunga "Bugun", tanlanganiga "tanlangan" qo'shiladi. Tanlab bo'lmaydigan kunlar xira va ustidan chizilgan — bosilmaydi.
- Oy va yil to'rlari —
role="group", har bir katakda to'liqaria-label, joriy oy/yilaria-currentbilan belgilangan. - DateRangePicker: birinchi kun tanlangach "Tugash sanasini tanlang" matni
aria-livehududida e'lon qilinadi; tayyor variant tugmalaridaaria-pressedbor. - Ikonkalar
aria-hidden; "Kalendarni ochish" va "Tozalash" tugmalaridaaria-labelbor.