diff --git a/angular/src/directives/proxies.ts b/angular/src/directives/proxies.ts
index e0a36eb59a9..32d31f9414b 100644
--- a/angular/src/directives/proxies.ts
+++ b/angular/src/directives/proxies.ts
@@ -524,14 +524,14 @@ export declare interface IonDatetime extends Components.IonDatetime {
@ProxyCmp({
defineCustomElementFn: undefined,
- inputs: ['cancelText', 'clearText', 'color', 'dayValues', 'disabled', 'doneText', 'firstDayOfWeek', 'hourCycle', 'hourValues', 'isDateEnabled', 'locale', 'max', 'min', 'minuteValues', 'mode', 'monthValues', 'multiple', 'name', 'preferWheel', 'presentation', 'readonly', 'showClearButton', 'showDefaultButtons', 'showDefaultTimeLabel', 'showDefaultTitle', 'size', 'titleSelectedDatesFormatter', 'value', 'yearValues'],
+ inputs: ['cancelText', 'clearText', 'color', 'dayValues', 'disabled', 'doneText', 'firstDayOfWeek', 'highlightedDates', 'hourCycle', 'hourValues', 'isDateEnabled', 'locale', 'max', 'min', 'minuteValues', 'mode', 'monthValues', 'multiple', 'name', 'preferWheel', 'presentation', 'readonly', 'showClearButton', 'showDefaultButtons', 'showDefaultTimeLabel', 'showDefaultTitle', 'size', 'titleSelectedDatesFormatter', 'value', 'yearValues'],
methods: ['confirm', 'reset', 'cancel']
})
@Component({
selector: 'ion-datetime',
changeDetection: ChangeDetectionStrategy.OnPush,
template: '',
- inputs: ['cancelText', 'clearText', 'color', 'dayValues', 'disabled', 'doneText', 'firstDayOfWeek', 'hourCycle', 'hourValues', 'isDateEnabled', 'locale', 'max', 'min', 'minuteValues', 'mode', 'monthValues', 'multiple', 'name', 'preferWheel', 'presentation', 'readonly', 'showClearButton', 'showDefaultButtons', 'showDefaultTimeLabel', 'showDefaultTitle', 'size', 'titleSelectedDatesFormatter', 'value', 'yearValues']
+ inputs: ['cancelText', 'clearText', 'color', 'dayValues', 'disabled', 'doneText', 'firstDayOfWeek', 'highlightedDates', 'hourCycle', 'hourValues', 'isDateEnabled', 'locale', 'max', 'min', 'minuteValues', 'mode', 'monthValues', 'multiple', 'name', 'preferWheel', 'presentation', 'readonly', 'showClearButton', 'showDefaultButtons', 'showDefaultTimeLabel', 'showDefaultTitle', 'size', 'titleSelectedDatesFormatter', 'value', 'yearValues']
})
export class IonDatetime {
protected el: HTMLElement;
diff --git a/core/api.txt b/core/api.txt
index 8eb31c06047..9783b904b80 100644
--- a/core/api.txt
+++ b/core/api.txt
@@ -377,6 +377,7 @@ ion-datetime,prop,dayValues,number | number[] | string | undefined,undefined,fal
ion-datetime,prop,disabled,boolean,false,false,false
ion-datetime,prop,doneText,string,'Done',false,false
ion-datetime,prop,firstDayOfWeek,number,0,false,false
+ion-datetime,prop,highlightedDates,((dateIsoString: string) => DatetimeHighlightStyle | undefined) | DatetimeHighlight[] | undefined,undefined,false,false
ion-datetime,prop,hourCycle,"h12" | "h23" | undefined,undefined,false,false
ion-datetime,prop,hourValues,number | number[] | string | undefined,undefined,false,false
ion-datetime,prop,isDateEnabled,((dateIsoString: string) => boolean) | undefined,undefined,false,false
diff --git a/core/src/components.d.ts b/core/src/components.d.ts
index 1164b07ad0a..844887bb26d 100644
--- a/core/src/components.d.ts
+++ b/core/src/components.d.ts
@@ -5,9 +5,10 @@
* It contains typing information for all components that exist in this project.
*/
import { HTMLStencilElement, JSXBase } from "@stencil/core/internal";
-import { AccordionGroupChangeEventDetail, ActionSheetAttributes, ActionSheetButton, AlertButton, AlertInput, AnimationBuilder, AutocompleteTypes, BreadcrumbCollapsedClickEventDetail, CheckboxChangeEventDetail, Color, ComponentProps, ComponentRef, DatetimeChangeEventDetail, DatetimePresentation, DomRenderFn, FooterHeightFn, FrameworkDelegate, HeaderFn, HeaderHeightFn, InputChangeEventDetail, ItemHeightFn, ItemRenderFn, ItemReorderEventDetail, LoadingAttributes, MenuChangeEventDetail, ModalAttributes, ModalBreakpointChangeEventDetail, ModalHandleBehavior, NavComponent, NavComponentWithProps, NavOptions, OverlayEventDetail, PickerAttributes, PickerButton, PickerColumn, PopoverAttributes, PopoverSize, PositionAlign, PositionReference, PositionSide, RadioGroupChangeEventDetail, RangeChangeEventDetail, RangeKnobMoveEndEventDetail, RangeKnobMoveStartEventDetail, RangeValue, RefresherEventDetail, RouteID, RouterDirection, RouterEventDetail, RouterOutletOptions, RouteWrite, ScrollBaseDetail, ScrollDetail, SearchbarChangeEventDetail, SegmentButtonLayout, SegmentChangeEventDetail, SelectChangeEventDetail, SelectInterface, SelectPopoverOption, Side, SpinnerTypes, StyleEventDetail, SwipeGestureHandler, TabBarChangedEventDetail, TabButtonClickEventDetail, TabButtonLayout, TextareaChangeEventDetail, TextFieldTypes, TitleSelectedDatesFormatter, ToastButton, ToggleChangeEventDetail, TransitionDoneFn, TransitionInstruction, TriggerAction, ViewController } from "./interface";
+import { AccordionGroupChangeEventDetail, ActionSheetAttributes, ActionSheetButton, AlertButton, AlertInput, AnimationBuilder, AutocompleteTypes, BreadcrumbCollapsedClickEventDetail, CheckboxChangeEventDetail, Color, ComponentProps, ComponentRef, DomRenderFn, FooterHeightFn, FrameworkDelegate, HeaderFn, HeaderHeightFn, InputChangeEventDetail, ItemHeightFn, ItemRenderFn, ItemReorderEventDetail, LoadingAttributes, MenuChangeEventDetail, ModalAttributes, ModalBreakpointChangeEventDetail, ModalHandleBehavior, NavComponent, NavComponentWithProps, NavOptions, OverlayEventDetail, PickerAttributes, PickerButton, PickerColumn, PopoverAttributes, PopoverSize, PositionAlign, PositionReference, PositionSide, RadioGroupChangeEventDetail, RangeChangeEventDetail, RangeKnobMoveEndEventDetail, RangeKnobMoveStartEventDetail, RangeValue, RefresherEventDetail, RouteID, RouterDirection, RouterEventDetail, RouterOutletOptions, RouteWrite, ScrollBaseDetail, ScrollDetail, SearchbarChangeEventDetail, SegmentButtonLayout, SegmentChangeEventDetail, SelectChangeEventDetail, SelectInterface, SelectPopoverOption, Side, SpinnerTypes, StyleEventDetail, SwipeGestureHandler, TabBarChangedEventDetail, TabButtonClickEventDetail, TabButtonLayout, TextareaChangeEventDetail, TextFieldTypes, ToastButton, ToggleChangeEventDetail, TransitionDoneFn, TransitionInstruction, TriggerAction, ViewController } from "./interface";
import { IonicSafeString } from "./utils/sanitization";
import { AlertAttributes } from "./components/alert/alert-interface";
+import { DatetimeChangeEventDetail, DatetimeHighlight, DatetimeHighlightCallback, DatetimePresentation, TitleSelectedDatesFormatter } from "./components/datetime/datetime-interface";
import { CounterFormatter } from "./components/item/item-interface";
import { PickerColumnItem } from "./components/picker-column-internal/picker-column-internal-interfaces";
import { PickerInternalChangeEventDetail } from "./components/picker-internal/picker-internal-interfaces";
@@ -757,6 +758,10 @@ export namespace Components {
* The first day of the week to use for `ion-datetime`. The default value is `0` and represents Sunday.
*/
"firstDayOfWeek": number;
+ /**
+ * Used to apply custom text and background colors to specific dates. Can be either an array of objects containing ISO strings and colors, or a callback that receives an ISO string and returns the colors. Only applies to the `date`, `date-time`, and `time-date` presentations, with `preferWheel="false"`.
+ */
+ "highlightedDates"?: DatetimeHighlight[] | DatetimeHighlightCallback;
/**
* The hour cycle of the `ion-datetime`. If no value is set, this is specified by the current locale.
*/
@@ -4727,6 +4732,10 @@ declare namespace LocalJSX {
* The first day of the week to use for `ion-datetime`. The default value is `0` and represents Sunday.
*/
"firstDayOfWeek"?: number;
+ /**
+ * Used to apply custom text and background colors to specific dates. Can be either an array of objects containing ISO strings and colors, or a callback that receives an ISO string and returns the colors. Only applies to the `date`, `date-time`, and `time-date` presentations, with `preferWheel="false"`.
+ */
+ "highlightedDates"?: DatetimeHighlight[] | DatetimeHighlightCallback;
/**
* The hour cycle of the `ion-datetime`. If no value is set, this is specified by the current locale.
*/
diff --git a/core/src/components/datetime/datetime-interface.ts b/core/src/components/datetime/datetime-interface.ts
index 83aa501af82..4fea1af5663 100644
--- a/core/src/components/datetime/datetime-interface.ts
+++ b/core/src/components/datetime/datetime-interface.ts
@@ -25,3 +25,17 @@ export interface DatetimeParts {
export type DatetimePresentation = 'date-time' | 'time-date' | 'date' | 'time' | 'month' | 'year' | 'month-year';
export type TitleSelectedDatesFormatter = (selectedDates: string[]) => string;
+
+export type DatetimeHighlightStyle =
+ | {
+ textColor: string;
+ backgroundColor?: string;
+ }
+ | {
+ textColor?: string;
+ backgroundColor: string;
+ };
+
+export type DatetimeHighlight = { date: string } & DatetimeHighlightStyle;
+
+export type DatetimeHighlightCallback = (dateIsoString: string) => DatetimeHighlightStyle | undefined;
diff --git a/core/src/components/datetime/datetime.ios.scss b/core/src/components/datetime/datetime.ios.scss
index 1ce28a13506..155ab6d5f77 100644
--- a/core/src/components/datetime/datetime.ios.scss
+++ b/core/src/components/datetime/datetime.ios.scss
@@ -92,14 +92,22 @@
font-size: 20px;
}
-:host .calendar-day:after {
+.calendar-day:focus .calendar-day-highlight,
+.calendar-day.calendar-day-active .calendar-day-highlight {
opacity: 0.2;
}
-:host .calendar-day:focus:after {
+.calendar-day.calendar-day-active .calendar-day-highlight {
background: current-color(base);
}
+// !important is needed here to overwrite custom highlight background, which is inline.
+// Does not apply to the active state because highlights aren't applied at all there.
+.calendar-day:focus .calendar-day-highlight {
+ /* stylelint-disable-next-line declaration-no-important */
+ background: current-color(base) !important;
+}
+
/**
* Day that today but not selected
* should have ion-color for text color.
@@ -119,10 +127,6 @@
font-weight: 600;
}
-:host .calendar-day.calendar-day-active:after {
- background: current-color(base);
-}
-
/**
* Day that is selected and is today
* should have white color.
@@ -131,7 +135,7 @@
color: current-color(contrast);
}
-:host .calendar-day.calendar-day-today.calendar-day-active:after {
+.calendar-day.calendar-day-today.calendar-day-active .calendar-day-highlight {
background: current-color(base);
opacity: 1;
diff --git a/core/src/components/datetime/datetime.md.scss b/core/src/components/datetime/datetime.md.scss
index 5d74dd563d6..832b61fec83 100644
--- a/core/src/components/datetime/datetime.md.scss
+++ b/core/src/components/datetime/datetime.md.scss
@@ -74,7 +74,7 @@
font-size: $datetime-md-calendar-item-font-size;
}
-:host .calendar-day:focus:after {
+.calendar-day:focus .calendar-day-highlight {
background: current-color(base, 0.2);
box-shadow: 0px 0px 0px 4px current-color(base, 0.2);
@@ -88,7 +88,7 @@
color: current-color(base);
}
-:host .calendar-day.calendar-day-today:after {
+.calendar-day.calendar-day-today .calendar-day-highlight {
border: 1px solid current-color(base);
}
@@ -101,7 +101,7 @@
color: current-color(contrast);
}
-:host .calendar-day.calendar-day-active:after {
+.calendar-day.calendar-day-active .calendar-day-highlight {
border: 1px solid current-color(base);
background: current-color(base);
diff --git a/core/src/components/datetime/datetime.scss b/core/src/components/datetime/datetime.scss
index 71c997ef661..3bd90f3bb29 100644
--- a/core/src/components/datetime/datetime.scss
+++ b/core/src/components/datetime/datetime.scss
@@ -356,31 +356,15 @@ ion-picker-column-internal {
opacity: 0.4;
}
-:host .calendar-day:after {
+.calendar-day-highlight {
@include border-radius(32px, 32px, 32px, 32px);
@include padding(4px, 4px, 4px, 4px);
position: absolute;
- /**
- * Explicit position values are required here
- * as pseudo element positioning is incorrect
- * in older implementations of css grid.
- *
- * TODO: FW-1720: Remove top/left styles when deprecating iOS 13 support
- */
- /* stylelint-disable-next-line property-disallowed-list */
- top: 50%;
- /* stylelint-disable-next-line property-disallowed-list */
- left: 50%;
-
width: 32px;
height: 32px;
- transform: translate(-50%, -50%);
-
- content: " ";
-
z-index: -1;
}
diff --git a/core/src/components/datetime/datetime.tsx b/core/src/components/datetime/datetime.tsx
index 63cf10adf3a..f92c2abbc4e 100644
--- a/core/src/components/datetime/datetime.tsx
+++ b/core/src/components/datetime/datetime.tsx
@@ -3,15 +3,7 @@ import { Component, Element, Event, Host, Method, Prop, State, Watch, h, writeTa
import { caretDownSharp, caretUpSharp, chevronBack, chevronDown, chevronForward } from 'ionicons/icons';
import { getIonMode } from '../../global/ionic-global';
-import type {
- Color,
- DatetimePresentation,
- DatetimeChangeEventDetail,
- DatetimeParts,
- Mode,
- StyleEventDetail,
- TitleSelectedDatesFormatter,
-} from '../../interface';
+import type { Color, Mode, StyleEventDetail } from '../../interface';
import { startFocusVisible } from '../../utils/focus-visible';
import { getElementRoot, raf, renderHiddenInput } from '../../utils/helpers';
import { printIonError, printIonWarning } from '../../utils/logging';
@@ -19,6 +11,15 @@ import { isRTL } from '../../utils/rtl';
import { createColorClasses } from '../../utils/theme';
import type { PickerColumnItem } from '../picker-column-internal/picker-column-internal-interfaces';
+import type {
+ DatetimePresentation,
+ DatetimeChangeEventDetail,
+ DatetimeParts,
+ TitleSelectedDatesFormatter,
+ DatetimeHighlight,
+ DatetimeHighlightStyle,
+ DatetimeHighlightCallback,
+} from './datetime-interface';
import { isSameDay, warnIfValueOutOfBounds, isBefore, isAfter } from './utils/comparison';
import {
generateMonths,
@@ -60,6 +61,7 @@ import {
} from './utils/parse';
import {
getCalendarDayState,
+ getHighlightStyles,
isDayDisabled,
isMonthDisabled,
isNextMonthDisabled,
@@ -322,6 +324,17 @@ export class Datetime implements ComponentInterface {
*/
@Prop() multiple = false;
+ /**
+ * Used to apply custom text and background colors to specific dates.
+ *
+ * Can be either an array of objects containing ISO strings and colors,
+ * or a callback that receives an ISO string and returns the colors.
+ *
+ * Only applies to the `date`, `date-time`, and `time-date` presentations,
+ * with `preferWheel="false"`.
+ */
+ @Prop() highlightedDates?: DatetimeHighlight[] | DatetimeHighlightCallback;
+
/**
* The value of the datetime as a valid ISO 8601 datetime string.
* Should be an array of strings if `multiple="true"`.
@@ -1235,7 +1248,7 @@ export class Datetime implements ComponentInterface {
};
componentWillLoad() {
- const { el, multiple, presentation, preferWheel } = this;
+ const { el, highlightedDates, multiple, presentation, preferWheel } = this;
if (multiple) {
if (presentation !== 'date') {
@@ -1247,6 +1260,19 @@ export class Datetime implements ComponentInterface {
}
}
+ if (highlightedDates !== undefined) {
+ if (presentation !== 'date' && presentation !== 'date-time' && presentation !== 'time-date') {
+ printIonWarning(
+ 'The highlightedDates property is only supported with the date, date-time, and time-date presentations.',
+ el
+ );
+ }
+
+ if (preferWheel) {
+ printIonWarning('The highlightedDates property is not supported with preferWheel="true".', el);
+ }
+ }
+
this.processMinParts();
this.processMaxParts();
const hourValues = (this.parsedHourValues = convertToArrayOfNumbers(this.hourValues));
@@ -1971,7 +1997,7 @@ export class Datetime implements ComponentInterface {
{getDaysOfMonth(month, year, this.firstDayOfWeek % 7).map((dateObject, index) => {
const { day, dayOfWeek } = dateObject;
- const { isDateEnabled, multiple } = this;
+ const { el, highlightedDates, isDateEnabled, multiple } = this;
const referenceParts = { month, day, year };
const { isActive, isToday, ariaLabel, ariaSelected, disabled, text } = getCalendarDayState(
this.locale,
@@ -1983,6 +2009,7 @@ export class Datetime implements ComponentInterface {
this.parsedDayValues
);
+ const dateIsoString = convertDataToISO(referenceParts);
let isCalDayDisabled = isCalMonthDisabled || disabled;
if (!isCalDayDisabled && isDateEnabled !== undefined) {
@@ -1992,15 +2019,26 @@ export class Datetime implements ComponentInterface {
* to prevent exceptions in the user's function from
* interrupting the calendar rendering.
*/
- isCalDayDisabled = !isDateEnabled(convertDataToISO(referenceParts));
+ isCalDayDisabled = !isDateEnabled(dateIsoString);
} catch (e) {
printIonError(
'Exception thrown from provided `isDateEnabled` function. Please check your function and try again.',
+ el,
e
);
}
}
+ let dateStyle: DatetimeHighlightStyle | undefined = undefined;
+
+ /**
+ * Custom highlight styles should not override the style for selected dates,
+ * nor apply to "filler days" at the start of the grid.
+ */
+ if (highlightedDates !== undefined && !isActive && day !== null) {
+ dateStyle = getHighlightStyles(highlightedDates, dateIsoString, el);
+ }
+
return (
);
diff --git a/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts
new file mode 100644
index 00000000000..2edebb7cffa
--- /dev/null
+++ b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts
@@ -0,0 +1,103 @@
+import { expect } from '@playwright/test';
+import { test } from '@utils/test/playwright';
+
+test.describe('datetime: highlightedDates', () => {
+ test.beforeEach(async ({ page, skip }) => {
+ skip.rtl();
+
+ await page.setContent(`
+
+ `);
+ });
+
+ test('should render highlights correctly when using an array', async ({ page }) => {
+ const datetime = page.locator('ion-datetime');
+
+ await datetime.evaluate((el: HTMLIonDatetimeElement) => {
+ el.highlightedDates = [
+ {
+ date: '2023-01-01', // ensure selected date style overrides highlight
+ textColor: '#800080',
+ backgroundColor: '#ffc0cb',
+ },
+ {
+ date: '2023-01-02',
+ textColor: '#b22222',
+ backgroundColor: '#fa8072',
+ },
+ {
+ date: '2023-01-03',
+ textColor: '#0000ff',
+ backgroundColor: '#add8e6',
+ },
+ ];
+ });
+
+ await page.waitForChanges();
+ expect(await datetime.screenshot()).toMatchSnapshot(
+ `datetime-highlightedDates-array-${page.getSnapshotSettings()}.png`
+ );
+ });
+
+ test('should render highlights correctly when using a callback', async ({ page }) => {
+ const datetime = page.locator('ion-datetime');
+
+ await datetime.evaluate((el: HTMLIonDatetimeElement) => {
+ el.highlightedDates = (isoString) => {
+ const date = new Date(isoString);
+ const utcDay = date.getUTCDate();
+
+ // ensure selected date style overrides highlight
+ if (utcDay === 1) {
+ return {
+ textColor: '#b22222',
+ backgroundColor: '#fa8072',
+ };
+ }
+
+ if (utcDay % 5 === 0) {
+ return {
+ textColor: '#800080',
+ backgroundColor: '#ffc0cb',
+ };
+ }
+
+ if (utcDay % 3 === 0) {
+ return {
+ textColor: '#0000ff',
+ backgroundColor: '#add8e6',
+ };
+ }
+
+ return undefined;
+ };
+ });
+
+ await page.waitForChanges();
+ expect(await datetime.screenshot()).toMatchSnapshot(
+ `datetime-highlightedDates-callback-${page.getSnapshotSettings()}.png`
+ );
+ });
+
+ test('should render highlights correctly when only using one color or the other', async ({ page }) => {
+ const datetime = page.locator('ion-datetime');
+
+ await datetime.evaluate((el: HTMLIonDatetimeElement) => {
+ el.highlightedDates = [
+ {
+ date: '2023-01-02',
+ backgroundColor: '#fa8072',
+ },
+ {
+ date: '2023-01-03',
+ textColor: '#0000ff',
+ },
+ ];
+ });
+
+ await page.waitForChanges();
+ expect(await datetime.screenshot()).toMatchSnapshot(
+ `datetime-highlightedDates-single-color-${page.getSnapshotSettings()}.png`
+ );
+ });
+});
diff --git a/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-array-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-array-ios-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 00000000000..86a3447122c
Binary files /dev/null and b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-array-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-array-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-array-ios-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 00000000000..c751dd3858a
Binary files /dev/null and b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-array-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-array-ios-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-array-ios-ltr-Mobile-Safari-linux.png
new file mode 100644
index 00000000000..d58794cf180
Binary files /dev/null and b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-array-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-array-md-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-array-md-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 00000000000..c5084a62304
Binary files /dev/null and b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-array-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-array-md-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-array-md-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 00000000000..7d98d74a71e
Binary files /dev/null and b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-array-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-array-md-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-array-md-ltr-Mobile-Safari-linux.png
new file mode 100644
index 00000000000..b138075ff54
Binary files /dev/null and b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-array-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-callback-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-callback-ios-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 00000000000..e566c190d98
Binary files /dev/null and b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-callback-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-callback-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-callback-ios-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 00000000000..bd77a99038c
Binary files /dev/null and b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-callback-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-callback-ios-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-callback-ios-ltr-Mobile-Safari-linux.png
new file mode 100644
index 00000000000..58c1376934f
Binary files /dev/null and b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-callback-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-callback-md-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-callback-md-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 00000000000..75685f791a4
Binary files /dev/null and b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-callback-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-callback-md-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-callback-md-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 00000000000..b8646fde35b
Binary files /dev/null and b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-callback-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-callback-md-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-callback-md-ltr-Mobile-Safari-linux.png
new file mode 100644
index 00000000000..da31daf14a5
Binary files /dev/null and b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-callback-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-single-color-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-single-color-ios-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 00000000000..c18944f97dc
Binary files /dev/null and b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-single-color-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-single-color-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-single-color-ios-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 00000000000..457b3540834
Binary files /dev/null and b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-single-color-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-single-color-ios-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-single-color-ios-ltr-Mobile-Safari-linux.png
new file mode 100644
index 00000000000..2e9ff91ece0
Binary files /dev/null and b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-single-color-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-single-color-md-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-single-color-md-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 00000000000..d71aad7f7b8
Binary files /dev/null and b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-single-color-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-single-color-md-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-single-color-md-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 00000000000..c32b0135b73
Binary files /dev/null and b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-single-color-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-single-color-md-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-single-color-md-ltr-Mobile-Safari-linux.png
new file mode 100644
index 00000000000..af652b53a90
Binary files /dev/null and b/core/src/components/datetime/test/highlightedDates/datetime.e2e.ts-snapshots/datetime-highlightedDates-single-color-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/highlightedDates/index.html b/core/src/components/datetime/test/highlightedDates/index.html
new file mode 100644
index 00000000000..965865b7b0f
--- /dev/null
+++ b/core/src/components/datetime/test/highlightedDates/index.html
@@ -0,0 +1,110 @@
+
+
+
+
+
Datetime - highlightedDates
+
+
+
+
+
+
+
+
+
+
+
+
+ Datetime - highlightedDates
+
+
+
+
+
+
With Array
+
+
+
+
With Callback
+
+
+
+
Highlight Today
+
+
+
+
+
+
+
+
+
diff --git a/core/src/components/datetime/utils/state.ts b/core/src/components/datetime/utils/state.ts
index 0d9200ffeb8..f709d7289a1 100644
--- a/core/src/components/datetime/utils/state.ts
+++ b/core/src/components/datetime/utils/state.ts
@@ -1,4 +1,11 @@
-import type { DatetimeParts } from '../datetime-interface';
+import { printIonError } from '@utils/logging';
+
+import type {
+ DatetimeHighlight,
+ DatetimeHighlightCallback,
+ DatetimeHighlightStyle,
+ DatetimeParts,
+} from '../datetime-interface';
import { isAfter, isBefore, isSameDay } from './comparison';
import { generateDayAriaLabel, getDay } from './format';
@@ -182,3 +189,41 @@ export const isNextMonthDisabled = (refParts: DatetimeParts, maxParts?: Datetime
maxParts,
});
};
+
+/**
+ * Given the value of the highlightedDates property
+ * and an ISO string, return the styles to use for
+ * that date, or undefined if none are found.
+ */
+export const getHighlightStyles = (
+ highlightedDates: DatetimeHighlight[] | DatetimeHighlightCallback,
+ dateIsoString: string,
+ el: HTMLIonDatetimeElement
+): DatetimeHighlightStyle | undefined => {
+ if (Array.isArray(highlightedDates)) {
+ const dateStringWithoutTime = dateIsoString.split('T')[0];
+ const matchingHighlight = highlightedDates.find((hd) => hd.date === dateStringWithoutTime);
+ if (matchingHighlight) {
+ return {
+ textColor: matchingHighlight.textColor,
+ backgroundColor: matchingHighlight.backgroundColor,
+ } as DatetimeHighlightStyle;
+ }
+ } else {
+ /**
+ * Wrap in a try-catch to prevent exceptions in the user's function
+ * from interrupting the calendar's rendering.
+ */
+ try {
+ return highlightedDates(dateIsoString);
+ } catch (e) {
+ printIonError(
+ 'Exception thrown from provided `highlightedDates` callback. Please check your function and try again.',
+ el,
+ e
+ );
+ }
+ }
+
+ return undefined;
+};
diff --git a/packages/vue/src/proxies.ts b/packages/vue/src/proxies.ts
index efd8d274f42..9479c895deb 100644
--- a/packages/vue/src/proxies.ts
+++ b/packages/vue/src/proxies.ts
@@ -289,6 +289,7 @@ export const IonDatetime = /*@__PURE__*/ defineContainer
('ion-d
'firstDayOfWeek',
'titleSelectedDatesFormatter',
'multiple',
+ 'highlightedDates',
'value',
'showDefaultTitle',
'showDefaultButtons',