NewPower Apps · canvas componentData display✓ Tested in StudioMIT License
Month calendar
A month grid from your start of week, events from a table as pills that run across the days they span, +N more past a limit, today marked, a day or an event selectable, previous, next and Today; light and dark, the pills drawing in when the month changes.
- Name in Studio
- lcsMonthCalendar
- Version
- 0.1.0
- Properties
- 9 inputs · 3 outputs · 3 events · 5 actions
Variations
As it is when you paste it, with every input at its default.
October 2026
VisibleMonth: 1 Oct 2026 · SelectedDate: blank · EventsInMonth: 8
Formulas on this screen
Set the same ones in Studio to try it the same way; there, each Notify shows its event in a banner, which this preview leaves out so nothing covers the component. The instance names are the ones Studio gives the first copy on a screen.
lcsMonthCalendar_1.OnSelectDay = Notify("Day: " & Text(SelectedDate, "d mmm"))
lcsMonthCalendar_1.OnSelectEvent = Notify("Event: " & Title)
lcsMonthCalendar_1.OnMonthChange = ClearCollect(colBookings, Filter(Bookings, 'End date' >= Month && 'Start date' < DateAdd(Month, 1, TimeUnit.Months)))
A web replica that behaves as the component does in Power Apps. In Studio it uses Microsoft's controls, which can look slightly different.
Add it in five steps
- In Power Apps Studio, open Settings > Updates and check that Modern controls and themes and Enhanced component properties are on.
- Open the Components tab in the tree view and select New component.
- Select an empty part of Studio, so the new component isn't selected.
- Copy the YAML on this page and press Ctrl+V.
lcsMonthCalendarappears with all its properties. - On a screen, insert it from Insert > Custom >
lcsMonthCalendar.
What it needs
- No premium licence: standard controls, no connectors
- Modern controls and themes: on
- Enhanced component properties: on
- Tested in Power Apps Studio 3.26094.9 on October 17, 2026
- Version 0.1.0
Properties (20)
Read from the component's own YAML, so they always match what you paste.
| Property | Kind | Type | Default |
|---|---|---|---|
EventsThe events, as a table with Key, Title, Start (a date), End (a date, the same as Start for one day) and Color (a hex, or empty for your accent) columns. | Input | Table | Table({Key: "e1", Title: "Fire drill", Start: Today(), End: Today(), Color: "#c50f1f"}, {Key: "e2", Title: "Site survey", Start: DateAdd(Today(), 1, TimeUnit.Days), End: DateAdd(Today(), 1, TimeUnit.Days), Color: ""}, {Key: "e3", Title: "Projector install", Start: DateAdd(Today(), 3, TimeUnit.Days), End: DateAdd(Today(), 5, TimeUnit.Days), Color: "#7c3aed"}, {Key: "e4", Title: "Board visit", Start: DateAdd(Today(), -2, TimeUnit.Days), End: DateAdd(Today(), -2, TimeUnit.Days), Color: "#107c10"}, {Key: "e5", Title: "Floor closed", Start: DateAdd(Today(), 8, TimeUnit.Days), End: DateAdd(Today(), 9, TimeUnit.Days), Color: "#c19c00"}, {Key: "e6", Title: "Audit", Start: DateAdd(Today(), 1, TimeUnit.Days), End: DateAdd(Today(), 1, TimeUnit.Days), Color: "#0e7490"}, {Key: "e7", Title: "Deliveries", Start: DateAdd(Today(), 1, TimeUnit.Days), End: DateAdd(Today(), 1, TimeUnit.Days), Color: ""}, {Key: "e8", Title: "Training", Start: DateAdd(Today(), 1, TimeUnit.Days), End: DateAdd(Today(), 1, TimeUnit.Days), Color: "#be185d"}) |
DefaultMonthAny date in the month to show first. The person moves months from there; GoToMonth moves them from your app. | Input | DateAndTime | Today() |
StartOfWeekMonday or Sunday, the first column. | Input | Text | "Monday" |
MaxPerDayHow many event pills a day shows before +N more. | Input | Number | 3 |
CellHeightEach day's height. 88 fits three pills; add 20 for each more. | Input | Number | 88 |
ShowTodayShows the Today button in the header. | Input | Boolean | true |
AccentColorYour brand colour, for today's mark, the selected day, events without a colour and the focus rings. | Input | Color | RGBA(15, 108, 189, 1) |
ThemeLight, or Dark for a dark screen. | Input | Text | "Light" |
MotionThe event pills draw in from the left when the month changes, and the selected day's ring pops in. None plays for people who've asked their device for reduced motion. | Input | Boolean | true |
| Property | Kind | Type | Default |
|---|---|---|---|
VisibleMonthThe first day of the month on show. | Output | DateAndTime | — |
SelectedDateThe selected day; blank when none. | Output | DateAndTime | — |
EventsInMonthHow many events touch the month on show. | Output | Number | — |
| Property | Kind | Type | Default |
|---|---|---|---|
OnSelectDay(SelectedDate)Runs in your app when a day is selected, with its date. Open a new-event form here.
| Event | — | false |
OnSelectEvent(Key, Title, Start)Runs in your app when an event pill is selected, with its key, title and start.
| Event | — | false |
OnMonthChange(Month)Runs in your app when the month on show changes, with its first day. Load that month's events here.
| Event | — | false |
| Property | Kind | Type | Default |
|---|---|---|---|
Next()Shows the next month. | Action | — | — |
Previous()Shows the month before. | Action | — | — |
GoToToday()Shows this month and selects today. | Action | — | — |
GoToMonth(Month)Shows the month of a date.
| Action | — | — |
Select(SelectedDate)Selects a day from your app, moving to its month if needed, without raising OnSelectDay.
| Action | — | — |
Guide
Use lcsMonthCalendar for bookings, shifts, leave, deadlines, visits: anything people want to see by month. Every calendar in a canvas app is rebuilt from a 42-cell gallery and a weekday offset, and the hard part, an event that runs across several days, is usually given up on. This component is that calendar done once:
- A month grid from any date, with the week starting on Monday or Sunday, the days outside the month greyed, and today marked;
- Events from a table of
Key,Title,Start,EndandColor, drawn as pills that run across the days they span, rounded only at their ends, the title on the first day and at the start of each week; MaxPerDaypills a day, then "+2 more" beside the day's number;- Previous, next and Today,
GoToMonthandSelectfrom your app, andOnMonthChangeso you load one month's events at a time; OnSelectDay(SelectedDate)for a new booking on that day, andOnSelectEvent(Key, Title, Start)to open one.
The examples call it calRooms on a bookings screen.
Adding events to a day. The calendar draws exactly the rows in its Events table, so to put an event (or several) on a date, add rows to the collection it reads. Selecting a day runs OnSelectDay with that date, which is the place to add one, or to open your own form first:
// Screen.OnVisible: start a collection for the calendar to read
ClearCollect(colEvents, Table({Key: "e1", Title: "Fire drill", Start: Today(), End: Today(), Color: "#c50f1f"}))
// calRooms.Events
colEvents
// calRooms.OnSelectDay: a new event on the day selected; select again and they stack
Collect(colEvents, {Key: Text(GUID()), Title: "New booking", Start: SelectedDate, End: SelectedDate, Color: "#0f6cbd"})
// An event over three days: End two days after Start
Collect(colEvents, {Key: Text(GUID()), Title: "Training", Start: SelectedDate, End: DateAdd(SelectedDate, 2, TimeUnit.Days), Color: "#7c3aed"})
A day shows up to MaxPerDay events, then "+N more". Remove one from OnSelectEvent with Remove(colEvents, LookUp(colEvents As e, e.Key = Key)), or save to your data source with Patch and refresh the collection.
One month's bookings at a time, from Dataverse:
// Screen.OnVisible, and calRooms.OnMonthChange
ClearCollect(
colBookings,
ForAll(
Filter(Bookings, 'End date' >= calRooms.VisibleMonth && 'Start date' < DateAdd(calRooms.VisibleMonth, 1, TimeUnit.Months)) As b,
{Key: Text(b.Booking), Title: b.Room.Name & ": " & b.Title, Start: b.'Start date', End: b.'End date', Color: ""}
)
)
// calRooms.Events
colBookings
A new booking on the day selected, and opening an existing one:
// calRooms.OnSelectDay
Navigate(scrNewBooking, ScreenTransition.None, {day: SelectedDate})
// calRooms.OnSelectEvent
Navigate(scrBooking, ScreenTransition.None, {ID: GUID(Key)})
Colour by room:
// In the ForAll above
Color: Switch(b.Room.Name, "Room 4", "#0f6cbd", "Room 7", "#7c3aed", "#616161")
Jump to a date from a date picker:
// dpJump.OnChange
calRooms.Select(dpJump.SelectedDate)
- Columns.
Eventswants exactlyKey,Title,Start,EndandColor; build the rows withForAllas in Use it.StartandEndare dates; a date-and-time column works too, because the calendar compares the date part only. - One month at a time. The filter in
OnMonthChangeis delegable (two date comparisons), so the app only ever holds a month of rows, and the 42 cells each filter that small table. - Multi-day events need an
Endon or afterStart; for a one-day event, set both the same. An event that runs past the month's edge shows on the days inside it and carries on next month. - Time zones. Date-only columns are safe. A date-and-time column set to user local shows on the day it falls for the person; one set to time-zone independent shows the stored day.
- The grid is a group named by the month, inside which each day is a button named "Tuesday 13 October, today, 2 events, selected"; each pill is a button named by the event's title and dates; the weekday row is a group. Tab moves through the days and the pills in order; Enter and Space select.
- Today has a filled circle behind its number; the selected day has a tinted cell and a ring, and "selected" in its name; the pills are colour and title, so nothing is colour alone.
- With
Motionon, the pills draw in from the left when the month changes, and the selected day's ring pops in. None plays for people who've asked their device for reduced motion, andMotionoff draws them at once.
- Each day shows
MaxPerDaypills; the rest fold into "+N more", and selecting the day is how to see them (open the day's list fromOnSelectDay). - A pill's title shows on the event's first day and at the start of each week, so a long event never has an unlabelled row; the title is cut at the cell's edge, and the full title is in the pill's name and tooltip.
- The pills are drawn in the order your table gives them; sort
EventsbyStartfor a tidy stack. - No week or day view, and no drag to move an event;
OnSelectEventopens it and your form moves it.
- 0.1.0: first version: the month grid, events as spanning pills, +N more, today, selection, previous, next, Today,
GoToMonth,Select,OnSelectDay,OnSelectEvent,OnMonthChange, the outputs, light and dark, the pill and ring motion.
Did it work for you?
No ratings yet.Nobody has said it worked in their app yet.
Sign in to rate it or to say it worked in your app.
Comments
No comments yet. Share how you used it, or ask something.
Sign in to comment or reply. Comments show under a display name you choose, never your email.