You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
Guillermo Pages c22918d3ea feat: DateRange example 5 months ago
nginx feat: working 10 months ago
src feat: DateRange example 5 months ago
.DS_Store feat: first commit, working 10 months ago
.deploy.yml feat: working 10 months ago
.drone.yml fix: wrong handle 10 months ago
.gitignore feat: working 10 months ago
Dockerfile feat: working 10 months ago
README.md feat: proper readme 10 months ago
docker-compose.yml feat: DateRange example 5 months ago
index.html feat: first commit, working 10 months ago
package-lock.json feat: first commit, working 10 months ago
package.json feat: first commit, working 10 months ago
tsconfig.json feat: working 10 months ago
vite.config.ts feat: first commit, working 10 months ago

README.md

React Calendar Component

A modern, flexible calendar component built with React, TypeScript, and SCSS modules.

Demo

Check out the live demo at calendar.code.meow.ch

Features

  • 📅 Multiple calendar views:
    • Full year view with configurable month grid
    • Single month view with customizable layout
    • Week view with interactive options
    • Date range picker with hover preview
  • 🎨 Visual customization:
    • Four header styles: expanded, compacted, tiny, and numeric
    • Configurable day sizes (XS to XL)
    • Adjustable font proportions
    • Optional magnify effect for selected dates
    • Weekend highlighting
  • 🔧 Functional options:
    • Month cutoff handling (dimmed, truncated, or show all)
    • Interactive date range selection
    • Hover states and preview
    • Responsive design for all screen sizes
  • 🛠 Technical features:
    • Built with React + TypeScript
    • SCSS modules for styling
    • date-fns for date manipulation
    • Zero external dependencies beyond core requirements

Installation

npm install

Development

npm run dev

Usage Examples

Date Range Picker

import React, { useState } from 'react';
import { Year } from './components/calendar/Year';
import { DateRange } from './types/calendar';

function DateRangePicker() {
  const [dateRange, setDateRange] = useState<DateRange>({
    startDate: null,
    endDate: null,
    selecting: false,
    hoverDate: null,
    anchorDate: null
  });

  const handleDateSelect = (date: Date) => {
    setDateRange(prev => {
      if (!prev.selecting) {
        return {
          startDate: date,
          endDate: date,
          selecting: true,
          hoverDate: date,
          anchorDate: date
        };
      }
      // Complete the selection
      return {
        startDate: prev.anchorDate,
        endDate: date,
        selecting: false,
        hoverDate: null,
        anchorDate: null
      };
    });
  };

  return (
    <Year 
      year={2024}
      dayHeaderStyle="tiny"
      monthCutoff="truncate"
      weekendDays={[6, 0]}
      dateRange={dateRange}
      onDateSelect={handleDateSelect}
      onDateHover={(date) => setDateRange(prev => ({ ...prev, hoverDate: date }))}
      size="l"
      fontProportion={100}
      magnify={true}
    />
  );
}

Single Month View

import React from 'react';
import { Month } from './components/calendar/Month';

function SingleMonth() {
  return (
    <Month
      date={new Date()}
      dayHeaderStyle="expanded"
      direction="column"
      monthCutoff="dimmed"
      weekendDays={[6, 0]}
      size="xl"
      fontProportion={100}
    />
  );
}

Week View

import React from 'react';
import { Week } from './components/calendar/Week';

function WeekView() {
  return (
    <Week
      startDate={new Date()}
      headerStyle="compacted"
      referenceMonth={new Date().getMonth()}
      weekendDays={[6, 0]}
      size="l"
      fontProportion={100}
    />
  );
}

Compact Year View

import React from 'react';
import { Year } from './components/calendar/Year';

function CompactYear() {
  return (
    <Year
      year={2024}
      dayHeaderStyle="tiny"
      monthCutoff="truncate"
      weekendDays={[6, 0]}
      size="xs"
      fontProportion={80}
      magnify={true}
    />
  );
}

Component Props

Year Component

interface YearProps {
  year: number;
  dayHeaderStyle: 'expanded' | 'compacted' | 'tiny' | 'none';
  monthDayOfWeekHeaderStyle?: HeaderStyle;
  monthCutoff?: 'dimmed' | 'truncate' | undefined;
  weekendDays?: number[];
  dateRange?: DateRange;
  onDateSelect?: (date: Date) => void;
  onDateHover?: (date: Date) => void;
  size?: 'xl' | 'l' | 'm' | 's' | 'xs';
  fontProportion?: number;
  magnify?: boolean;
}

Month Component

interface MonthProps {
  date: Date;
  dayHeaderStyle: HeaderStyle;
  direction: 'row' | 'column';
  monthCutoff?: MonthCutoffType;
  weekendDays?: number[];
  dateRange?: DateRange;
  onDateSelect?: (date: Date) => void;
  onDateHover?: (date: Date) => void;
  size?: DaySize;
  fontProportion?: number;
  magnify?: boolean;
}

Styling

The component uses SCSS modules for styling. Key style files:

  • src/components/calendar/shared/_colors.scss: Color variables
  • src/components/calendar/shared/_variables.scss: Layout variables
  • Individual component SCSS modules for specific styling

Browser Support

  • Chrome (latest)
  • Firefox (latest)
  • Safari (latest)
  • Edge (latest)

License

MIT