Tailwind UIベースでカレンダー作ってみた
https://almap.hata6502.com/ にUIを置いた
遠くのカレンダーに移動したいときは、
< ボタンを連打せずに 2023年3月 を押して入力できるようにした 目立たないけどボタンっぽい見た目にしてみた
ドラムロールとか作れるといいとは思うけど、まずはwindow.promptで勘弁
Tailwind Plusのカレンダーがオリジナル
Tailwind UIはあくまでテンプレート集なので、ロジックは実装されていない
日付の配列もベタ書き
jsconst days = [ { date: '2021-12-27' }, { date: '2021-12-28' }, { date: '2021-12-29' }, // ...] ロジックを自力で書かなきゃいけないのは大変
しかし、プロダクトごとの選定ライブラリに合わせて実装できるとも思えた
JavaScriptの日付周りは、多種多様なライブラリがある状況
momentから脱出できていないかもしれないし
Temporalを試しているかもしれない
Dateにいろんなハマりどころがあるのは有名な話
getMonth()は0-based
getDay()は日付ではなく曜日
jsconst getDaysOfMonth = (dateOfMonth: Date) => { const days: Date[] = []; for ( const day = new Date(dateOfMonth.getFullYear(), dateOfMonth.getMonth(), 1); day.getMonth() === dateOfMonth.getMonth(); day.setDate(day.getDate() + 1) ) { days.push(new Date(day)); }
// 先月分を埋める while (days[0].getDay() !== 0) { const day = new Date(days[0]); day.setDate(day.getDate() - 1); days.unshift(day); } // 翌月分を埋める while (days[days.length - 1].getDay() !== 6) { const day = new Date(days[days.length - 1]); day.setDate(day.getDate() + 1); days.push(day); }
return days;};js<button type="button" className="rounded bg-indigo-50 px-2 py-1 text-xs text-gray-900 shadow-sm hover:bg-indigo-100" onClick={handleCurrentMonthButtonClick}> {new Intl.DateTimeFormat([], { year: "numeric", month: "long", }).format(dateOfMonth)}</button>範囲選択するロジックも作った
けっこう要件が複雑
初期状態は全選択
範囲選択しないときは、内部的には全選択した状態とする
しかし全日付を選択状態の見た目にしたら、強調だらけになってしまう
全選択しているときは、普通のカレンダーを表示することにした
広い範囲を選択したいこともある
ステートはなるべく増やしたくないけど、2クリックで範囲選択することにした
ドラッグ&ドロップでは、月をまたいで選択できない
選択範囲と非選択範囲の対比を、色反転ではなく浮かび上がる感じ?にしてみた
コントラスト強すぎない感じになった
〇〇日以前や〇〇日以降を選択したいこともある
選択範囲の端をクリックしたら、解除するようにした
開始日時をクリックしたら、〇〇日以前を選択する
終了日時をクリックしたら、〇〇日以降を選択する
開始日時と終了日時を同時にクリックしたら、全選択になる
選択範囲の端に特別な動作を仕込んだので、色も変えてみる
日付範囲を選択するUI、難しくてチャレンジ感ある
カレンダーヒートマップに続く