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.

cmpCalendar.yaml

Import via Components → New component → Import from code → paste YAML

Preview

Select Date

Dec 26, 2025

December 2025
S
M
T
W
T
F
S
HolidayWeekendHighlightSelected

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 state

Usage

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)

PropertyTypeDefault
Title

Header title text.

Text"Select Date"
DateFormatting

Date display format string.

Text"ddd dd mmm yy"
FirstDayOfWeek

Starting day: Sunday through Saturday.

Text"Sunday"
TodayStyle

How to highlight today: "circle", "bold", or "none".

Text"circle"
ShowHeader

Display title bar with selected date.

Booleantrue
ShowFooter

Display Cancel/OK buttons.

Booleantrue
ShowCloseButton

Display X button in header.

Booleantrue
ShowPadding

Show adjacent month dates in grid.

Booleantrue
ShowTodayButton

Show go-to-today calendar icon.

Booleantrue
SelectRange

Enable start/end date range mode.

Booleanfalse
SelectMultiple

Enable multi-date selection mode.

Booleanfalse
AllowEmptySelection

Allow deselecting by re-clicking.

Booleantrue

Selection (Record)

PropertyTypeDefault
DefaultDate

Initially selected date.

DateToday()
DefaultEndDate

Initial end date in range mode.

DateToday() + 7
DefaultSelection

Initial dates in multi-select mode.

Table[]
MinDate

Earliest selectable date.

Date1/1/1900
MaxDate

Latest selectable date.

Date12/31/2100
BlockDates

Specific dates to block (shown with strikethrough).

Table[]
DisableWeekends

Block Saturday and Sunday.

Booleanfalse
BlockFederalHolidays

Block all US federal holidays.

Booleanfalse
HighlightDates

Dates to highlight with highlightFill color.

Table[]
HighlightFederalHolidays

Highlight US holidays with federalHolidayFill.

Booleanfalse

Other Input & Events

PropertyKindDescription
DarkModeInput (Boolean)Enable dark theme. Default false.
ThemeInput (Table)Color theme with light and dark mode records. 18 color properties + 6 SVG icons per mode.
OnChangeEventFires on every date tap. Passes SelectedDate parameter.
OnConfirmEventFires when OK button pressed.
OnCancelEventFires when Cancel button pressed.
OnCloseEventFires when X button pressed.

Output

PropertyTypeDescription
SelectedDateDateCurrently selected date (single and range start).
SelectedEndDateDateEnd date in range mode.
SelectedDatesTableAll selected dates in multi-select mode.
FederalHolidaysTableUS federal holidays for displayed year ± 1 (HolidayName, HolidayDate, HolidayYear).
ComponentHeightNumberTotal 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

Schedule Meeting
Dec 26, 2025
S
M
T
W
T
F
S
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
HolidayWeekend
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

Check-in
Dec 18
Check-out
Dec 23
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
5 nights$745
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

Due Date
Dec 30, 2025
Click to open calendar picker
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