日付ピッカーライブラリ比較

このページでは、react-datepicker・@daypicker/react・Mantine・Ant Design・shadcn/ui・MUI X・ブラウザ標準input・カスタム実装の8方式による日付ピッカー(単一選択・範囲選択)の実装をデモ・コード付きで確認できます。

共通の初期設定

範囲選択デモでは本日から7日後まで、単一選択デモでは本日を初期値として設定しています。カレンダーから日付を選択でき、選択結果がリアルタイムに表示されます。

{
  "startDate": "2026-07-14",
  "endDate": "2026-07-21",
  "locale": "ja (日本語)"
}

1. react-datepicker

最も人気のあるReact日付ピッカー — 豊富な機能と柔軟なカスタマイズ性

選択中:2026年7月14日2026年7月21日7日間)

インラインカレンダー表示

7月 2026

日曜日
月曜日
火曜日
水曜日
木曜日
金曜日
土曜日
28
29
30
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
29
30
31

8月 2026

日曜日
月曜日
火曜日
水曜日
木曜日
金曜日
土曜日
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
29
30
31
1
2
3
4
5

特徴

  • • ポップアップ・インライン両対応のカレンダー表示
  • • 範囲選択・複数月表示・時刻選択に対応
  • • ロケール設定で日本語表示が可能
  • • 最小日・最大日の制限、除外日の設定が容易

インストール

npm install react-datepicker date-fns
tsx
'use client';
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';
import { useState } from 'react';
import { isAfter } from 'date-fns';

export function ReactDatePickerDemo() {
  // 基準時刻を1つに統一(別々に取得するとSSRとクライアントで日数計算が揺れる)
  const [initial] = useState(() => {
    const start = new Date();
    return { start, end: new Date(start.getTime() + 7 * 24 * 60 * 60 * 1000) };
  });
  const [startDate, setStartDate] = useState<Date | null>(initial.start);
  const [endDate, setEndDate] = useState<Date | null>(initial.end);

  return (
    <div className="flex flex-col sm:flex-row gap-4">
      <div>
        <label className="block text-sm font-medium text-gray-700 mb-1">開始日</label>
        <DatePicker
          selected={startDate}
          onChange={(date: Date | null) => {
            setStartDate(date);
            if (endDate && date && isAfter(date, endDate)) setEndDate(null);
          }}
          selectsStart
          startDate={startDate}
          endDate={endDate}
          dateFormat="yyyy/MM/dd"
          className="border border-gray-300 rounded px-3 py-2 text-sm"
        />
      </div>
      <div>
        <label className="block text-sm font-medium text-gray-700 mb-1">終了日</label>
        <DatePicker
          selected={endDate}
          onChange={(date: Date | null) => setEndDate(date)}
          selectsEnd
          startDate={startDate}
          endDate={endDate}
          minDate={startDate ?? undefined}
          dateFormat="yyyy/MM/dd"
          className="border border-gray-300 rounded px-3 py-2 text-sm"
        />
      </div>
    </div>
  );
}

🤖 AIプロンプトテンプレート

React + Tailwind CSSで、react-datepickerを使った日付範囲ピッカーを実装してください。
- 使用ライブラリ: react-datepicker、date-fns
- DatePicker コンポーネントで selectsStart/selectsEnd プロパティを使って開始日・終了日を個別に選択できること
- monthsShown={2} と selectsRange、inline プロパティでインラインの2ヶ月表示を実装すること
- locale="ja" で日本語表示し、dateFormat="yyyy/MM/dd" で書式化すること
- minDate プロパティで終了日に開始日以前を選択できないよう制限すること
- 選択された期間の日数をリアルタイムに計算して表示すること

⚠️ このプロンプトはあくまでたたき台です。AIの回答はモデルやバージョン、会話の文脈によって毎回異なります。意図通りに動かない場合は、条件を追記・修正してお使いください。

2. @daypicker/react(v10)

軽量でアクセシブルなカレンダー — WAI-ARIA対応でモダンな設計

選択中:2026年7月14日2026年7月21日7日間)

2026年7月
2026年8月

特徴

  • • WAI-ARIAガイドラインに準拠した高いアクセシビリティ
  • • シングル・複数・範囲選択モードを標準サポート
  • • CSSカスタムプロパティでスタイル変更が容易
  • • date-fnsベースでロケール対応が充実(ロケールは同梱)

インストール

npm install @daypicker/react
tsx
'use client';
import { DayPicker, type DateRange } from '@daypicker/react';
import '@daypicker/react/style.css';
import { useState } from 'react';
import { ja } from '@daypicker/react/locale';

export function ReactDayPickerDemo() {
  // 基準時刻を1つに統一(別々に取得するとSSRとクライアントで日数計算が揺れる)
  const [range, setRange] = useState<DateRange | undefined>(() => {
    const from = new Date();
    return { from, to: new Date(from.getTime() + 7 * 24 * 60 * 60 * 1000) };
  });

  return (
    <div>
      <DayPicker
        mode="range"
        selected={range}
        onSelect={setRange}
        locale={ja}
        numberOfMonths={2}
      />
      {range?.from && range?.to && (
        <p className="text-sm text-gray-600 mt-2">
          選択期間: {range.from.toLocaleDateString('ja-JP')} 〜 {range.to.toLocaleDateString('ja-JP')}
        </p>
      )}
    </div>
  );
}

🤖 AIプロンプトテンプレート

React + Tailwind CSSで、@daypicker/react(v10)を使った日付範囲ピッカーを実装してください。
- 使用ライブラリ: @daypicker/react(v10)
- DayPicker コンポーネントで mode="range" と numberOfMonths={2} を使った2ヶ月表示の範囲選択を実装すること
- DateRange 型で選択中の from/to を管理すること
- locale={ja} で日本語表示すること(import { ja } from '@daypicker/react/locale')
- 「今週」「30日間」「90日間」「クリア」のプリセットボタンを実装すること
- 選択された期間の日数をリアルタイムに計算して表示すること

⚠️ このプロンプトはあくまでたたき台です。AIの回答はモデルやバージョン、会話の文脈によって毎回異なります。意図通りに動かない場合は、条件を追記・修正してお使いください。

3. Mantine DatePicker

Mantineと統合された日付ピッカー — 範囲選択・インライン表示・日本語対応が標準装備

インラインカレンダー表示

特徴

  • type="range" で日付範囲選択、DateTimePicker で時刻選択にも対応
  • • ポップアップ(DatePickerInput)とインライン(DatePicker)の両形式をサポート
  • • locale="ja" と dayjs で日本語対応が容易
  • • MantineをすでにDI採用しているプロジェクトなら追加ライブラリなしで使える

インストール

npm install @mantine/dates dayjs(@mantine/coreは別途必要)
tsx
'use client';
import { useState } from 'react';
import { DatePickerInput, DatePicker } from '@mantine/dates';
import { MantineProvider } from '@mantine/core';
import '@mantine/core/styles.css';
import '@mantine/dates/styles.css';
import dayjs from 'dayjs';

export function MantineDatePickerDemo() {
  const [range, setRange] = useState<[Date | null, Date | null]>([null, null]);

  const presets = [
    { label: '今週', value: [dayjs().startOf('week').toDate(), dayjs().endOf('week').toDate()] as [Date, Date] },
    { label: '今月', value: [dayjs().startOf('month').toDate(), dayjs().endOf('month').toDate()] as [Date, Date] },
    { label: '先月', value: [dayjs().subtract(1, 'month').startOf('month').toDate(), dayjs().subtract(1, 'month').endOf('month').toDate()] as [Date, Date] },
  ];

  return (
    <MantineProvider>
      <div className="flex flex-col gap-4">
        <DatePickerInput
          type="range"
          label="日付範囲を選択"
          placeholder="開始日 → 終了日"
          value={range}
          onChange={setRange}
          locale="ja"
          valueFormat="YYYY/MM/DD"
          clearable
        />
        <div className="flex gap-2">
          {presets.map(preset => (
            <button
              key={preset.label}
              onClick={() => setRange(preset.value)}
              className="px-3 py-1 text-sm border rounded hover:bg-gray-50"
            >
              {preset.label}
            </button>
          ))}
        </div>
        <DatePicker
          type="range"
          value={range}
          onChange={setRange}
          locale="ja"
          numberOfColumns={2}
        />
      </div>
    </MantineProvider>
  );
}

🤖 AIプロンプトテンプレート

React + Tailwind CSSで、Mantine DatePickerを使った日付範囲ピッカーを実装してください。
- 使用ライブラリ: @mantine/dates、@mantine/core、dayjs
- DatePickerInput コンポーネントで type="range" を使ったポップアップ日付範囲選択を実装すること
- DatePicker コンポーネントで type="range" と numberOfColumns={2} を使ったインライン2ヶ月表示を実装すること
- clearable プロパティでクリア機能を追加すること
- locale="ja" で日本語表示し、valueFormat="YYYY/MM/DD" で書式化すること
- dayjs を使って「今週」「今月」「先月」のプリセットボタンを実装すること
- MantineProvider でラップすること

⚠️ このプロンプトはあくまでたたき台です。AIの回答はモデルやバージョン、会話の文脈によって毎回異なります。意図通りに動かない場合は、条件を追記・修正してお使いください。

4. カスタム実装(React + Tailwind CSS)

ライブラリ不要の完全カスタム実装 — ホバープレビューや2ヶ月表示を自作

2026年7月

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
29
30
31

2026年8月

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
29
30
31

選択期間:2026年7月14日2026年7月21日7日間)

特徴

  • • 外部ライブラリ不要で依存関係が最小限
  • • ホバー時のプレビュー表示で直感的な範囲選択
  • • プリセットボタン(今週・30日間など)を自由に追加可能
  • • デザインの自由度が最も高い

インストール

npm install date-fns(日付計算用、カレンダーUIは自作)
tsx
'use client';
import { useState } from 'react';
import { format, addMonths, subMonths, isSameDay, isAfter, isBefore } from 'date-fns';
import { ja } from 'date-fns/locale';

export function CustomDateRangePickerDemo() {
  const [start, setStart] = useState<Date | null>(null);
  const [end, setEnd] = useState<Date | null>(null);
  const [hovered, setHovered] = useState<Date | null>(null);
  const [viewMonth, setViewMonth] = useState(new Date());

  const handleDayClick = (day: Date) => {
    if (!start || (start && end)) {
      setStart(day);
      setEnd(null);
    } else {
      if (isAfter(day, start)) setEnd(day);
      else { setEnd(start); setStart(day); }
    }
  };

  const isInRange = (day: Date) => {
    const rangeEnd = end ?? hovered;
    if (!start || !rangeEnd) return false;
    return isAfter(day, start) && isBefore(day, rangeEnd);
  };

  const daysInMonth = (year: number, month: number) =>
    new Date(year, month + 1, 0).getDate();

  const year = viewMonth.getFullYear();
  const month = viewMonth.getMonth();
  const firstDay = new Date(year, month, 1).getDay();
  const days = daysInMonth(year, month);

  return (
    <div className="inline-block">
      <div className="flex items-center justify-between mb-3">
        <button onClick={() => setViewMonth(subMonths(viewMonth, 1))} className="px-2 py-1 text-sm">←</button>
        <span className="font-semibold text-sm">{format(viewMonth, 'yyyy年M月', { locale: ja })}</span>
        <button onClick={() => setViewMonth(addMonths(viewMonth, 1))} className="px-2 py-1 text-sm">→</button>
      </div>
      <div className="grid grid-cols-7 gap-1 text-center text-xs text-gray-500 mb-1">
        {['日','月','火','水','木','金','土'].map(d => <span key={d}>{d}</span>)}
      </div>
      <div className="grid grid-cols-7 gap-1">
        {Array.from({ length: firstDay }).map((_, i) => <span key={`e${i}`} />)}
        {Array.from({ length: days }, (_, i) => {
          const day = new Date(year, month, i + 1);
          const isStart = start && isSameDay(day, start);
          const isEnd = end && isSameDay(day, end);
          const inRange = isInRange(day);
          return (
            <button
              key={i}
              onClick={() => handleDayClick(day)}
              onMouseEnter={() => setHovered(day)}
              onMouseLeave={() => setHovered(null)}
              className={`text-sm py-1 rounded ${
                isStart || isEnd ? 'bg-blue-600 text-white' : inRange ? 'bg-blue-100' : 'hover:bg-gray-100'
              }`}
            >
              {i + 1}
            </button>
          );
        })}
      </div>
      {start && (
        <p className="text-xs text-gray-500 mt-2">
          {format(start, 'yyyy/MM/dd')} {end ? `〜 ${format(end, 'yyyy/MM/dd')}` : '(終了日を選択)'}
        </p>
      )}
    </div>
  );
}

🤖 AIプロンプトテンプレート

React + Tailwind CSSで、ライブラリ不要のカスタム日付範囲ピッカーを実装してください。
- 使用ライブラリ: date-fns(日付計算用)、React + Tailwind CSS(カレンダーUIは自作)
- 2ヶ月分のカレンダーを横並びで表示し、開始日・終了日を順番にクリックして選択できること
- onMouseEnter でホバー中の日付をプレビュー表示し、選択予定の範囲をハイライトすること
- 選択中の範囲内の日付は bg-emerald-100、開始日・終了日は bg-emerald-600 でスタイリングすること
- 「今週」「30日間」「クリア」のプリセットボタンと前月・翌月ナビゲーションを実装すること
- 選択された期間の日数をリアルタイムに計算して表示すること

⚠️ このプロンプトはあくまでたたき台です。AIの回答はモデルやバージョン、会話の文脈によって毎回異なります。意図通りに動かない場合は、条件を追記・修正してお使いください。

5. Ant Design DatePicker

エンタープライズ定番のデザインシステム — 単一選択・範囲選択・プリセットが標準装備

選択期間:2026年7月14日2026年7月21日7日間)

特徴

  • DatePicker(単一)と DatePicker.RangePicker(範囲)を完成品として提供
  • presets プロパティでプリセット(今週・今月・先月)が組み込みで実装できる
  • ConfigProvider locale={jaJP} + dayjs の 'dayjs/locale/ja' で日本語化
  • showTime で時刻選択、allowClear でクリアも標準対応

インストール

npm install antd dayjs
tsx
'use client';
import { useState } from 'react';
import { ConfigProvider, DatePicker } from 'antd';
import jaJP from 'antd/locale/ja_JP';
import dayjs, { Dayjs } from 'dayjs';
import 'dayjs/locale/ja';

const { RangePicker } = DatePicker;

export function AntdDatePickerDemo() {
  const [single, setSingle] = useState<Dayjs | null>(dayjs());
  const [range, setRange] = useState<[Dayjs | null, Dayjs | null] | null>([
    dayjs(),
    dayjs().add(7, 'day'),
  ]);

  const presets = [
    { label: '今週', value: [dayjs().startOf('week'), dayjs().endOf('week')] as [Dayjs, Dayjs] },
    { label: '今月', value: [dayjs().startOf('month'), dayjs().endOf('month')] as [Dayjs, Dayjs] },
    { label: '先月', value: [dayjs().subtract(1, 'month').startOf('month'), dayjs().subtract(1, 'month').endOf('month')] as [Dayjs, Dayjs] },
  ];

  return (
    <ConfigProvider locale={jaJP}>
      <div className="flex flex-col gap-4">
        {/* 単一選択 */}
        <DatePicker
          value={single}
          onChange={(date) => setSingle(date)}
          format="YYYY/MM/DD"
          placeholder="日付を選択"
        />
        {/* 範囲選択(プリセット付き) */}
        <RangePicker
          value={range}
          onChange={(dates) => setRange(dates)}
          presets={presets}
          format="YYYY/MM/DD"
          placeholder={['開始日', '終了日']}
        />
        {range?.[0] && range?.[1] && (
          <p className="text-sm text-gray-600">
            選択期間: {range[0].format('YYYY/MM/DD')} 〜 {range[1].format('YYYY/MM/DD')}
            ({range[1].diff(range[0], 'day')}日間)
          </p>
        )}
      </div>
    </ConfigProvider>
  );
}

🤖 AIプロンプトテンプレート

React + Tailwind CSSで、Ant Design(antd)のDatePickerを使った日付ピッカーを実装してください。
- 使用ライブラリ: antd、dayjs
- DatePicker コンポーネントで単一日付選択、DatePicker.RangePicker で日付範囲選択を実装すること
- ConfigProvider に locale={jaJP}(antd/locale/ja_JP)を渡し、dayjs は 'dayjs/locale/ja' を import して日本語化すること
- RangePicker の presets プロパティで「今週」「今月」「先月」のプリセットを実装すること
- format="YYYY/MM/DD" で書式化し、選択された期間の日数を dayjs の diff で計算して表示すること

⚠️ このプロンプトはあくまでたたき台です。AIの回答はモデルやバージョン、会話の文脈によって毎回異なります。意図通りに動かない場合は、条件を追記・修正してお使いください。

6. shadcn/ui(Calendar + Popover合成)

Calendar(@daypicker/reactベース)とPopoverを組み合わせて自分で組み立てる合成方式

Popover合成型(クリックで開く)

mode="single"(単一選択)

2026年7月

mode="range"(範囲選択)

2026年7月
2026年8月

選択期間:2026年7月14日2026年7月21日7日間)

特徴

  • 完成品コンポーネントではなく合成方式。CalendarとPopoverを自分で組み合わせるため、組み立ての自由度と引き換えに実装量が多い
  • • Calendar の実体は @daypicker/react(react-day-picker v10)。mode="single" / mode="range" をそのまま使える
  • • コードがプロジェクトに同梱されるため、Tailwindクラスを直接編集してデザインを完全制御できる
  • • locale={ja}(@daypicker/react/locale)で日本語表示

インストール

npx shadcn@latest add calendar popover
tsx
'use client';
// npx shadcn@latest add calendar popover
// ※ calendar.tsx の import は react-day-picker → @daypicker/react に書き換え(同一API)
import { useState } from 'react';
import { type DateRange } from '@daypicker/react';
import { ja } from '@daypicker/react/locale';
import { format } from 'date-fns';
import { CalendarIcon } from 'lucide-react';
import { Calendar } from '@/components/ui/calendar';
import { Popover, PopoverTrigger, PopoverContent } from '@/components/ui/popover';

export function ShadcnDatePickerDemo() {
  const [date, setDate] = useState<Date | undefined>();
  const [range, setRange] = useState<DateRange | undefined>({
    from: new Date(),
    to: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
  });
  const [open, setOpen] = useState(false);

  return (
    <div className="flex flex-col gap-6">
      {/* 入力欄クリックで開くポップオーバー型(単一選択) */}
      <Popover open={open} onOpenChange={setOpen}>
        <PopoverTrigger className="inline-flex w-56 items-center gap-2 rounded-lg border px-3 py-2 text-sm">
          <CalendarIcon className="size-4" />
          {date ? format(date, 'yyyy年M月d日', { locale: ja }) : '日付を選択'}
        </PopoverTrigger>
        <PopoverContent className="w-auto p-0" align="start">
          <Calendar
            mode="single"
            selected={date}
            onSelect={(d) => { setDate(d); setOpen(false); }}
            locale={ja}
          />
        </PopoverContent>
      </Popover>

      {/* インライン範囲選択(2ヶ月表示) */}
      <Calendar
        mode="range"
        selected={range}
        onSelect={setRange}
        numberOfMonths={2}
        locale={ja}
      />
    </div>
  );
}

🤖 AIプロンプトテンプレート

React + Tailwind CSSで、shadcn/uiのCalendarとPopoverを合成した日付ピッカーを実装してください。
- 使用コンポーネント: shadcn/ui の Calendar(@daypicker/react ベース)と Popover
- Calendar の mode="single" で単一選択、mode="range" と numberOfMonths={2} で2ヶ月表示の範囲選択を実装すること
- Popover + PopoverTrigger + PopoverContent を組み合わせ、入力欄クリックでカレンダーが開くポップオーバー型も実装すること
- locale={ja} で日本語表示すること(import { ja } from '@daypicker/react/locale')
- 日付選択後に Popover を閉じ、選択された期間の日数を計算して表示すること

⚠️ このプロンプトはあくまでたたき台です。AIの回答はモデルやバージョン、会話の文脈によって毎回異なります。意図通りに動かない場合は、条件を追記・修正してお使いください。

7. MUI X Date Pickers

Material UIと統合された日付ピッカー — アダプタ方式で日付ライブラリを選択できる

2026/07/14

選択中:2026年7月14日

注記:範囲選択(DateRangePicker)は @mui/x-date-pickers-pro (有償のProライセンス)限定のため、このページでは単一選択のみデモしています。

特徴

  • アダプタ方式AdapterDayjs / AdapterDateFns / AdapterLuxon から日付ライブラリを選択
  • LocalizationProvideradapterLocale="ja" で日本語化
  • • 単一選択のDatePicker・TimePicker・DateTimePickerはMITで無償
  • 範囲選択(DateRangePicker)はPro(有償)限定。無償版で範囲選択が必要なら他ライブラリを検討

インストール

npm install @mui/x-date-pickers @mui/material dayjs
tsx
'use client';
import { useState } from 'react';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
import dayjs, { Dayjs } from 'dayjs';
import 'dayjs/locale/ja';

export function MuiDatePickerDemo() {
  const [value, setValue] = useState<Dayjs | null>(dayjs());

  return (
    // アダプタ方式: AdapterDayjs / AdapterDateFns / AdapterLuxon から選択
    <LocalizationProvider dateAdapter={AdapterDayjs} adapterLocale="ja">
      <DatePicker
        label="日付を選択"
        value={value}
        onChange={(date) => setValue(date)}
        format="YYYY/MM/DD"
        slotProps={{ textField: { size: 'small' } }}
      />
      {/* 範囲選択(DateRangePicker)は @mui/x-date-pickers-pro(有償)限定 */}
    </LocalizationProvider>
  );
}

🤖 AIプロンプトテンプレート

React + Tailwind CSSで、MUI X Date Pickersを使った日付ピッカーを実装してください。
- 使用ライブラリ: @mui/x-date-pickers、@mui/material、dayjs
- LocalizationProvider に dateAdapter={AdapterDayjs} と adapterLocale="ja" を設定すること
- DatePicker コンポーネントで単一日付選択を実装すること(範囲選択のDateRangePickerはPro限定のため使わない)
- format="YYYY/MM/DD" で書式化し、slotProps={{ textField: { size: 'small' } }} でコンパクト表示にすること
- 選択された日付を日本語(YYYY年M月D日)で表示すること

⚠️ このプロンプトはあくまでたたき台です。AIの回答はモデルやバージョン、会話の文脈によって毎回異なります。意図通りに動かない場合は、条件を追記・修正してお使いください。

8. ブラウザ標準 input[type="date"]

ゼロ依存の最小構成 — HTMLだけで日付選択を実現

範囲選択(2つのinputをmin/maxで連動)

選択期間:2026-07-142026-07-217日間)

特徴

  • ゼロ依存:ライブラリ不要でバンドルサイズへの影響なし
  • • フォーム送信時に値が yyyy-mm-dd 形式に正規化される
  • 表示UIはブラウザ/OS依存で統一できない(カレンダーの見た目は環境ごとに異なる)
  • • 範囲選択は2つのinputを min / max で連動させるのが現実解

※ ブラウザ標準要素の詳細な挙動は、今後「ブラウザ標準でできるUI」カテゴリで個別ページとして掘り下げる予定です。

インストール

不要(HTML標準機能)
tsx
'use client';
import { useState } from 'react';

// ゼロ依存: ブラウザ標準の input[type="date"] のみで実装
export function NativeDateInputDemo() {
  const [single, setSingle] = useState('');
  const [start, setStart] = useState('');
  const [end, setEnd] = useState('');

  return (
    <div className="flex flex-col gap-4">
      {/* 単一選択 */}
      <input
        type="date"
        value={single}
        onChange={(e) => setSingle(e.target.value)}
        className="border rounded px-3 py-2 text-sm"
      />

      {/* 範囲選択: 2つのinputをmin/maxで連動させる */}
      <div className="flex items-center gap-3">
        <input
          type="date"
          value={start}
          max={end || undefined}
          onChange={(e) => setStart(e.target.value)}
          className="border rounded px-3 py-2 text-sm"
        />
        <span>→</span>
        <input
          type="date"
          value={end}
          min={start || undefined}
          onChange={(e) => setEnd(e.target.value)}
          className="border rounded px-3 py-2 text-sm"
        />
      </div>
      {/* 値は yyyy-mm-dd 形式に正規化される。表示UIはブラウザ/OS依存 */}
    </div>
  );
}

🤖 AIプロンプトテンプレート

React + Tailwind CSSで、ブラウザ標準の input[type="date"] を使った日付ピッカーを実装してください。
- 外部ライブラリは使わないこと(ゼロ依存)
- 単一選択のinputを1つと、範囲選択用に開始日・終了日の2つのinputを実装すること
- 開始日inputの max に終了日、終了日inputの min に開始日を設定して不正な範囲を選べないよう連動させること
- 値は yyyy-mm-dd 形式の文字列で state 管理し、選択された期間の日数を計算して表示すること

⚠️ このプロンプトはあくまでたたき台です。AIの回答はモデルやバージョン、会話の文脈によって毎回異なります。意図通りに動かない場合は、条件を追記・修正してお使いください。

ライブラリ比較表

行=方式、列=評価項目。横スクロールで全項目を確認できます。

方式単一選択範囲選択導入形態インライン表示ポップアップ表示プリセット時刻選択日本語対応クリア機能バンドルサイズ学習コストおすすめ用途
react-datepicker✅ selected✅ selectsRange完成品内蔵内蔵自作内蔵locale="ja"isClearable中程度(~40KB)フォーム内の日付入力全般
@daypicker/react(v10)✅ mode="single"✅ mode="range"完成品(カレンダー部)内蔵自作自作なしlocale={ja}自作小さい(~10KB)低〜中アクセシビリティ重視のアプリ
Mantine DatePicker✅ type="default"✅ type="range"完成品✅ DatePicker✅ DatePickerInput⚠️ 手動で実装✅ DateTimePickerlocale="ja"(dayjs)✅ clearable中(Mantine全体で大)低〜中Mantine採用プロジェクト
Ant Design✅ DatePicker✅ RangePicker完成品なし(ポップアップ前提)内蔵✅ presets内蔵✅ showTimeConfigProvider + jaJP✅ allowClear大(antd全体)低〜中antd採用・管理画面
shadcn/ui✅ mode="single"✅ mode="range"合成(Calendar+Popover)✅ CalendarPopoverと合成自作なしlocale={ja}自作小(コード同梱)Tailwind採用・デザイン自由度重視
MUI X Date Pickers✅ DatePicker⚠️ Pro(有償)限定完成品✅ StaticDatePicker内蔵自作✅ DateTimePickeradapterLocale="ja"✅ slotProps大(MUI全体)MUI採用プロジェクト
ブラウザ標準 input✅ type="date"⚠️ 2つのinputを連動標準—(UI依存)OS標準UIなしtype="datetime-local"OS言語に依存自作ゼロ最低依存を増やしたくないフォーム
カスタム実装自作✅(自作)自作自作自作自由に実装自作自作自作最小中〜高(要件次第)独自デザインが必要な場合

まとめ

react-datepicker — 最も手軽に日付範囲ピッカーを導入したい場合に最適。ポップアップ・インライン・時刻選択など豊富な機能が揃っている。

@daypicker/react(v10) — アクセシビリティを重視する場合におすすめ。WAI-ARIA準拠で、CSSカスタムプロパティによるスタイル変更も容易。

Mantine DatePicker — Mantineの統一デザインシステムに組み込まれた日付ピッカー。type="range" で日付範囲選択、DateTimePicker で時刻選択にも対応。すでにMantineを採用しているプロジェクトなら追加ライブラリなしで使える点が強み。

カスタム実装 — ブランドに合わせた独自デザインが必要な場合や、ホバープレビューなど細かいUX制御をしたい場合に最適。

Ant Design DatePicker — 単一選択・範囲選択・プリセット・時刻選択まで完成品として揃っており、antd採用プロジェクトや管理画面なら最短で導入できる。

shadcn/ui(Calendar + Popover) — 完成品ではなく合成方式。実装量は多いが、コードが手元に同梱されるためTailwindでデザインを完全制御したい場合に最適。

MUI X Date Pickers — アダプタ方式で日付ライブラリを選べるMUI統合ピッカー。単一選択は無償だが、範囲選択はPro(有償)限定な点に注意。

ブラウザ標準 input[type="date"] — ゼロ依存で最軽量。見た目の統一はできないが、シンプルなフォームなら十分実用になる。

よくある質問

Q. Reactで日付範囲ピッカーを無料で実装できるライブラリは?

react-datepicker・@daypicker/react・Mantine・Ant Design はいずれもMITライセンスで、範囲選択まで無償で使えます。MUI X は単一選択のDatePickerが無償で、範囲選択のDateRangePickerのみPro(有償)です。

Q. MUI Xの日付範囲選択(DateRangePicker)は無料で使える?

使えません。DateRangePickerは @mui/x-date-pickers-pro(商用ライセンス)限定です。無償のMIT版に含まれるのはDatePicker・TimePicker・DateTimePickerなどの単一選択系のみです。

Q. shadcn/uiに完成品の日付ピッカーコンポーネントはある?

ありません。Calendar(@daypicker/react = react-day-picker v10ベース)とPopoverを自分で合成して組み立てる方式です。組み立ての自由度が高い分、完成品ライブラリより実装量は多くなります。

Q. ライブラリなしで日付選択UIは作れる?

ブラウザ標準の input[type="date"] でゼロ依存の単一選択が可能です。範囲選択は2つのinputのmin/maxを連動させるのが現実解です。値はyyyy-mm-dd形式に正規化されますが、カレンダーUIの見た目はブラウザ/OSに依存します。

日付ピッカーは、単一の日付や開始日〜終了日の範囲をカレンダーUIで選択するフォームコンポーネント。日付入力・期間指定のインターフェースとして広く使われる。

生年月日・予約日の入力、ホテル・航空券予約・レポートの期間指定・タスクの開始〜終了日設定など、日付や期間を選択する場面で使われる。

主なバリエーション
  • シングルカレンダー型
  • ダブルカレンダー型(2ヶ月表示)
  • インライン型(常時表示)
  • ポップオーバー型(クリックで表示)
  • プリセット選択付き型(今週・今月など)