A "GitHub Contribution/Activity" like calendar widget, that can be used as native components of React, Vue, Svelte, Solid and Qwik. You can used it with the GitHub activity API or to display any activity data.
Activity Calendar Widget is built with Mitosis (with a little modifications), which aims to "Write components once, compile to every framework". Interested to learn more? Here is a walkthrough of building a "simplied" Activity Calendar Widget.
Credits: The API of Activity Calendar Widget is highly influenced by React Activity Calendar. React Activity Calendar is a great component library, which provides more granular options in certain areas.
npm i activity-calendar-widget
It can then be imported in various frameworks like...
// React
import ActivityCalendarWidget from 'activity-calendar-widget/react';
// Vue
import ActivityCalendarWidget from 'activity-calendar-widget/vue';
// Svelte
import ActivityCalendarWidget from 'activity-calendar-widget/svelte';
// Solid
import ActivityCalendarWidget from 'activity-calendar-widget/solid';
// Qwik
import ActivityCalendarWidget from 'activity-calendar-widget/qwik';
<ActivityCalendarWidget
daysToRender={150}
data={[
{ date: '2023-04-05', activities: [{}, {}, {}, {}] },
{ date: '2023-04-07', activities: [{}] },
{ date: '2023-04-08', activities: [{}, {}, {}] },
]}
/>
Props name | Type | Default | Description |
---|---|---|---|
data | array of Data |
[] | The activity data array. It accepts the date and activities fields. |
clickHandler | Function(dateInfo: DateInfo ) => {} |
undefined | The activity data array. It accepts the date and activities fields. |
daysToRender | number | 365 (+ 0 to 6 days more). See more the description | When daysToRender isn't specified, at least 365 days from today will be rendered, while the leftmost (oldest) column will also be filled up entirely.When daysToRender is specified, activity-calendar-widget will render the exact number of daysToRender from today. |
mode | string | 'day' |
Options: 'day' / 'week' / 'month' .Note: Only day is supported currently. See roadmap for more info. |
showSummary | boolean | true | If set to true , a summary of "26 activities in this period" will be displayed in the bottom left of the component. |
summaryText | string | '{{count}} activities in this period' |
The customized summary text with placeholder {{count}} |
showLevels | boolean | true | If set to true , a level legend will be displayed in the bottom right of the component. |
levelColorMode | string | 'light' |
Options: 'light' / 'dark' . It changes the color palette of the level legend, like the screenshots at the top.If levelColorMode is used together with levelColors , levelColorMode will be ignored and ONLY levelColor will be used. |
levelColors | array of string | undefined |
If levelColors is used together with levelColorMode , levelColorMode will be ignored and ONLY levelColor will be used. E.g. ['white', 'rgba(0, 0, 0, 0.2'), '#a6a6a6'] |
levelLabelLess | string | 'Less' |
The "Less" label of the level legend |
levelLabelMore | string | 'More' |
The "More" label of the level legend |
showTooltip | boolean | true | If set to true , when users hover the date box, a tooltip of "2 activities on Apr 11, 2023" will be displayed. |
tooltipBgColor | string | 'rgba(0, 0, 0, 0.8)' |
The tooltip background color |
tooltipTextColor | string | '#e4e8ec' |
The tooltip text color |
weekStart | number | 0 | Options: 0 / 1 / 2 / 3 / 4 / 5 / 6 The week start with: 0 : Sun1 : Mon2 : Tue3 : Wed4 : Thu5 : Fri6 : Sat |
showWeekdayLabels | boolean | true | If set to true , the left weekday labels will be displayed. |
weekdayLabel | WeekdayLabel |
{} | By default, the widget only displays Mon , Wed and Fri . If the allowed keys in weekdayLabel is provided e.g. { 0: '日曜日' } , the week value will be overwritten.Note: To provide custom value for Sunday, provide value to 0 e.g. { 0: '日曜日' } . |
showMonthLabels | boolean | true | If set to true , the top month labels will be displayed. |
monthLabel | MonthLabel |
{} | By default, all months will be displayed. If the allowed keys in monthLabel is provided e.g. { 1: '1월' } , the month value will be overwritten. |
Fields | Type | Format | Description |
---|---|---|---|
id | string | yyyy-MM-dd |
The date being clicked |
year | number | yyyy |
The year of the date box being clicked |
month | number | MM |
The month of the date box being clicked |
day | number | dd |
The day of the date box being clicked |
dayOfWeek | number | 0-6 |
The day of week of the date box being clicked0 : Sun1 : Mon2 : Tue3 : Wed4 : Thu5 : Fri6 : Sat |
dayDiffFromToday | number | >= 0 |
Numebrs of days from today |
activities | array of any |
[] |
Each item inside the activities array will count as 1 activity. The format is arbitary here. You can pass { "type": "PushEvent" } or 'PullRequestEvent' or anything. |
level | number | >= 0 |
If no custom levelColors is passed, level will be 0-4 . 0 means no activities and 4 means the tier of having the most activities.If custom levelColors is passed, level will be 0 to length of levelColors - 1 . |
<ActivityCalendarWidget
clickHandler={(dateInfo) => console.log({ dateInfo })}
/>
{
"id": "2023-04-16",
"year": 2023,
"month": 4,
"day": 16,
"dayOfWeek": 0,
"dayDiffFromToday": 0,
"activities": [
...
],
"level": 2
}
Field | Type | Format | Description |
---|---|---|---|
date | string | yyyy-MM-dd |
The date which contains 0 or more activities. E.g. '2023-04-05' |
activities | array of any |
[] |
Each item inside the activities array will count as 1 activity. The format is arbitary here. You can pass { "type": "PushEvent" } or 'PullRequestEvent' or anything.If you pass a clickHandler and you clicked the date box, the clickHandler callback will be executed with the activities . |
[
{ date: '2023-04-05', activities: [{}, {}, {}, {}] },
{ date: '2023-04-07', activities: [{}] },
{ date: '2023-04-08', activities: [{}, {}, {}] }
]
type WeekdayKey = 0 | 1 | 2 | 3 | 4 | 5 | 6;
export type WeekdayLabel = Record<WeekdayKey, string>;
{
0: '日曜日',
1: '月曜日',
2: '火曜日',
3: '水曜日',
4: '木曜日',
5: '金曜日',
6: '土曜日',
}
type MonthKey = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
export type MonthLabel = Record<MonthKey, string>;
{
1: '1월',
2: '2월',
3: '3월',
// ...
10: '10월',
11: '11월',
12: '12월',
}
- Support
mode={'month'}
- Support
mode={'week'}
- (One off) Install dependencies of the Mitosis component and the test app
npm install
cd test-app
npm install
- In the root directory, watch and re-build changes in
/src
.
npm run start
- In another terminal, run the test-app (an Astro app that have
react
,solid
,svelte
andvue
baked in)
cd test-app
npm run start