Calendar
Material Design 3 date picker with single, range, and multi-select modes. Year/month picker, US federal holidays, weekend blocking, min/max constraints, and full light/dark theming. 4 grouped input properties, 4 events, 5 outputs.
Import via Components → New component → Import from code → paste YAML
Preview
Select Date
Dec 26, 2025
Toggle features above to see how BlockFederalHolidays, DisableWeekends, and HighlightDates render
Installation
This component requires Modern controls to be enabled. Settings → Updates → Preview → Modern controls and themes
# In Power Apps Studio:
1. Components tab → New component → Import from code
2. Paste the full YAML definition
3. Component appears as "cmpCalendar" in library
4. Reset component on screen OnVisible to initialize stateUsage
Single date selection
// Named formula for default
DefaultDate = Today()
// Component properties
cmpCalendar.Selection = {DefaultDate: DefaultDate}
cmpCalendar.OnConfirm = Set(varConfirmedDate, cmpCalendar.SelectedDate)
// Display formatted result
lblDate.Text = Text(varConfirmedDate, "dddd, mmmm dd, yyyy")Date range selection
// Enable range mode
cmpCalendar.Settings = {
SelectRange: true,
Title: "Select Date Range"
}
cmpCalendar.Selection = {
DefaultDate: Today(),
DefaultEndDate: Today() + 7
}
// Filter data by selected range
Filter(
Orders,
OrderDate >= cmpCalendar.SelectedDate &&
OrderDate <= cmpCalendar.SelectedEndDate
)Business calendar (no weekends or holidays)
cmpCalendar.Selection = {
MinDate: Today(),
MaxDate: DateAdd(Today(), 90, Days),
DisableWeekends: true,
BlockFederalHolidays: true,
HighlightFederalHolidays: true
}
// Access the built-in holidays table
ForAll(
Filter(cmpCalendar.FederalHolidays, HolidayYear = 2026),
HolidayName & ": " & Text(HolidayDate, "mmm d")
)Multi-select mode
cmpCalendar.Settings = {
SelectMultiple: true,
Title: "Select Multiple Dates"
}
cmpCalendar.Selection = {
DefaultSelection: Table(
{Value: Date(2026, 3, 25)},
{Value: Date(2026, 3, 31)}
)
}
// Access all selected dates
ForAll(cmpCalendar.SelectedDates, Text(Value, "mmm dd"))Popup pattern (show/hide calendar)
// Text field opens calendar overlay
btnDateField.OnSelect = Set(varShowCalendar, true)
btnDateField.Text = If(
IsBlank(varSelectedDate),
"Select date...",
Text(varSelectedDate, "mmm d, yyyy")
)
// Calendar in overlay container
cmpCalendar.Visible = varShowCalendar
cmpCalendar.OnConfirm =
Set(varSelectedDate, cmpCalendar.SelectedDate);
Set(varShowCalendar, false)
cmpCalendar.OnCancel = Set(varShowCalendar, false)
cmpCalendar.OnClose = Set(varShowCalendar, false)Properties
Settings (Record)
| Property | Type | Default |
|---|---|---|
TitleHeader title text. | Text | "Select Date" |
DateFormattingDate display format string. | Text | "ddd dd mmm yy" |
FirstDayOfWeekStarting day: Sunday through Saturday. | Text | "Sunday" |
TodayStyleHow to highlight today: "circle", "bold", or "none". | Text | "circle" |
ShowHeaderDisplay title bar with selected date. | Boolean | true |
ShowFooterDisplay Cancel/OK buttons. | Boolean | true |
ShowCloseButtonDisplay X button in header. | Boolean | true |
ShowPaddingShow adjacent month dates in grid. | Boolean | true |
ShowTodayButtonShow go-to-today calendar icon. | Boolean | true |
SelectRangeEnable start/end date range mode. | Boolean | false |
SelectMultipleEnable multi-date selection mode. | Boolean | false |
AllowEmptySelectionAllow deselecting by re-clicking. | Boolean | true |
Selection (Record)
| Property | Type | Default |
|---|---|---|
DefaultDateInitially selected date. | Date | Today() |
DefaultEndDateInitial end date in range mode. | Date | Today() + 7 |
DefaultSelectionInitial dates in multi-select mode. | Table | [] |
MinDateEarliest selectable date. | Date | 1/1/1900 |
MaxDateLatest selectable date. | Date | 12/31/2100 |
BlockDatesSpecific dates to block (shown with strikethrough). | Table | [] |
DisableWeekendsBlock Saturday and Sunday. | Boolean | false |
BlockFederalHolidaysBlock all US federal holidays. | Boolean | false |
HighlightDatesDates to highlight with highlightFill color. | Table | [] |
HighlightFederalHolidaysHighlight US holidays with federalHolidayFill. | Boolean | false |
Other Input & Events
| Property | Kind | Description |
|---|---|---|
DarkMode | Input (Boolean) | Enable dark theme. Default false. |
Theme | Input (Table) | Color theme with light and dark mode records. 18 color properties + 6 SVG icons per mode. |
OnChange | Event | Fires on every date tap. Passes SelectedDate parameter. |
OnConfirm | Event | Fires when OK button pressed. |
OnCancel | Event | Fires when Cancel button pressed. |
OnClose | Event | Fires when X button pressed. |
Output
| Property | Type | Description |
|---|---|---|
SelectedDate | Date | Currently selected date (single and range start). |
SelectedEndDate | Date | End date in range mode. |
SelectedDates | Table | All selected dates in multi-select mode. |
FederalHolidays | Table | US federal holidays for displayed year ± 1 (HolidayName, HolidayDate, HolidayYear). |
ComponentHeight | Number | Total rendered height for dynamic container sizing. |
4 grouped input properties (Settings, Selection, Theme, DarkMode) + 4 events + 5 outputs. The grouped record pattern keeps the component API clean — instead of 28+ individual properties, configure just Settings and Selection records.
Theme Colors
The Theme property accepts a table with one record per mode. Each record defines 18 color properties and 6 SVG icon URIs. Override specific properties without redefining the entire table by usingPatch() orWith() to merge changes onto the defaults.
cmpCalendar.Theme = Table(
{
mode: "Light",
selectionFill: RGBA(30, 64, 175, 1), // Selected date circle
selectionColour: RGBA(255, 255, 255, 1), // Text on selected
todayBorderColour: RGBA(30, 64, 175, 1), // Today ring
buttonColour: RGBA(30, 64, 175, 1), // Button text
containerFill: RGBA(255, 255, 255, 1), // Card background
backgroundFill: RGBA(226, 232, 240, 1), // Range fill bg
titleColour: RGBA(15, 23, 42, 1), // Header text
textColour: RGBA(51, 65, 85, 1), // Day numbers
noteColour: RGBA(100, 116, 139, 1), // Day headers
lineColour: RGBA(203, 213, 225, 1), // Borders
highlightFill: RGBA(251, 191, 36, 0.25), // Custom highlights
federalHolidayFill: RGBA(239, 68, 68, 0.2), // Holiday highlights
hoverFill: RGBA(30, 64, 175, 0.1), // Hover state
rangeFill: RGBA(30, 64, 175, 0.15), // Range selection
...icons
},
{
mode: "Dark",
containerFill: RGBA(30, 41, 59, 1), // Slate-800
selectionFill: RGBA(59, 130, 246, 1), // Blue-500
// ... dark overrides
}
)Implementation Details
Grouped record properties
Instead of 28+ individual custom properties, configuration is organized into two records:Settings for display and behavior, andSelection for date constraints and defaults. This keeps the component panel clean and properties discoverable.
Year/month picker
Clicking the month name opens a scrollable year picker (100 years centered on current), then selecting a year transitions to a 3×4 month grid. This lets users jump to any date without arrow-clicking through dozens of months.
US federal holidays
All 11 US federal holidays are computed inline using date arithmetic — no external data source required. Fixed-date holidays (New Year's, Juneteenth, Independence Day, Veterans Day, Christmas) use Switch(Weekday(), 1, +1, 7, -1) for weekend observation rules. Floating holidays (MLK Day, Presidents Day, Memorial Day, Labor Day, Columbus Day, Thanksgiving) use modular arithmetic to find the Nth weekday of a month. The FederalHolidays output table covers the displayed year ± 1.
Range selection
Range mode tracks three variables:varCalendarSelDate (start),varCalendarEndDate (end), andvarCalendarThisDate (last click). Smart swap logic automatically corrects the order if the user clicks an earlier date second. Visual range fill is rendered by three parallel galleries: one for the main rows, and two narrow galleries for left/right edge fills at row boundaries.
Configurable week start
The FirstDayOfWeek setting accepts any day name and applies an offset to both the day-name header gallery and the date grid calculation via Mod(Value - 1 + _offset, 7).
Use OnConfirm over OnChange
OnChange fires on every date tap, which can cause excessive variable writes and downstream recalculation. For most use cases, wire your logic to OnConfirm instead — it only fires when the user presses OK, giving a clean commit point.
Examples
Business calendar with holidays blocked
cmpCalendar.Settings = {
Title: "Schedule Meeting"
}
cmpCalendar.Selection = {
MinDate: Today(),
MaxDate: DateAdd(Today(), 60, Days),
DisableWeekends: true,
BlockFederalHolidays: true,
HighlightFederalHolidays: true
}
cmpCalendar.OnConfirm =
Set(varMeetingDate, cmpCalendar.SelectedDate);
Navigate(ConfirmScreen)Hotel booking with date range
cmpCalendar.Settings = {
SelectRange: true,
Title: "Select Stay Dates"
}
cmpCalendar.Selection = {MinDate: Today()}
// Calculate nights and total
varNights = DateDiff(
cmpCalendar.SelectedDate,
cmpCalendar.SelectedEndDate,
TimeUnit.Days
)
lblTotal.Text = "$" & (varNights * 149)Date field with popup calendar
btnDateField.OnSelect =
Set(varShowCalendar, true)
btnDateField.Text = If(
IsBlank(varSelectedDate),
"Select date...",
Text(varSelectedDate, "mmm d, yyyy")
)
cmpCalendar.Visible = varShowCalendar
cmpCalendar.OnConfirm =
Set(varSelectedDate, cmpCalendar.SelectedDate);
Set(varShowCalendar, false)
cmpCalendar.OnCancel =
Set(varShowCalendar, false)Architecture
~30 controls — GroupContainers, Galleries, Labels, Images, Classic/Buttons, Rectangles, Circle.
320 × 540px default size. Height auto-adjusts based on ShowHeader/ShowFooter visibility.
Self-contained — all colors from Theme property, all holidays computed inline, no external dependencies.
cmpCalendar (320 × 540)
└── cntCalendar (GroupContainer, rounded card)
├── Fill: _CurrentTheme.containerFill
│
├── cntCalendarHeader (visible: ShowHeader)
│ ├── lblCalendarHeaderTitle ("SELECT DATE")
│ ├── lblCalendarHeaderDate (formatted selection)
│ ├── cntCalendarHeaderToday (go-to-today icon+button)
│ ├── cntCalendarHeaderClose (X icon+button → OnClose)
│ └── shpCalendarHeaderDivider (1px line)
│
├── cntCalendarInner
│ ├── cntCalendarOptions (month/year nav bar)
│ │ ├── cntCalendarOptionsMonth (month label + ▼ arrow)
│ │ ├── cntCalendarOptionsPrev (◄ button)
│ │ └── cntCalendarOptionsNext (► button)
│ │
│ ├── galCalendarDays (S M T W T F S header row)
│ │
│ ├── cntCalendarGrid (date cells)
│ │ ├── galCalendarRangeLeft (edge fills)
│ │ ├── galCalendarRows → galCalendarCells
│ │ │ ├── shpCalendarCellRangeFill (range bg)
│ │ │ ├── shpCalendarCellHighlight (highlight/holiday circle)
│ │ │ └── cntCalendarCell (selection circle + label + button)
│ │ └── galCalendarRangeRight (edge fills)
│ │
│ ├── cntCalendarYears (year picker grid)
│ │ └── galCalendarYears (100 years, 3-col wrap)
│ │
│ └── cntCalendarMonths (month picker grid)
│ └── galCalendarMonths (12 months, 3-col wrap)
│
└── cntCalendarFooter (visible: ShowFooter)
├── btnCalendarCancel → OnCancel
└── btnCalendarOK → OnConfirm