npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

react-attendance-calendar

v2.3.6

Published

A responsive React attendance calendar component with TypeScript support

Readme

React Attendance Calendar

A modern, responsive, and highly customizable attendance calendar component for React with full TypeScript support. Perfect for tracking employee attendance, student presence, or any date-based status system.

✨ Features

  • 📅 Responsive design - Automatically switches between 7-14 columns based on container width
  • 🎨 Fully customizable - Complete control with Tailwind CSS classes
  • 🖱️ Interactive - Date click callbacks with hover effects
  • 📱 Mobile-friendly - Responsive grid layout with touch-friendly interactions
  • 🔧 TypeScript support - Full type safety and IntelliSense
  • 🎭 Beautiful defaults - Modern design with emerald/amber color scheme
  • 📊 Multi-month support - Provide attendance data for multiple months at once
  • 🔄 Flexible data format - Support both single month and array of months
  • Auto-initialization - Defaults to current month if no view provided
  • 🎯 Smart navigation - Seamless month/year transitions

📦 Installation

npm install react-attendance-calendar

🎨 CSS Setup

Simply import the CSS in your app:

// In your main app file (e.g., App.tsx, main.tsx, or _app.tsx)
import "react-attendance-calendar/styles.css";

That's it! The component will render with beautiful default styling.

Note: No additional setup required. The package includes pre-compiled CSS. If you're using Tailwind CSS v4 in your project, you can customize the component further using the className props.

🚀 Usage

Basic Example

import { useState } from "react";
import { AttendanceCalendar } from "react-attendance-calendar";
import "react-attendance-calendar/styles.css";

function App() {
  const [view, setView] = useState({ year: 2024, monthIndex: 0 });

  return <AttendanceCalendar view={view} onChangeView={setView} />;
}

Minimal Example (Auto-initialize to current month)

import { AttendanceCalendar } from "react-attendance-calendar";
import "react-attendance-calendar/styles.css";

function App() {
  const [view, setView] = useState();

  return <AttendanceCalendar onChangeView={setView} />;
}

With Single Month Attendance Data

import { AttendanceCalendar } from "react-attendance-calendar";
import "react-attendance-calendar/styles.css";

const attendanceData = {
  year: 2024,
  monthIndex: 0,
  presentDays: new Set([1, 2, 3, 5, 8, 9, 10]),
  absentDays: new Set([4, 11]),
};

<AttendanceCalendar
  view={view}
  onChangeView={setView}
  attendanceData={attendanceData}
  onDateClick={(day, month, year) => console.log(day, month, year)}
/>;

With Multiple Months Attendance Data

import { AttendanceCalendar } from "react-attendance-calendar";
import "react-attendance-calendar/styles.css";

// Provide data for multiple months at once
const attendanceData = [
  // January 2024
  {
    year: 2024,
    monthIndex: 0,
    presentDays: new Set([
      1, 2, 3, 5, 8, 9, 10, 12, 15, 16, 17, 19, 22, 23, 24, 26, 29, 30, 31,
    ]),
    absentDays: new Set([4, 11, 18, 25]),
  },
  // February 2025
  {
    year: 2025,
    monthIndex: 1,
    presentDays: new Set([
      1, 2, 5, 6, 7, 8, 9, 12, 13, 14, 15, 16, 19, 20, 21, 22, 23, 26, 27, 28,
    ]),
    absentDays: new Set([3, 10, 17, 24]),
  },
];

<AttendanceCalendar
  view={view}
  onChangeView={setView}
  attendanceData={attendanceData}
  onDateClick={(day, month, year) => console.log(day, month, year)}
/>;

Custom Styling

<AttendanceCalendar
  view={view}
  onChangeView={setView}
  presentCellClassName="bg-blue-500 text-white"
  absentCellClassName="bg-red-500 text-white"
  cellClassName="rounded-full"
/>

Custom Cell Sizes

// Square cells with custom size
<AttendanceCalendar
  view={view}
  onChangeView={setView}
  cellSize={60} // 60px x 60px cells
/>

// Custom width and height
<AttendanceCalendar
  view={view}
  onChangeView={setView}
  cellWidth={80}  // 80px wide
  cellHeight={50} // 50px tall
/>

// Small compact calendar
<AttendanceCalendar
  view={view}
  onChangeView={setView}
  cellSize={32} // 32px x 32px cells
  cellClassName="text-xs"
/>

Complete Example with Custom Styling

import { useState } from "react";
import {
  AttendanceCalendar,
  type MonthView,
  type AttendanceData,
} from "react-attendance-calendar";
import "react-attendance-calendar/styles.css";

function App() {
  const [view, setView] = useState<MonthView>({
    year: 2024,
    monthIndex: 0, // January
  });

  // Sample attendance data for multiple months
  const attendanceData: AttendanceData = [
    // January 2024
    {
      year: 2024,
      monthIndex: 0,
      presentDays: new Set([
        1, 2, 3, 5, 8, 9, 10, 12, 15, 16, 17, 19, 22, 23, 24, 26, 29, 30, 31,
      ]),
      absentDays: new Set([4, 11, 18, 25]),
    },
    // February 2025
    {
      year: 2025,
      monthIndex: 1,
      presentDays: new Set([
        1, 2, 5, 6, 7, 8, 9, 12, 13, 14, 15, 16, 19, 20, 21, 22, 23, 26, 27, 28,
      ]),
      absentDays: new Set([3, 10, 17, 24]),
    },
  ];

  const handleDateClick = (day: number, month: number, year: number) => {
    console.log(`Clicked on ${day}/${month + 1}/${year}`);
    // Your custom logic here
  };

  return (
    <div className="max-w-4xl mx-auto p-4">
      <AttendanceCalendar
        view={view}
        onChangeView={setView}
        attendanceData={attendanceData}
        onDateClick={handleDateClick}
        showNavigation={true}
        showWeekdayHeaders={true}
        // Custom styling with className props
        cellClassName="rounded-full"
        presentCellClassName="bg-green-500 text-white shadow-lg"
        absentCellClassName="bg-red-500 text-white border-2 border-red-300"
        navigationButtonClassName="bg-blue-500 text-white hover:bg-blue-600"
        monthTitleClassName="text-3xl text-purple-600"
        containerClassName="border border-gray-200 rounded-lg p-4"
      />
    </div>
  );
}

export default App;

📚 Props

| Prop | Type | Required | Description | | --------------------------- | ---------------------------- | -------- | -------------------------------------------------- | | view | MonthView | ❌ | Current month and year (defaults to current month) | | onChangeView | (view: MonthView) => void | ✅ | Month navigation callback | | attendanceData | AttendanceData | ❌ | Present/absent days data (single month or array) | | onDateClick | (day, month, year) => void | ❌ | Date click callback | | showNavigation | boolean | ❌ | Show nav arrows (default: true) | | showWeekdayHeaders | boolean | ❌ | Show weekday headers (default: true) | | cellSize | number | ❌ | Size in pixels for all calendar cells (square) | | cellHeight | number | ❌ | Height in pixels for calendar cells | | cellWidth | number | ❌ | Width in pixels for calendar cells | | className | string | ❌ | Additional classes for root element | | cellClassName | string | ❌ | Custom classes for all cells | | presentCellClassName | string | ❌ | Custom classes for present days | | absentCellClassName | string | ❌ | Custom classes for absent days | | navigationButtonClassName | string | ❌ | Custom classes for nav buttons | | monthTitleClassName | string | ❌ | Custom classes for month title | | weekdayHeaderClassName | string | ❌ | Custom classes for weekday headers | | containerClassName | string | ❌ | Custom classes for main container |

TypeScript

type MonthView = {
  year: number; // e.g., 2024
  monthIndex: number; // 0-11 (0 = January)
};

type MonthAttendanceData = {
  year: number;
  monthIndex: number;
  presentDays: Set<number>; // Day numbers 1-31
  absentDays: Set<number>; // Day numbers 1-31
};

// Support both single month and multiple months
type AttendanceData = MonthAttendanceData | MonthAttendanceData[];

🎨 Styling

The component uses Tailwind CSS classes with a modern design system:

Default Theme

  • Present days: Emerald green (emerald-500) with white text
  • Absent days: Amber orange (amber-500) with white text
  • Regular days: Slate gray (slate-700) with light border
  • Navigation: Rounded buttons with hover effects
  • Typography: Clean, readable fonts with proper hierarchy

Responsive Behavior

  • Desktop: 7 columns with larger cells (size-12 sm:size-14)
  • Wide screens: 14 columns with smaller cells (size-8 sm:size-12)
  • Mobile: Optimized touch targets and spacing

Customization

Override any styling using the className props and size controls:

Size Control

  • cellSize - Set both width and height for square cells
  • cellWidth - Set only the width of cells
  • cellHeight - Set only the height of cells
  • Automatic font sizing - Text size adjusts based on cell dimensions

Styling Options

All Tailwind classes are supported:

  • Colors, spacing, borders, shadows
  • Hover effects, transitions, animations
  • Responsive breakpoints and utilities

🔄 Multi-Month Data Format

The attendanceData prop supports two formats:

Single Month (Legacy Format)

const attendanceData: AttendanceData = {
  year: 2024,
  monthIndex: 0,
  presentDays: new Set([1, 2, 3, 5, 8]),
  absentDays: new Set([4, 6, 7]),
};

Multiple Months (New Format)

const attendanceData: AttendanceData = [
  {
    year: 2024,
    monthIndex: 0, // January
    presentDays: new Set([1, 2, 3, 5, 8]),
    absentDays: new Set([4, 6, 7]),
  },
  {
    year: 2024,
    monthIndex: 1, // February
    presentDays: new Set([1, 2, 5, 6, 7]),
    absentDays: new Set([3, 4, 8]),
  },
  // ... add more months as needed
];

Benefits of Multi-Month Format:

  • Batch loading - Load attendance data for multiple months at once
  • Better performance - No need to fetch data when navigating between months
  • Seamless navigation - Smooth transitions between months with data
  • Backward compatible - Works with existing single month format
  • Memory efficient - Store data in memory for instant access
  • Offline ready - Pre-load data for offline calendar browsing

📝 License

MIT © Alamin