Event Badges
Show an icon and label badge in the top-left corner of Week view event cards — including badgeId for JSON APIs.
Event Badges
You can attach a badge to any CalendarEvent to display a small icon and label in the top-left corner of the event card in Week view.
This is useful for marking lesson types (private / group / package), online sessions, exams, and more.
Badge model
interface EventBadge {
icon: React.ReactNode; // e.g. a Lucide icon or any JSX
name: string; // short label shown next to the icon
}
interface CalendarEvent {
// ...
badge?: EventBadge; // client-side full badge (JSX)
badgeId?: BuiltInEventBadgeId; // JSON-safe key from the backend (recommended)
}Week view resolves
badgeorbadgeId. If both are set,badgewins.
Backend data (badgeId) — recommended
Icons are React nodes and cannot come from a JSON API. Send a string badgeId instead; Week view resolves it to icon + label automatically.
API response example
{
"id": "3",
"title": "Paket: 10. Ders",
"start": "2026-07-21T14:00:00",
"end": "2026-07-21T15:00:00",
"badgeId": "packageLesson"
}Client mapping
import type { CalendarEvent } from 'calendarkit-prov2';
const event: CalendarEvent = {
id: api.id,
title: api.title,
start: new Date(api.start),
end: new Date(api.end),
badgeId: api.badgeId, // e.g. "packageLesson"
};No need to call EVENT_BADGES or attach JSX — badgeId is enough.
Full badgeId catalog (JSON)
[
{ "badgeId": "privateLesson", "name": "Özel Ders", "nameEn": "Private" },
{ "badgeId": "groupLesson", "name": "Grup Ders", "nameEn": "Group" },
{ "badgeId": "packageLesson", "name": "Paket Ders", "nameEn": "Package" },
{ "badgeId": "online", "name": "Online", "nameEn": "Online" },
{ "badgeId": "inPerson", "name": "Yüz Yüze", "nameEn": "In Person" },
{ "badgeId": "homeVisit", "name": "Evde", "nameEn": "At Home" },
{ "badgeId": "trial", "name": "Deneme", "nameEn": "Trial" },
{ "badgeId": "makeup", "name": "Telafi", "nameEn": "Makeup" },
{ "badgeId": "exam", "name": "Sınav", "nameEn": "Exam" },
{ "badgeId": "workshop", "name": "Workshop", "nameEn": "Workshop" },
{ "badgeId": "priority", "name": "Öncelikli", "nameEn": "Priority" },
{ "badgeId": "holiday", "name": "Tatil", "nameEn": "Holiday" },
{ "badgeId": "cancelled", "name": "İptal", "nameEn": "Cancelled" },
{ "badgeId": "listening", "name": "Dinleme", "nameEn": "Listening" }
]Optional helpers
import {
resolveEventBadge,
getEventBadge,
isBuiltInEventBadgeId,
} from 'calendarkit-prov2';
// Resolve for custom UI outside Week view
const badge = resolveEventBadge(event, 'tr');
// Build a badge manually
getEventBadge('packageLesson', 'tr');
getEventBadge('groupLesson', 'en', 'Group A1'); // custom label
// Validate API string
if (isBuiltInEventBadgeId(api.badgeId)) {
event.badgeId = api.badgeId;
}Built-in presets (client-only)
If you build events entirely on the client (no API), you can attach a full badge object:
import { EVENT_BADGES, getEventBadge } from 'calendarkit-prov2';
import type { CalendarEvent } from 'calendarkit-prov2';
const event: CalendarEvent = {
id: '1',
title: 'Ayşe Yılmaz',
start: new Date('2026-07-21T09:00:00'),
end: new Date('2026-07-21T10:00:00'),
badge: EVENT_BADGES.privateLesson, // Özel Ders
};Available ids (table)
| Id | TR label | EN label |
|---|---|---|
privateLesson | Özel Ders | Private |
groupLesson | Grup Ders | Group |
packageLesson | Paket Ders | Package |
online | Online | Online |
inPerson | Yüz Yüze | In Person |
homeVisit | Evde | At Home |
trial | Deneme | Trial |
makeup | Telafi | Makeup |
exam | Sınav | Exam |
workshop | Workshop | Workshop |
priority | Öncelikli | Priority |
holiday | Tatil | Holiday |
cancelled | İptal | Cancelled |
listening | Dinleme | Listening |
import type { BuiltInEventBadgeId } from 'calendarkit-prov2';Custom badge (any icon)
import { Video } from 'lucide-react';
import type { CalendarEvent } from 'calendarkit-prov2';
const event: CalendarEvent = {
id: '1',
title: 'Project Review',
start: new Date('2026-07-21T10:00:00'),
end: new Date('2026-07-21T12:00:00'),
color: '#3b82f6',
badge: {
icon: <Video className="w-2.5 h-2.5" />,
name: 'Online',
},
};Display behavior
| Card height | What is shown |
|---|---|
| Normal (≥ 60 min) | Icon + name in the top-left corner |
| Short (< 60 min) | Icon only (name available via tooltip) |
The event title and time shift slightly downward so they do not overlap the badge.
Full example (API-style badgeId)
'use client';
import { useState } from 'react';
import { ProScheduler, DATE_FNS_LOCALES } from 'calendarkit-prov2';
import type { CalendarEvent, LanguageCode } from 'calendarkit-prov2';
import { addHours, addDays, startOfWeek } from 'date-fns';
const weekStart = startOfWeek(new Date());
// Same shape as a backend payload — only badgeId, no JSX
const defaultEvents: CalendarEvent[] = [
{
id: '1',
title: 'Ayşe Yılmaz',
start: addHours(addDays(weekStart, 1), 9),
end: addHours(addDays(weekStart, 1), 10),
color: '#3b82f6',
badgeId: 'privateLesson',
},
{
id: '2',
title: 'A1 İngilizce',
start: addHours(addDays(weekStart, 1), 11),
end: addHours(addDays(weekStart, 1), 12.5),
color: '#8b5cf6',
badgeId: 'groupLesson',
},
{
id: '3',
title: 'Paket: 10. Ders',
start: addHours(addDays(weekStart, 2), 14),
end: addHours(addDays(weekStart, 2), 15),
color: '#10b981',
badgeId: 'packageLesson',
},
{
id: '4',
title: 'Zoom – Mehmet K.',
start: addHours(addDays(weekStart, 3), 9),
end: addHours(addDays(weekStart, 3), 10),
color: '#3b82f6',
badgeId: 'online',
},
];
export default function BadgeExample() {
const [events] = useState<CalendarEvent[]>(defaultEvents);
const [date, setDate] = useState(new Date());
const [lang] = useState<LanguageCode>('tr');
return (
<div className="h-[700px] border rounded-xl overflow-hidden">
<ProScheduler
view="week"
events={events}
date={date}
onDateChange={setDate}
language={lang}
locale={DATE_FNS_LOCALES[lang]}
/>
</div>
);
}Notes
- Badges are currently rendered in Week view event cards.
- Prefer
badgeIdwhen events come from a backend (JSON-safe). - Prefer
EVENT_BADGES.*/ custom{ icon, name }only for client-built events. - Use
getEventBadge(id, language)when you need a localized badge outside Week view. - Keep labels short so they fit inside narrow week columns.