Expo App UIExpo App UI
Components

Calendar

A flexible calendar component supporting single date selection, date ranges, and customizable theming for Expo React Native. Learn how to use Calendar with examples and API documentation.

Calendar Component Example

Installation

npx expo-app-ui add calendar

:::note The calendar component is self-contained and doesn't require any external dependencies. :::

Usage

import Calendar from "@/components/ui/calender";

<Calendar 
  mode="single" 
  value={date} 
  onChange={setDate} 
/>

Complete Example

Here's a complete example showing all calendar features:

import Calendar from "@/components/ui/calender";
import React, { useState } from "react";
import { StyleSheet, Text, View } from "react-native";

export default function CalendarExampleScreen() {
  /* ---------- Single Date ---------- */
  const [singleDate, setSingleDate] = useState<Date | null>(null);

  /* ---------- Date Range ---------- */
  const [range, setRange] = useState<{
    start: Date | null;
    end: Date | null;
  }>({ start: null, end: null });

  return (
    <View style={styles.container}>
      <Text style={styles.heading}>Calendar Component Demo</Text>

      {/* ================= Single Select ================= */}
      <Text style={styles.subHeading}>Single Date Selection</Text>

      <Calendar
        mode="single"
        value={singleDate ?? new Date()}
        minDate="1900-01-01"
        maxDate={new Date().toISOString().split("T")[0]}
        onChange={setSingleDate}
        allowFutureDates={true}
      />

      {singleDate && (
        <Text style={styles.result}>
          Selected: {singleDate.toISOString().split("T")[0]}
        </Text>
      )}

      {/* ================= Range Select ================= */}
      <Text style={styles.subHeading}>Date Range Selection</Text>

      <Calendar
        mode="range"
        rangeValue={range}
        onRangeChange={setRange}
        minDate="1900-01-01"
        maxDate={new Date().toISOString().split("T")[0]}
      />

      {range.start && (
        <Text style={styles.result}>
          Start: {range.start.toISOString().split("T")[0]}
        </Text>
      )}

      {range.end && (
        <Text style={styles.result}>
          End: {range.end.toISOString().split("T")[0]}
        </Text>
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 24,
    backgroundColor: "#FFFFFF",
  },
  heading: {
    fontSize: 22,
    fontWeight: "600",
    textAlign: "center",
    marginBottom: 20,
  },
  subHeading: {
    fontSize: 18,
    fontWeight: "500",
    marginTop: 20,
    marginBottom: 12,
  },
  result: {
    marginTop: 10,
    textAlign: "center",
    fontSize: 14,
    color: "#333",
  },
});

Props

PropTypeDefaultDescription
mode'single' | 'range''single'Selection mode
valueDate-Selected date (for single mode)
onChange(date: Date) => void-Callback when date changes (for single mode)
rangeValueDateRange{ start: null, end: null }Selected date range (for range mode)
onRangeChange(range: DateRange) => void-Callback when range changes (for range mode)
minDatestring-Minimum selectable date (YYYY-MM-DD format)
maxDatestring-Maximum selectable date (YYYY-MM-DD format)
allowFutureDatesbooleanfalseAllow selection of future dates
themeCalendarTheme{}Custom theme object for styling

DateRange Type

interface DateRange {
  start: Date | null;
  end: Date | null;
}

CalendarTheme Type

interface CalendarTheme {
  primaryColor?: string;
  rangeColor?: string;
  backgroundColor?: string;
  textColor?: string;
  mutedTextColor?: string;
  disabledTextColor?: string;
  selectedTextColor?: string;
  pickerBackground?: string;
  borderRadius?: number;
  daySize?: number;
}

Examples

Single Date Selection

const [date, setDate] = useState<Date | null>(null);

<Calendar
  mode="single"
  value={date ?? new Date()}
  onChange={setDate}
/>

Date Range Selection

const [range, setRange] = useState<DateRange>({ 
  start: null, 
  end: null 
});

<Calendar
  mode="range"
  rangeValue={range}
  onRangeChange={setRange}
/>

With Date Limits

<Calendar
  mode="single"
  value={date}
  onChange={setDate}
  minDate="1900-01-01"
  maxDate={new Date().toISOString().split("T")[0]}
  allowFutureDates={false}
/>

Custom Theme

<Calendar
  mode="single"
  value={date}
  onChange={setDate}
  theme={{
    primaryColor: "#2563EB",
    rangeColor: "#2563EB20",
    backgroundColor: "#FFFFFF",
    textColor: "#111827",
    mutedTextColor: "#6B7280",
    borderRadius: 12,
    daySize: 44,
  }}
/>

Range with Highlighting

<Calendar
  mode="range"
  rangeValue={range}
  onRangeChange={setRange}
  theme={{
    primaryColor: "#7C3AED",
    rangeColor: "#7C3AED30",
  }}
/>

Features

  • Two Selection Modes: Single date or date range selection
  • Month/Year Pickers: Quick navigation via modal pickers
  • Date Range Highlighting: Visual indication of selected range
  • Date Constraints: Min/max date and future date restrictions
  • Customizable Theming: Full control over colors and styling
  • Smooth Navigation: Previous/next month navigation
  • Disabled Dates: Visual indication of non-selectable dates
  • No Dependencies: Self-contained component
  • TypeScript Support: Full TypeScript types included

Date Format

All date strings should be in YYYY-MM-DD format:

minDate="1900-01-01"
maxDate="2024-12-31"

Range Selection Behavior

  1. First Click: Sets the start date
  2. Second Click:
    • If after start date: Sets end date
    • If before start date: Resets and sets new start date
  3. Range Highlighting: Days between start and end are highlighted

Notes

  • The calendar automatically handles month boundaries
  • Disabled dates are visually distinct and non-interactive
  • When allowFutureDates is false, dates after today are disabled
  • Month and year pickers open in modal overlays
  • The calendar syncs with external value changes in single mode
  • Range mode requires both rangeValue and onRangeChange props
  • Theme values are merged with defaults
  • The component uses a 6-row grid to display all days
  • Days from previous/next month are shown as empty cells
  • Selected dates are highlighted with the primary color
  • Range dates are highlighted with a semi-transparent background

On this page

Find this useful?

Buy me a coffee