@atom_design/calendar
v1.0.0
Published
A styled React Native calendar component built on react-native-calendars with Atom Design theming.
Downloads
91
Readme
@atom_design/calendar
A customizable and elegant Calendar Component for React Native, built on top of react-native-calendars and styled for the Atom Design System. Supports date selection, min/max restrictions, marked dates, and full theming.
✨ Features
- 📅 Full Monthly Calendar - Clean, modern calendar UI
- 🎨 Atom Design Theming - Pre-configured with brand colors
- 🔘 Date Selection - Single date selection with highlight
- 🚫 Min/Max Date Limits - Restrict selectable date range
- 🏷️ Marked Dates - Add dots, highlights, or custom marks
- 📱 Swipe Navigation - Swipe to change months
- ⚙️ Highly Customizable - Colors, theme, and all calendar props
- 🎯 TypeScript Support - Full type definitions included
📦 Installation
npm install @atom_design/calendarOr with yarn:
yarn add @atom_design/calendarPeer Dependencies
Make sure you have the required peer dependencies installed:
npm install react-native-calendars prop-types📥 Import
import Calendar from '@atom_design/calendar';
// or
import { AtomCalendar } from '@atom_design/calendar';🎯 Basic Usage
import React, { useState } from 'react';
import Calendar from '@atom_design/calendar';
function CalendarExample() {
const [selectedDate, setSelectedDate] = useState('2025-12-03');
return (
<Calendar
selectedDate={selectedDate}
onDateSelect={setSelectedDate}
/>
);
}📋 Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| selectedDate | string | - | Selected date (YYYY-MM-DD format) |
| onDateSelect | (date: string) => void | - | Callback when date is selected |
| minDate | string | - | Minimum selectable date |
| maxDate | string | - | Maximum selectable date |
| markedDates | object | {} | Custom marked dates object |
| primaryColor | string | '#d9232d' | Primary/accent color |
| showShadow | boolean | true | Show shadow around calendar |
| hideArrows | boolean | false | Hide navigation arrows |
| hideExtraDays | boolean | true | Hide days from other months |
| disableMonthChange | boolean | false | Disable month navigation |
| firstDay | number | 0 | First day of week (0=Sun, 1=Mon) |
| showWeekNumbers | boolean | false | Show week numbers |
| enableSwipeMonths | boolean | true | Enable swipe navigation |
| containerStyle | ViewStyle | - | Container style override |
| calendarStyle | ViewStyle | - | Calendar style override |
| theme | object | - | Custom theme object |
| testID | string | - | Test ID for testing |
🎨 Customization Examples
With Date Restrictions
<Calendar
selectedDate={date}
onDateSelect={setDate}
minDate="2025-01-01"
maxDate="2025-12-31"
/>Custom Primary Color
<Calendar
selectedDate={date}
onDateSelect={setDate}
primaryColor="#4CAF50"
/>With Marked Dates
<Calendar
selectedDate={date}
onDateSelect={setDate}
markedDates={{
'2025-12-25': { marked: true, dotColor: 'green' },
'2025-12-31': { marked: true, dotColor: 'red' },
'2025-12-15': { disabled: true, disableTouchEvent: true },
}}
/>Monday as First Day
<Calendar
selectedDate={date}
onDateSelect={setDate}
firstDay={1} // Monday
/>Without Shadow
<Calendar
selectedDate={date}
onDateSelect={setDate}
showShadow={false}
/>Custom Theme
<Calendar
selectedDate={date}
onDateSelect={setDate}
theme={{
textDayFontSize: 18,
textMonthFontSize: 20,
dayTextColor: '#333',
monthTextColor: '#000',
}}
/>🏷️ Marked Dates Format
The markedDates prop accepts an object where keys are dates in YYYY-MM-DD format:
const markedDates = {
// Simple dot marker
'2025-12-10': { marked: true },
// Custom dot color
'2025-12-15': { marked: true, dotColor: 'blue' },
// Disabled date
'2025-12-20': { disabled: true, disableTouchEvent: true },
// Selected with custom color
'2025-12-25': { selected: true, selectedColor: 'green' },
// Multiple dots
'2025-12-31': {
dots: [
{ key: 'event1', color: 'red' },
{ key: 'event2', color: 'blue' },
],
},
};Note: The component automatically merges your markedDates with the selectedDate highlight.
🧪 Test Screen Example
import React, { useState } from 'react';
import { View, Text, ScrollView, StyleSheet, TouchableOpacity } from 'react-native';
import Calendar from '@atom_design/calendar';
const CalendarTestScreen = () => {
const [selectedDate, setSelectedDate] = useState('2025-12-03');
const [primaryColor, setPrimaryColor] = useState('#d9232d');
// Get today and date limits
const today = new Date().toISOString().split('T')[0];
const minDate = '2025-01-01';
const maxDate = '2025-12-31';
// Sample marked dates (holidays, events)
const markedDates = {
'2025-12-25': { marked: true, dotColor: '#4CAF50' }, // Christmas
'2025-12-31': { marked: true, dotColor: '#FF9800' }, // New Year's Eve
'2025-01-01': { marked: true, dotColor: '#2196F3' }, // New Year
'2025-01-26': { marked: true, dotColor: '#FF5722' }, // Republic Day
'2025-08-15': { marked: true, dotColor: '#FF5722' }, // Independence Day
};
// Color options
const colors = ['#d9232d', '#4CAF50', '#2196F3', '#9C27B0', '#FF9800'];
return (
<ScrollView style={styles.container}>
<Text style={styles.header}>Atom Design - Calendar</Text>
{/* Basic Calendar */}
<View style={styles.section}>
<Text style={styles.sectionTitle}>Basic Calendar</Text>
<Calendar
selectedDate={selectedDate}
onDateSelect={setSelectedDate}
/>
<Text style={styles.result}>
Selected: {selectedDate || 'None'}
</Text>
</View>
{/* With Date Restrictions */}
<View style={styles.section}>
<Text style={styles.sectionTitle}>With Min/Max Dates</Text>
<Text style={styles.description}>
Restricted to year 2025 only
</Text>
<Calendar
selectedDate={selectedDate}
onDateSelect={setSelectedDate}
minDate={minDate}
maxDate={maxDate}
/>
</View>
{/* With Marked Dates */}
<View style={styles.section}>
<Text style={styles.sectionTitle}>With Marked Dates</Text>
<Text style={styles.description}>
Holidays and events are marked with dots
</Text>
<Calendar
selectedDate={selectedDate}
onDateSelect={setSelectedDate}
markedDates={markedDates}
/>
<View style={styles.legend}>
<View style={styles.legendItem}>
<View style={[styles.dot, { backgroundColor: '#4CAF50' }]} />
<Text style={styles.legendText}>Christmas</Text>
</View>
<View style={styles.legendItem}>
<View style={[styles.dot, { backgroundColor: '#FF9800' }]} />
<Text style={styles.legendText}>New Year's Eve</Text>
</View>
<View style={styles.legendItem}>
<View style={[styles.dot, { backgroundColor: '#FF5722' }]} />
<Text style={styles.legendText}>National Holiday</Text>
</View>
</View>
</View>
{/* Custom Color */}
<View style={styles.section}>
<Text style={styles.sectionTitle}>Custom Primary Color</Text>
<View style={styles.colorPicker}>
{colors.map((color) => (
<TouchableOpacity
key={color}
style={[
styles.colorOption,
{ backgroundColor: color },
primaryColor === color && styles.colorSelected,
]}
onPress={() => setPrimaryColor(color)}
/>
))}
</View>
<Calendar
selectedDate={selectedDate}
onDateSelect={setSelectedDate}
primaryColor={primaryColor}
/>
</View>
{/* Monday First Day */}
<View style={styles.section}>
<Text style={styles.sectionTitle}>Monday as First Day</Text>
<Calendar
selectedDate={selectedDate}
onDateSelect={setSelectedDate}
firstDay={1}
/>
</View>
{/* With Week Numbers */}
<View style={styles.section}>
<Text style={styles.sectionTitle}>With Week Numbers</Text>
<Calendar
selectedDate={selectedDate}
onDateSelect={setSelectedDate}
showWeekNumbers
firstDay={1}
/>
</View>
{/* No Shadow */}
<View style={styles.section}>
<Text style={styles.sectionTitle}>Without Shadow</Text>
<Calendar
selectedDate={selectedDate}
onDateSelect={setSelectedDate}
showShadow={false}
containerStyle={styles.flatCalendar}
/>
</View>
{/* Disabled Month Change */}
<View style={styles.section}>
<Text style={styles.sectionTitle}>Current Month Only</Text>
<Text style={styles.description}>
Navigation arrows hidden, swipe disabled
</Text>
<Calendar
selectedDate={today}
onDateSelect={setSelectedDate}
hideArrows
disableMonthChange
enableSwipeMonths={false}
/>
</View>
</ScrollView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#F5F5F5',
},
header: {
fontSize: 24,
fontWeight: 'bold',
textAlign: 'center',
marginVertical: 20,
color: '#1A1A1A',
},
section: {
marginHorizontal: 16,
marginBottom: 24,
},
sectionTitle: {
fontSize: 18,
fontWeight: '600',
marginBottom: 8,
color: '#1A1A1A',
},
description: {
fontSize: 14,
color: '#666',
marginBottom: 12,
},
result: {
marginTop: 12,
fontSize: 14,
color: '#d9232d',
fontStyle: 'italic',
textAlign: 'center',
},
legend: {
flexDirection: 'row',
flexWrap: 'wrap',
marginTop: 12,
gap: 12,
},
legendItem: {
flexDirection: 'row',
alignItems: 'center',
},
dot: {
width: 10,
height: 10,
borderRadius: 5,
marginRight: 6,
},
legendText: {
fontSize: 12,
color: '#666',
},
colorPicker: {
flexDirection: 'row',
marginBottom: 12,
gap: 10,
},
colorOption: {
width: 36,
height: 36,
borderRadius: 18,
borderWidth: 2,
borderColor: 'transparent',
},
colorSelected: {
borderColor: '#1A1A1A',
},
flatCalendar: {
borderWidth: 1,
borderColor: '#E0E0E0',
},
});
export default CalendarTestScreen;🎨 Default Theme
The calendar comes with the following Atom Design theming:
| Property | Value |
|----------|-------|
| Selected Day Color | #d9232d (or primaryColor) |
| Today Text Color | #d9232d |
| Arrow Color | #d9232d |
| Day Text Color | #1A1A1A |
| Disabled Text Color | #CCCCCC |
| Month Text Color | #1A1A1A |
| Background | #FFFFFF |
Override any value using the theme prop.
📝 TypeScript
Full TypeScript definitions are included:
import Calendar, { AtomCalendarProps } from '@atom_design/calendar';
const MyCalendar: React.FC = () => {
const [date, setDate] = useState<string>('2025-12-03');
const handleDateSelect = (dateString: string): void => {
setDate(dateString);
};
return (
<Calendar
selectedDate={date}
onDateSelect={handleDateSelect}
minDate="2025-01-01"
maxDate="2025-12-31"
/>
);
};⚠️ Important Notes
- Always provide dates in YYYY-MM-DD format
- The component wraps
react-native-calendars- all its props are supported - Works on both iOS and Android
- Requires
react-native-calendarsas a peer dependency
📄 License
MIT © Atom Design
👤 Author
Atom Design Team
Part of the Atom Design System for React Native.
