feat: proper readme
continuous-integration/drone/push Build is passing Details

master
Guillermo Pages 10 months ago
parent 847294d826
commit bc2c3b5474

@ -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 ## Features
- 📅 Year, month, and week views - 📅 Multiple calendar views:
- 🎨 Multiple header styles (expanded, compacted, tiny, none) - Full year view with configurable month grid
- 🎯 Customizable month cutoff behavior - Single month view with customizable layout
- 🎭 Weekend highlighting - Week view with interactive options
- 📱 Fully responsive design - Date range picker with hover preview
- 🔧 TypeScript support - 🎨 Visual customization:
- 💅 Styled with styled-components - 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 ## Installation
```bash ```bash
npm install date-fns styled-components npm install
```
## Development
```bash
npm run dev
``` ```
## Basic Usage ## Usage Examples
### Date Range Picker
```tsx ```tsx
import React, { useState } from 'react';
import { Year } from './components/calendar/Year'; 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
};
});
};
function App() {
return ( return (
<Year <Year
year={2024} year={2024}
dayHeaderStyle="tiny" dayHeaderStyle="tiny"
weekendDays={[6, 0]} // Saturday and Sunday monthCutoff="truncate"
weekendDays={[6, 0]}
dateRange={dateRange}
onDateSelect={handleDateSelect}
onDateHover={(date) => setDateRange(prev => ({ ...prev, hoverDate: date }))}
size="l"
fontProportion={100}
magnify={true}
/> />
); );
} }
``` ```
## Advanced Usage ### Single Month View
### With Date Selection
```tsx ```tsx
import { useState } from 'react'; import React from 'react';
import { Year } from './components/calendar/Year'; import { Month } from './components/calendar/Month';
function App() {
const [selectedDate, setSelectedDate] = useState<Date | undefined>();
function SingleMonth() {
return ( return (
<Year <Month
year={2024} date={new Date()}
dayHeaderStyle="expanded" dayHeaderStyle="expanded"
monthCutoff="truncate" direction="column"
monthCutoff="dimmed"
weekendDays={[6, 0]} weekendDays={[6, 0]}
selectedDate={selectedDate} size="xl"
onDateSelect={setSelectedDate} fontProportion={100}
/> />
); );
} }
``` ```
### With Controls ### Week View
```tsx ```tsx
import { useState } from 'react'; import React from 'react';
import { Year } from './components/calendar/Year'; import { Week } from './components/calendar/Week';
import { Controls } from './components/calendar/Controls';
import { HeaderStyle, MonthCutoffType } from './types/calendar';
function App() {
const [headerStyle, setHeaderStyle] = useState<HeaderStyle>('tiny');
const [monthCutoff, setMonthCutoff] = useState<MonthCutoffType>('truncate');
function WeekView() {
return ( return (
<> <Week
<Controls startDate={new Date()}
headerStyle={headerStyle} headerStyle="compacted"
monthCutoff={monthCutoff} referenceMonth={new Date().getMonth()}
onHeaderStyleChange={setHeaderStyle} weekendDays={[6, 0]}
onMonthCutoffChange={setMonthCutoff} size="l"
/> fontProportion={100}
<Year />
year={2024}
dayHeaderStyle={headerStyle}
monthCutoff={monthCutoff}
weekendDays={[6, 0]}
/>
</>
); );
} }
``` ```
## Component Props ### Compact Year View
### 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:
```tsx ```tsx
import styled from 'styled-components'; import React from 'react';
import { Year } from './components/calendar/Year'; import { Year } from './components/calendar/Year';
const CustomCalendarContainer = styled.div` function CompactYear() {
padding: 2rem;
background: #fafafa;
// Custom styles for the calendar
.month-title {
color: #1a73e8;
}
`;
function App() {
return ( return (
<CustomCalendarContainer> <Year
<Year year={2024}
year={2024} dayHeaderStyle="tiny"
dayHeaderStyle="tiny" monthCutoff="truncate"
/> weekendDays={[6, 0]}
</CustomCalendarContainer> size="xs"
fontProportion={80}
magnify={true}
/>
); );
} }
``` ```
## 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") ### Month Component
- **compacted**: Three-letter day names (e.g., "MON") ```typescript
- **tiny**: Single letter day names (e.g., "M") interface MonthProps {
- **none**: No day headers, only numbers 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 The component uses SCSS modules for styling. Key style files:
- **truncate**: Hide days from other months
- **undefined**: Show all days normally
## 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) - Chrome (latest)
- Firefox (latest) - Firefox (latest)

Loading…
Cancel
Save