@lequyettien/angular-calendar
v1.0.1
Published
Modern Angular Calendar Component with TailwindCSS and multiple event dots support
Maintainers
Readme
Angular Calendar
A modern, lightweight calendar component for Angular with TailwindCSS styling and multiple event dot support.
✨ Features
- ✅ Standalone Component - Built with Angular's standalone API for easy integration
- ✅ Signals - Leverages Angular Signals for reactive state management
- ✅ TailwindCSS Styling - Beautiful, customizable design with TailwindCSS
- ✅ Multiple Event Dots - Display multiple events on the same day with different colors
- ✅ Internationalization - Support for English, Spanish, and Vietnamese
- ✅ Responsive Design - Works seamlessly across all screen sizes
- ✅ Accessible - Follows WCAG accessibility standards
- ✅ Fully Typed - Complete TypeScript support with strict mode
- ✅ Zero Dependencies - No external dependencies like moment.js or lodash
- ✅ Tree-shakeable - Optimized bundle size with modern build tools
📦 Installation
NPM
npm install @lequyettien/angular-calendarYarn
yarn add @lequyettien/angular-calendarPrerequisites
This package requires:
- Angular 18.0.0 or higher
- TailwindCSS 3.0.0 or higher
TailwindCSS Setup
If you don't have TailwindCSS installed in your Angular project:
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss initConfigure tailwind.config.js:
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./src/**/*.{html,ts}",
"./node_modules/@lequyettien/angular-calendar/**/*.{html,ts,js,mjs}"
],
theme: {
extend: {},
},
plugins: [],
}Add to src/styles.css:
@tailwind base;
@tailwind components;
@tailwind utilities;🚀 Quick Start
Basic Usage
Import the component in your Angular standalone component or module:
import { Component } from '@angular/core';
import { CalendarComponent, DateObj, SingularDate } from '@lequyettien/angular-calendar';
@Component({
selector: 'app-root',
standalone: true,
imports: [CalendarComponent],
template: `
<div class="container mx-auto p-4">
<h1 class="text-2xl font-bold mb-4">My Calendar</h1>
<ng-calendar
[events]="events"
[lang]="'en'"
(onDaySelect)="handleDaySelect($event)"
(onMonthSelect)="handleMonthChange($event)">
</ng-calendar>
</div>
`
})
export class AppComponent {
// Define events with colors
events: SingularDate[] = [
{ year: 2026, month: 1, date: 5, color: '#3b82f6' }, // Blue
{ year: 2026, month: 1, date: 5, color: '#ef4444' }, // Red (same day)
{ year: 2026, month: 1, date: 10, color: '#10b981' }, // Green
{ year: 2026, month: 1, date: 15, color: '#f59e0b' }, // Orange
{ year: 2026, month: 1, date: 15, color: '#8b5cf6' }, // Purple
{ year: 2026, month: 1, date: 15, color: '#ec4899' }, // Pink
{ year: 2026, month: 1, date: 20, color: '#14b8a6' }, // Teal
];
handleDaySelect(day: DateObj) {
console.log('Selected day:', day);
console.log('Events on this day:', day.eventDots);
}
handleMonthChange(event: { year: number; month: number }) {
console.log('Month changed:', event);
}
}Using with NgModule
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { CalendarComponent } from '@lequyettien/angular-calendar';
@NgModule({
imports: [
BrowserModule,
CalendarComponent // Import standalone component
],
// ...
})
export class AppModule { }📖 API Reference
Component Inputs
| Property | Type | Default | Description |
|----------|------|---------|-------------|
| events | SingularDate[] | [] | Array of events to display on the calendar |
| lang | string | 'en' | Language for month/day names ('en', 'es', 'vi') |
Component Outputs
| Event | Payload | Description |
|-------|---------|-------------|
| onDaySelect | DateObj | Emitted when a user selects a day |
| onMonthSelect | MonthChangeEvent | Emitted when the displayed month changes |
🎨 Customization
Custom Styling
You can customize the calendar appearance using TailwindCSS utility classes:
// Example: Change primary color from blue to purple
<ng-calendar
class="[&_.bg-blue-500]:bg-purple-500 [&_.ring-blue-500]:ring-purple-500">
</ng-calendar>💡 Advanced Examples
Loading Events from an API
import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { CalendarComponent, SingularDate, DateObj } from '@lequyettien/angular-calendar';
@Component({
selector: 'app-event-calendar',
standalone: true,
imports: [CalendarComponent, HttpClientModule],
template: `
<ng-calendar
[events]="events"
[lang]="'en'"
(onDaySelect)="showEventDetails($event)">
</ng-calendar>
`
})
export class EventCalendarComponent implements OnInit {
events: SingularDate[] = [];
constructor(private http: HttpClient) {}
ngOnInit() {
this.loadEvents();
}
loadEvents() {
this.http.get<any[]>('/api/events').subscribe(apiEvents => {
this.events = apiEvents.map(event => ({
year: new Date(event.date).getFullYear(),
month: new Date(event.date).getMonth(),
date: new Date(event.date).getDate(),
color: event.type === 'meeting' ? '#3b82f6' : '#10b981'
}));
});
}
showEventDetails(day: DateObj) {
if (day.hasEvent) {
console.log(`Found ${day.eventDots?.length} events on this day`);
// Show modal or navigate to event details
}
}
}Multiple Calendars Side by Side
import { Component } from '@angular/core';
import { CalendarComponent, SingularDate } from '@lequyettien/angular-calendar';
@Component({
selector: 'app-multi-calendar',
standalone: true,
imports: [CalendarComponent],
template: `
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<h2 class="text-lg font-semibold mb-2">Personal</h2>
<ng-calendar [events]="personalEvents" [lang]="'en'"></ng-calendar>
</div>
<div>
<h2 class="text-lg font-semibold mb-2">Work</h2>
<ng-calendar [events]="workEvents" [lang]="'en'"></ng-calendar>
</div>
</div>
`
})
export class MultiCalendarComponent {
personalEvents: SingularDate[] = [
{ year: 2026, month: 1, date: 14, color: '#ec4899' }, // Valentine's Day
{ year: 2026, month: 1, date: 20, color: '#10b981' }, // Birthday
];
workEvents: SingularDate[] = [
{ year: 2026, month: 1, date: 5, color: '#3b82f6' }, // Team Meeting
{ year: 2026, month: 1, date: 15, color: '#ef4444' }, // Project Deadline
];
}📝 TypeScript Interfaces
/**
* Represents a single day in the calendar grid
*/
interface DateObj {
year: number;
month: number;
date: number;
isThisMonth: boolean;
isToday?: boolean;
isSelect?: boolean;
hasEvent?: boolean;
eventDots?: string[]; // Array of color hex codes for multiple events
}
/**
* Represents a single event on the calendar
*/
interface SingularDate {
year: number;
month: number; // 0-11 (JavaScript Date convention)
date: number; // 1-31
color?: string; // Hex color code (e.g., '#3b82f6')
}
/**
* Event emitted when the displayed month changes
*/
interface MonthChangeEvent {
year: number;
month: number; // 0-11
}🌐 Internationalization
The calendar supports multiple languages out of the box:
- English (
en) - Default - Spanish (
es) - Vietnamese (
vi)
To add a new language, you can extend the weekHeads and monthNames objects in your component or create a custom pipe.
🎯 Key Features Explained
Multiple Event Dots
Display multiple events on the same day with different colors:
events: SingularDate[] = [
{ year: 2026, month: 1, date: 15, color: '#3b82f6' }, // Blue dot
{ year: 2026, month: 1, date: 15, color: '#ef4444' }, // Red dot (same day)
{ year: 2026, month: 1, date: 15, color: '#10b981' }, // Green dot (same day)
];Up to 3 dots will be displayed on a single day. If there are more events, they will still be tracked in the eventDots array.
Angular Signals
The component uses Angular Signals for reactive state management, providing better performance and cleaner code:
displayYear = signal(this.currentYear);
displayMonth = signal(this.currentMonth);
weekHead = computed(() => this.weekHeads[this.lang] || this.weekHeads['en']);Zero Dependencies
Unlike many calendar libraries, this component has no runtime dependencies. It uses native JavaScript Date APIs instead of libraries like moment.js or date-fns, resulting in a smaller bundle size.
🏗️ Project Structure
@lequyettien/angular-calendar/
├── src/
│ ├── calendar.component.ts # Main calendar component
│ ├── calendar.component.html # Calendar template
│ ├── calendar.component.css # Calendar styles
│ ├── calendar.types.ts # TypeScript interfaces
│ ├── month-name.pipe.ts # Month name transformation pipe
│ ├── calendar-example.component.ts # Example usage component
│ └── index.ts # Public API
├── dist/ # Built package
├── README.md
├── package.json
└── ng-package.json🔧 Development
Prerequisites
- Node.js 18.x or higher
- Angular CLI 18.x or higher
Build
npm run buildPack for testing
npm run packThis will create a .tgz file in the dist folder that you can install locally for testing.
🤝 Contributing
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
📄 License
MIT License - see the LICENSE file for details.
🙏 Acknowledgments
Built with modern Angular features and TailwindCSS for a clean, performant calendar solution.
📞 Support
- Issues: GitHub Issues
- Discussions: GitHub Discussions
🚀 Roadmap
- [ ] Drag and drop support for events
- [ ] Week view and day view modes
- [ ] Custom event templates
- [ ] Date range selection
- [ ] Keyboard navigation improvements
- [ ] Dark mode support
- [ ] More language support
Made with ❤️ using Angular and TailwindCSS
