@alicetears/nextjs-universal-datepicker
v1.1.0
Published
A modern, accessible, and themeable date picker component for Next.js with support for AD/BE era display, 62+ locales, and full keyboard navigation.
Maintainers
Readme
Next.js Universal DatePicker
A modern, accessible, and themeable date picker component for Next.js with support for AD/BE era display, 62+ locales, and full keyboard navigation.
✨ Features
- ✅ Light / Dark / System theme support - Automatically adapts to user's system preferences
- ✅ AD / BE era display - Support for Anno Domini and Buddhist Era calendars
- ✅ 62+ locales - Comprehensive internationalization support
- ✅ Full keyboard navigation - Arrow keys, Enter, Space, Home, End
- ✅ WCAG AA accessible - ARIA labels, proper focus management, high contrast
- ✅ Mobile-friendly - Touch targets ≥44px, responsive design
- ✅ Correct day-of-week calculation - Guaranteed accuracy across all operations
- ✅ Next.js App Router compatible - Works seamlessly with server components
📦 Installation
Install from npm (when published)
npm install @alicetears/nextjs-universal-datepicker
# or
yarn add @alicetears/nextjs-universal-datepicker
# or
pnpm add @alicetears/nextjs-universal-datepickerInstall from local development
If you're developing the library locally and want to test it in another project:
# In the library directory
npm run build
npm link
# In your project directory
npm link @alicetears/nextjs-universal-datepicker🚀 Quick Start
1. Import the Component and Styles
"use client";
import { useState } from "react";
import { UniversalDatePicker } from "@alicetears/nextjs-universal-datepicker";
import "@alicetears/nextjs-universal-datepicker/styles";
export default function MyPage() {
const [selectedDate, setSelectedDate] = useState<Date | undefined>(new Date());
return (
<UniversalDatePicker
value={selectedDate}
onChange={setSelectedDate}
/>
);
}Important: Don't forget to import the CSS styles! The component requires the stylesheet to render correctly.
import "@alicetears/nextjs-universal-datepicker/styles";2. That's it! Your date picker is ready to use. 🎉
📖 Usage Examples
Basic Usage
"use client";
import { useState } from "react";
import { UniversalDatePicker } from "@alicetears/nextjs-universal-datepicker";
import "@alicetears/nextjs-universal-datepicker/styles";
export default function MyPage() {
const [selectedDate, setSelectedDate] = useState<Date | undefined>(new Date());
return (
<UniversalDatePicker
value={selectedDate}
onChange={setSelectedDate}
/>
);
}With Custom Theme and Era
<UniversalDatePicker
value={selectedDate}
onChange={setSelectedDate}
theme="dark"
era="BE"
locale="th"
/>With Date Constraints
<UniversalDatePicker
value={selectedDate}
onChange={setSelectedDate}
minDate={new Date(2024, 0, 1)}
maxDate={new Date(2024, 11, 31)}
disabled={false}
/>🎨 Theming
The DatePicker supports three theme modes:
system(default) - Automatically detects and follows the user's system theme preferencelight- Light theme with neutral gray background and blue accentdark- Dark theme with dark neutral background and same accent color
Theme Props
<UniversalDatePicker
theme="system" | "light" | "dark"
// ... other props
/>Custom Theme Tokens
The theme system uses CSS variables that can be customized. The component uses the following design tokens:
- Radius:
sm(6px),md(10px),lg(14px) - Spacing:
xs(4px),sm(8px),md(12px),lg(16px),xl(20px) - Font: System UI font stack
You can override CSS variables in your global styles:
:root {
--color-accent: #2563eb;
--color-background: #ffffff;
--color-surface: #f8f9fa;
--radius-md: 10px;
/* ... other variables */
}Tailwind Compatibility
The DatePicker uses CSS variables for theming, making it compatible with Tailwind CSS. You can use Tailwind's theme configuration to customize the colors:
// tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
accent: 'var(--color-accent)',
// ... other colors
}
}
}
}📋 Props
UniversalDatePickerProps
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| value | Date \| undefined | undefined | The selected date |
| onChange | (date: Date) => void | - | Callback when date is selected |
| theme | "system" \| "light" \| "dark" | "system" | Theme mode |
| era | "AD" \| "BE" | "AD" | Calendar era (affects display only) |
| locale | "en" \| "th" \| "es" \| "ja" \| "fr" \| "de" \| "zh" \| "ko" \| "pt" \| "it" \| "ru" \| ... | "en" | Locale for day/month names (62+ locales supported) |
| dateFormat | "DD/MM/YYYY" \| "MM/DD/YYYY" | "DD/MM/YYYY" | Date format for input |
| className | string | "" | Additional CSS classes |
| disabled | boolean | false | Disable the date picker |
| minDate | Date | - | Minimum selectable date |
| maxDate | Date | - | Maximum selectable date |
♿ Accessibility
The DatePicker is fully accessible and follows WCAG AA guidelines:
- ARIA labels for all interactive elements
- Keyboard navigation:
ArrowLeft/Right- Navigate daysArrowUp/Down- Navigate weeksEnter/Space- Select dateHome- Go to first day of monthEnd- Go to last day of monthTab- Navigate between controls
- Focus indicators - Clear visual focus states
- Color contrast - WCAG AA compliant contrast ratios
📅 Era Display
The era prop affects display only. Internally, all date calculations use the Gregorian calendar. When era="BE", the year is displayed as AD year + 543, but the underlying Date object remains unchanged.
// Display shows BE year, but Date object is still Gregorian
<UniversalDatePicker era="BE" value={new Date(2024, 0, 15)} />
// Displays: 15 มกราคม 2567 พ.ศ. (but Date is still 2024)🌐 Locale Support
The DatePicker supports 62+ locales with full translations for day names, abbreviated day names, and month names.
Supported Locales
European Languages:
en- Englishes- Spanish (Español)fr- French (Français)de- German (Deutsch)it- Italian (Italiano)pt- Portuguese (Português)ru- Russian (Русский)nl- Dutch (Nederlands)pl- Polish (Polski)cs- Czech (Čeština)hu- Hungarian (Magyar)ro- Romanian (Română)uk- Ukrainian (Українська)bg- Bulgarian (Български)hr- Croatian (Hrvatski)sr- Serbian (Српски)sk- Slovak (Slovenčina)sl- Slovenian (Slovenščina)et- Estonian (Eesti)lv- Latvian (Latviešu)lt- Lithuanian (Lietuvių)fi- Finnish (Suomi)sv- Swedish (Svenska)no- Norwegian (Norsk)da- Danish (Dansk)el- Greek (Ελληνικά)ca- Catalan (Català)mk- Macedonian (Македонски)sq- Albanian (Shqip)bs- Bosnian (Bosanski)
Asian Languages:
th- Thai (ไทย)ja- Japanese (日本語)zh- Chinese (中文)ko- Korean (한국어)hi- Hindi (हिन्दी)vi- Vietnamese (Tiếng Việt)id- Indonesian (Bahasa Indonesia)ms- Malay (Bahasa Melayu)tl- Tagalog/Filipinobn- Bengali (বাংলা)ta- Tamil (தமிழ்)te- Telugu (తెలుగు)mr- Marathi (मराठी)gu- Gujarati (ગુજરાતી)pa- Punjabi (ਪੰਜਾਬੀ)ur- Urdu (اردو)fa- Persian/Farsi (فارسی)ne- Nepali (नेपाली)si- Sinhala (සිංහල)my- Myanmar/Burmese (မြန်မာ)km- Khmer (ខ្មែរ)lo- Lao (ລາວ)
Middle Eastern & Other Languages:
ar- Arabic (العربية)he- Hebrew (עברית)tr- Turkish (Türkçe)ka- Georgian (ქართული)hy- Armenian (Հայերեն)az- Azerbaijani (Azərbaycan)kk- Kazakh (Қазақ)uz- Uzbek (Oʻzbek)mn- Mongolian (Монгол)af- Afrikaans
Example Usage
// English
<UniversalDatePicker locale="en" />
// Spanish
<UniversalDatePicker locale="es" />
// Japanese
<UniversalDatePicker locale="ja" />
// Arabic
<UniversalDatePicker locale="ar" />
// And 58+ more locales...🛠️ Development
For Library Developers
# Install dependencies
npm install
# Run Next.js development server (for testing/demo)
npm run dev
# Build the library for distribution
npm run build
# Run tests
npm test
# Run tests in watch mode
npm run test:watch
# Build Next.js app (for demo/testing)
npm run build:next
# Start Next.js production server
npm startPublishing to npm
- Update the version in
package.json - Build the library:
npm run build - Publish:
npm publish --access public(make sure you're logged in withnpm login)
The prepublishOnly script will automatically build the library before publishing.
📁 Project Structure
src/
├── theme/
│ ├── tokens.ts # Design tokens (radius, spacing, font)
│ ├── light.ts # Light theme colors
│ ├── dark.ts # Dark theme colors
│ └── index.ts # Theme exports
├── react/
│ ├── UniversalDatePicker.tsx # Main component
│ ├── CalendarGrid.tsx # Calendar grid layout
│ ├── DateCell.tsx # Individual date cell
│ ├── MonthNavigation.tsx # Month navigation controls
│ └── ThemeProvider.tsx # Theme context provider
├── utils/
│ ├── date.ts # Date utility functions
│ ├── era.ts # Era conversion utilities
│ └── locale.ts # Locale utilities
└── types/
└── index.ts # TypeScript type definitions✅ Validation Checklist
- ✅ Day-of-week correctness preserved across all operations
- ✅ Era logic untouched by theme changes
- ✅ Light / Dark modes work correctly
- ✅ Mobile-friendly (touch targets ≥44px)
- ✅ Full keyboard accessibility
- ✅ Next.js App Router safe (no client-side only code in server components)
- ✅ WCAG AA contrast compliance
- ✅ No hardcoded colors or magic numbers
- ✅ Theme switching doesn't affect date calculations
📄 License
MIT
