From bc2c3b5474c9ff0f42ed7f5ecf6da1dc8f8acde8 Mon Sep 17 00:00:00 2001 From: Guillermo Pages Date: Fri, 7 Feb 2025 15:51:27 +0100 Subject: [PATCH] feat: proper readme --- README.md | 265 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 152 insertions(+), 113 deletions(-) diff --git a/README.md b/README.md index 5b86588..6dc1e47 100644 --- a/README.md +++ b/README.md @@ -1,172 +1,211 @@ -# Minimal Calendar Component +# React Calendar Component -A flexible and customizable calendar component built with React, TypeScript, and styled-components. +A modern, flexible calendar component built with React, TypeScript, and SCSS modules. + +## Demo + +Check out the live demo at [calendar.code.meow.ch](https://calendar.code.meow.ch) ## Features -- 📅 Year, month, and week views -- 🎨 Multiple header styles (expanded, compacted, tiny, none) -- 🎯 Customizable month cutoff behavior -- 🎭 Weekend highlighting -- 📱 Fully responsive design -- 🔧 TypeScript support -- 💅 Styled with styled-components +- 📅 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 ```bash -npm install date-fns styled-components +npm install +``` + +## Development + +```bash +npm run dev ``` -## Basic Usage +## Usage Examples + +### Date Range Picker ```tsx +import React, { useState } from 'react'; import { Year } from './components/calendar/Year'; +import { DateRange } from './types/calendar'; + +function DateRangePicker() { + const [dateRange, setDateRange] = useState({ + 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 + }; + }); + }; -function App() { return ( setDateRange(prev => ({ ...prev, hoverDate: date }))} + size="l" + fontProportion={100} + magnify={true} /> ); } ``` -## Advanced Usage - -### With Date Selection +### Single Month View ```tsx -import { useState } from 'react'; -import { Year } from './components/calendar/Year'; - -function App() { - const [selectedDate, setSelectedDate] = useState(); +import React from 'react'; +import { Month } from './components/calendar/Month'; +function SingleMonth() { return ( - ); } ``` -### With Controls +### Week View ```tsx -import { useState } from 'react'; -import { Year } from './components/calendar/Year'; -import { Controls } from './components/calendar/Controls'; -import { HeaderStyle, MonthCutoffType } from './types/calendar'; - -function App() { - const [headerStyle, setHeaderStyle] = useState('tiny'); - const [monthCutoff, setMonthCutoff] = useState('truncate'); +import React from 'react'; +import { Week } from './components/calendar/Week'; +function WeekView() { return ( - <> - - - + ); } ``` -## Component Props - -### Year Component - -| Prop | Type | Description | -|------|------|-------------| -| year | number | The year to display | -| dayHeaderStyle | 'expanded' \| 'compacted' \| 'tiny' \| 'none' | Style of day headers | -| monthDayOfWeekHeaderStyle | HeaderStyle (optional) | Style of month day headers | -| monthCutoff | 'dimmed' \| 'truncate' \| undefined | How to handle days from other months | -| weekendDays | number[] | Array of day indices to mark as weekends (0-6) | -| selectedDate | Date (optional) | Currently selected date | -| rangeStart | Date (optional) | Start date for range selection | -| rangeEnd | Date (optional) | End date for range selection | -| onDateSelect | (date: Date) => void (optional) | Date selection callback | -| compact | boolean (optional) | Use compact layout | - -### Controls Component - -| Prop | Type | Description | -|------|------|-------------| -| headerStyle | HeaderStyle | Current header style | -| monthCutoff | MonthCutoffType | Current month cutoff type | -| onHeaderStyleChange | (type: HeaderStyle) => void | Header style change handler | -| onMonthCutoffChange | (type: MonthCutoffType) => void | Month cutoff change handler | - -## Styling - -The calendar uses styled-components for styling. You can customize the appearance by: - -1. Using the built-in props -2. Extending the styled components -3. Wrapping components with custom styled containers - -Example of custom styling: +### Compact Year View ```tsx -import styled from 'styled-components'; +import React from 'react'; import { Year } from './components/calendar/Year'; -const CustomCalendarContainer = styled.div` - padding: 2rem; - background: #fafafa; - - // Custom styles for the calendar - .month-title { - color: #1a73e8; - } -`; - -function App() { +function CompactYear() { return ( - - - + ); } ``` -## Header Styles +## Component Props + +### Year Component +```typescript +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; +} +``` -- **expanded**: Full day names (e.g., "MONDAY") -- **compacted**: Three-letter day names (e.g., "MON") -- **tiny**: Single letter day names (e.g., "M") -- **none**: No day headers, only numbers +### Month Component +```typescript +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; +} +``` -## Month Cutoff Options +## Styling -- **dimmed**: Show days from other months with reduced opacity -- **truncate**: Hide days from other months -- **undefined**: Show all days normally +The component uses SCSS modules for styling. Key style files: -## Browser Support +- `src/components/calendar/shared/_colors.scss`: Color variables +- `src/components/calendar/shared/_variables.scss`: Layout variables +- Individual component SCSS modules for specific styling -The calendar component supports all modern browsers: +## Browser Support - Chrome (latest) - Firefox (latest)