feat(datetime): add parts for calendar day, active, and today (#27641)

Issue number: resolves #25340

---------

- Exposes the following parts for a calendar day: `calendar-day`,
`today`, and `active`
- Combines the `calendar-day-highlight` element with the `calendar-day`
element so developers don't have to know to style two different elements
& we don't have to expose them as separate parts
- Improves height parity of the calendar day across browsers
- Updates the `custom` e2e test to include an example of styling days
using the newly exposed CSS parts
- Adds tests for the focus states of the calendar day
This commit is contained in:
Brandy Carney
2023-09-06 11:58:41 -04:00
committed by GitHub
parent e6c7bb60e7
commit 79b005da70
180 changed files with 370 additions and 150 deletions

View File

@ -428,6 +428,9 @@ ion-datetime,css-prop,--background-rgb
ion-datetime,css-prop,--title-color
ion-datetime,css-prop,--wheel-fade-background-rgb
ion-datetime,css-prop,--wheel-highlight-background
ion-datetime,part,calendar-day
ion-datetime,part,calendar-day active
ion-datetime,part,calendar-day today
ion-datetime,part,month-year-button
ion-datetime,part,time-button
ion-datetime,part,time-button active

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -85,27 +85,32 @@
*/
@include padding($datetime-ios-padding * 0.5, $datetime-ios-padding * 0.5, $datetime-ios-padding * 0.5, $datetime-ios-padding * 0.5);
align-items: center;
height: calc(100% - #{$datetime-ios-padding});
}
:host .calendar-day {
font-size: 20px;
}
:host .calendar-day-wrapper {
@include padding(4px);
// This is required so that the calendar day wrapper
// will collapse instead of expanding to fill the button
height: 0;
.calendar-day:focus .calendar-day-highlight,
.calendar-day.calendar-day-active .calendar-day-highlight {
opacity: 0.2;
min-height: 16px;
}
.calendar-day.calendar-day-active .calendar-day-highlight {
background: current-color(base);
:host .calendar-day {
width: $datetime-ios-day-width;
min-width: $datetime-ios-day-width;
height: $datetime-ios-day-height;
font-size: 20px;
}
// !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;
.calendar-day.calendar-day-active {
background: current-color(base, 0.2);
}
/**
@ -135,12 +140,6 @@
color: current-color(contrast);
}
.calendar-day.calendar-day-today.calendar-day-active .calendar-day-highlight {
background: current-color(base);
opacity: 1;
}
// Time / Header
// -----------------------------------
:host .datetime-time {

View File

@ -15,3 +15,9 @@ $datetime-ios-time-width: 68px !default;
/// @prop - Border radius of the time picker
$datetime-ios-time-border-radius: 8px !default;
/// @prop - Width of the calendar day
$datetime-ios-day-width: 40px !default;
/// @prop - Height of the calendar day
$datetime-ios-day-height: $datetime-ios-day-width !default;

View File

@ -69,15 +69,12 @@
// Individual day button in month
:host .calendar-day {
@include padding(13px, 0, 13px, 0px);
width: $datetime-md-day-width;
min-width: $datetime-md-day-width;
font-size: $datetime-md-calendar-item-font-size;
}
.calendar-day:focus .calendar-day-highlight {
background: current-color(base, 0.2);
height: $datetime-md-day-height;
box-shadow: 0px 0px 0px 4px current-color(base, 0.2);
font-size: $datetime-md-calendar-item-font-size;
}
/**
@ -85,11 +82,9 @@
* should have ion-color for text color.
*/
:host .calendar-day.calendar-day-today {
color: current-color(base);
}
.calendar-day.calendar-day-today .calendar-day-highlight {
border: 1px solid current-color(base);
color: current-color(base);
}
/**
@ -101,7 +96,7 @@
color: current-color(contrast);
}
.calendar-day.calendar-day-active .calendar-day-highlight {
.calendar-day.calendar-day-active {
border: 1px solid current-color(base);
background: current-color(base);

View File

@ -15,3 +15,9 @@ $datetime-md-header-padding: 20px !default;
/// @prop - Padding for content
$datetime-md-padding: 16px !default;
/// @prop - Width of the calendar day
$datetime-md-day-width: 42px !default;
/// @prop - Height of the calendar day
$datetime-md-day-height: $datetime-md-day-width !default;

View File

@ -290,6 +290,10 @@ ion-picker-column-internal {
}
:host .calendar-body .calendar-month {
display: flex;
flex-flow: column;
/**
* Swiping should snap to at
* most one month at a time.
@ -325,13 +329,31 @@ ion-picker-column-internal {
grid-template-columns: repeat(7, 1fr);
}
:host .calendar-day-wrapper {
display: flex;
align-items: center;
justify-content: center;
// Adding a min width and min height allows
// it to shrink smaller than its content
// which keeps the calendar day highlight
// larger while letting the grid items shrink
min-width: 0;
min-height: 0;
overflow: visible;
}
/**
* Center the day text vertically
* and horizontally within its grid cell.
*/
:host .calendar-day {
@include padding(0px, 0px, 0px, 0px);
@include margin(0px, 0px, 0px, 0px);
@include border-radius(50%);
@include padding(0px);
@include margin(0px);
display: flex;
@ -362,16 +384,10 @@ ion-picker-column-internal {
opacity: 0.4;
}
.calendar-day-highlight {
@include border-radius(32px, 32px, 32px, 32px);
@include padding(4px, 4px, 4px, 4px);
position: absolute;
width: 32px;
height: 32px;
.calendar-day:focus {
background: current-color(base, 0.2);
z-index: -1;
box-shadow: 0px 0px 0px 4px current-color(base, 0.2);
}
// Time / Header

View File

@ -85,6 +85,11 @@ import {
*
* @part month-year-button - The button that opens the month/year picker when
* using a grid style layout.
*
* @part calendar-day - The individual buttons that display a day inside of the datetime
* calendar.
* @part calendar-day active - The currently selected calendar day.
* @part calendar-day today - The calendar day that contains the current day.
*/
@Component({
tag: 'ion-datetime',
@ -756,7 +761,7 @@ export class Datetime implements ComponentInterface {
/**
* Get the number of padding days so
* we know how much to offset our next selector by
* to grab the correct calenday-day element.
* to grab the correct calendar-day element.
*/
const padding = currentMonth.querySelectorAll('.calendar-day-padding');
const { day } = this.workingParts;
@ -770,7 +775,7 @@ export class Datetime implements ComponentInterface {
* and focus it.
*/
const dayEl = currentMonth.querySelector(
`.calendar-day:nth-of-type(${padding.length + day})`
`.calendar-day-wrapper:nth-of-type(${padding.length + day}) .calendar-day`
) as HTMLElement | null;
if (dayEl) {
dayEl.focus();
@ -2116,69 +2121,85 @@ export class Datetime implements ComponentInterface {
dateStyle = getHighlightStyles(highlightedDates, dateIsoString, el);
}
return (
<button
tabindex="-1"
data-day={day}
data-month={month}
data-year={year}
data-index={index}
data-day-of-week={dayOfWeek}
disabled={isCalDayDisabled}
class={{
'calendar-day-padding': isCalendarPadding,
'calendar-day': true,
'calendar-day-active': isActive,
'calendar-day-today': isToday,
}}
style={
dateStyle && {
color: dateStyle.textColor,
}
}
aria-hidden={isCalendarPadding ? 'true' : null}
aria-selected={ariaSelected}
aria-label={ariaLabel}
onClick={() => {
if (isCalendarPadding) {
return;
}
let dateParts = undefined;
this.setWorkingParts({
...this.workingParts,
month,
day,
year,
});
// multiple only needs date info, so we can wipe out other fields like time
if (multiple) {
this.setActiveParts(
{
month,
day,
year,
},
isActive
);
} else {
this.setActiveParts({
...activePart,
// "Filler days" at the beginning of the grid should not get the calendar day
// CSS parts added to them
if (!isCalendarPadding) {
dateParts = `calendar-day${isActive ? ' active' : ''}${isToday ? ' today' : ''}`;
}
return (
<div class="calendar-day-wrapper">
<button
// We need to use !important for the inline styles here because
// otherwise the CSS shadow parts will override these styles.
// See https://github.com/WICG/webcomponents/issues/847
// Both the CSS shadow parts and highlightedDates styles are
// provided by the developer, but highlightedDates styles should
// always take priority.
ref={(el) => {
if (el) {
el.style.setProperty('color', `${dateStyle ? dateStyle.textColor : ''}`, 'important');
el.style.setProperty(
'background-color',
`${dateStyle ? dateStyle.backgroundColor : ''}`,
'important'
);
}
}}
tabindex="-1"
data-day={day}
data-month={month}
data-year={year}
data-index={index}
data-day-of-week={dayOfWeek}
disabled={isCalDayDisabled}
class={{
'calendar-day-padding': isCalendarPadding,
'calendar-day': true,
'calendar-day-active': isActive,
'calendar-day-today': isToday,
}}
part={dateParts}
aria-hidden={isCalendarPadding ? 'true' : null}
aria-selected={ariaSelected}
aria-label={ariaLabel}
onClick={() => {
if (isCalendarPadding) {
return;
}
this.setWorkingParts({
...this.workingParts,
month,
day,
year,
});
}
}}
>
<div
class="calendar-day-highlight"
style={{
backgroundColor: dateStyle?.backgroundColor,
// multiple only needs date info, so we can wipe out other fields like time
if (multiple) {
this.setActiveParts(
{
month,
day,
year,
},
isActive
);
} else {
this.setActiveParts({
...activePart,
month,
day,
year,
});
}
}}
></div>
{text}
</button>
>
{text}
</button>
</div>
);
})}
</div>

View File

@ -490,3 +490,40 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, screenshot, co
});
});
});
/**
* This behavior does not differ across
* directions.
*/
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('datetime: focus'), () => {
test('should focus the selected day and then the day after', async ({ page }) => {
await page.setContent(
`
<ion-datetime value="2023-08-01"></ion-datetime>
`,
config
);
await page.waitForSelector('.datetime-ready');
const datetime = page.locator('ion-datetime');
const day = datetime.locator(`.calendar-day[data-day='1'][data-month='8']`);
await day.focus();
await page.waitForChanges();
await expect(day).toBeFocused();
await expect(datetime).toHaveScreenshot(screenshot(`datetime-focus-selected-calendar-day`));
await page.keyboard.press('ArrowRight');
await page.waitForChanges();
const nextDay = datetime.locator(`.calendar-day[data-day='2'][data-month='8']`);
await expect(nextDay).toBeFocused();
await expect(datetime).toHaveScreenshot(screenshot(`datetime-focus-calendar-day`));
});
});
});

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -9,7 +9,7 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test('should not have visual regressions', async ({ page }) => {
await page.goto('/src/components/datetime/test/color', config);
const datetime = page.locator('ion-datetime');
const datetime = page.locator('#color-datetime');
await expect(datetime).toHaveScreenshot(screenshot(`datetime-color`));

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -9,11 +9,18 @@
<script src="../../../../../scripts/testing/scripts.js"></script>
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
<style>
ion-checkbox,
ion-select {
margin-inline-start: 10px;
margin-inline-end: 10px;
}
.grid {
display: grid;
grid-template-columns: repeat(2, minmax(250px, 1fr));
grid-template-columns: repeat(auto-fill, 250px);
grid-gap: 20px;
}
h2 {
font-size: 12px;
font-weight: normal;
@ -29,10 +36,14 @@
border-radius: 8px;
}
#color-name::first-letter {
text-transform: capitalize;
}
/*
* Dark Colors
* -------------------------------------------
*/
* Dark Theme
* -------------------------------------------
*/
body.dark {
--ion-color-primary: #428cff;
@ -100,9 +111,9 @@
}
/*
* iOS Dark Theme
* -------------------------------------------
*/
* iOS Dark Theme
* -------------------------------------------
*/
.ios body.dark {
--ion-background-color: #000000;
@ -144,9 +155,9 @@
}
/*
* Material Design Dark Theme
* -------------------------------------------
*/
* Material Design Dark Theme
* -------------------------------------------
*/
.md body.dark {
--ion-background-color: #121212;
@ -191,30 +202,23 @@
<ion-app>
<ion-header translucent="true">
<ion-toolbar>
<ion-title>Datetime - Color</ion-title>
<ion-item lines="none" slot="end">
<ion-label>Dark Mode</ion-label>
<ion-checkbox slot="end"></ion-checkbox>
</ion-item>
<ion-item lines="none" slot="end">
<ion-label>Color</ion-label>
<ion-select value="danger">
<ion-select-option value="primary">Primary</ion-select-option>
<ion-select-option value="secondary">Secondary</ion-select-option>
<ion-select-option value="tertiary">Tertiary</ion-select-option>
<ion-select-option value="success">Success</ion-select-option>
<ion-select-option value="warning">Warning</ion-select-option>
<ion-select-option value="danger">Danger</ion-select-option>
</ion-select>
</ion-item>
<ion-checkbox>Dark Mode</ion-checkbox>
<ion-select label="Color" justify="end" slot="end" value="danger">
<ion-select-option value="primary">Primary</ion-select-option>
<ion-select-option value="secondary">Secondary</ion-select-option>
<ion-select-option value="tertiary">Tertiary</ion-select-option>
<ion-select-option value="success">Success</ion-select-option>
<ion-select-option value="warning">Warning</ion-select-option>
<ion-select-option value="danger">Danger</ion-select-option>
</ion-select>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
<div class="grid">
<div class="grid-item">
<h2>Default</h2>
<h2 id="color-name">Danger</h2>
<ion-datetime
id="color-datetime"
color="danger"
value="2022-05-03"
show-default-title="true"
@ -224,14 +228,14 @@
</div>
</ion-content>
<script>
const colorDatetime = document.querySelector('#color-datetime');
const colorName = document.querySelector('#color-name');
const colorSelect = document.querySelector('ion-select');
const darkModeToggle = document.querySelector('ion-checkbox');
const datetimes = document.querySelectorAll('ion-datetime');
colorSelect.addEventListener('ionChange', (ev) => {
datetimes.forEach((datetime) => {
datetime.color = ev.detail.value;
});
colorDatetime.color = ev.detail.value;
colorName.innerHTML = ev.detail.value;
});
darkModeToggle.addEventListener('ionChange', (ev) => {

View File

@ -14,7 +14,7 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
});
test('should allow styling time picker in grid style datetimes', async ({ page }) => {
const timeButton = page.locator('ion-datetime .time-body');
const timeButton = page.locator('#custom-grid .time-body');
const popover = page.locator('.popover-viewport');
const ionPopoverDidPresent = await page.spyOnEvent('ionPopoverDidPresent');
@ -26,5 +26,41 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
await expect(popover).toHaveScreenshot(screenshot(`datetime-custom-time-picker`));
await expect(timeButton).toHaveScreenshot(screenshot(`datetime-custom-time-button-active`));
});
test('should allow styling calendar days in grid style datetimes', async ({ page }) => {
const datetime = page.locator('#custom-calendar-days');
await expect(datetime).toHaveScreenshot(screenshot(`datetime-custom-calendar-days`));
});
});
});
/**
* This behavior does not differ across
* directions.
*/
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('datetime: custom focus'), () => {
test('should focus the selected day and then the day after', async ({ page }) => {
await page.goto(`/src/components/datetime/test/custom`, config);
const datetime = page.locator('#custom-calendar-days');
const day = datetime.locator(`.calendar-day[data-day='15'][data-month='6']`);
await day.focus();
await page.waitForChanges();
await expect(day).toBeFocused();
await expect(datetime).toHaveScreenshot(screenshot(`datetime-custom-focus-selected-calendar-day`));
await page.keyboard.press('ArrowRight');
await page.waitForChanges();
const nextDay = datetime.locator(`.calendar-day[data-day='16'][data-month='6']`);
await expect(nextDay).toBeFocused();
await expect(datetime).toHaveScreenshot(screenshot(`datetime-custom-focus-calendar-day`));
});
});
});

View File

@ -33,43 +33,97 @@
}
}
/*
* Custom Datetime Time / Wheel Parts
* -------------------------------------------
*/
.custom-grid-wheel {
--background: rgb(245, 235, 247);
--background-rgb: 245, 235, 247;
}
.custom-grid-wheel::part(time-button) {
color: rgb(128, 30, 171);
}
.custom-grid-wheel::part(time-button active) {
background-color: rgb(248, 215, 255);
}
/*
The second selectors that target ion-picker(-column)-internal
directly are for styling the time picker. This is currently
undocumented usage.
*/
ion-datetime,
.custom-grid-wheel,
ion-picker-internal {
--wheel-highlight-background: rgb(218, 216, 255);
--wheel-fade-background-rgb: 245, 235, 247;
}
ion-datetime {
--background: rgb(245, 235, 247);
--background-rgb: 245, 235, 247;
}
ion-picker-internal {
background-color: rgb(245, 235, 247);
}
ion-datetime::part(wheel-item),
.custom-grid-wheel::part(wheel-item),
ion-picker-column-internal::part(wheel-item) {
color: rgb(255, 134, 154);
}
ion-datetime::part(wheel-item active),
.custom-grid-wheel::part(wheel-item active),
ion-picker-column-internal::part(wheel-item active) {
color: rgb(128, 30, 171);
}
ion-datetime::part(time-button) {
color: rgb(128, 30, 171);
/*
* Custom Datetime Day Parts
* -------------------------------------------
*/
#custom-calendar-days::part(calendar-day) {
background-color: #ffe2e6;
color: #da5296;
margin: 2px 0;
}
ion-datetime::part(time-button active) {
background-color: rgb(248, 215, 255);
#custom-calendar-days::part(calendar-day today) {
color: #8462d1;
}
#custom-calendar-days::part(calendar-day):focus {
background-color: rgb(154 209 98 / 0.2);
box-shadow: 0px 0px 0px 4px rgb(154 209 98 / 0.2);
}
/*
* Custom Material Design Datetime Day Parts
* -------------------------------------------
*/
#custom-calendar-days.md::part(calendar-day active),
#custom-calendar-days.md::part(calendar-day active):focus {
background-color: #9ad162;
border-color: #9ad162;
color: #fff;
}
#custom-calendar-days.md::part(calendar-day today) {
border-color: #8462d1;
}
/*
* Custom iOS Datetime Day Parts
* -------------------------------------------
*/
#custom-calendar-days.ios::part(calendar-day active),
#custom-calendar-days.ios::part(calendar-day active):focus {
background-color: rgb(154 209 98 / 0.2);
color: #9ad162;
}
</style>
</head>
@ -85,14 +139,57 @@
<div class="grid">
<div class="grid-item">
<h2>Grid Style</h2>
<ion-datetime id="custom-grid" value="2020-03-14T14:23:00.000Z"></ion-datetime>
<ion-datetime id="custom-grid" value="2020-03-14T14:23:00.000Z" class="custom-grid-wheel"></ion-datetime>
</div>
<div class="grid-item">
<h2>Wheel Style</h2>
<ion-datetime id="custom-wheel" prefer-wheel="true" value="2020-03-14T14:23:00.000Z"></ion-datetime>
<ion-datetime
id="custom-wheel"
prefer-wheel="true"
value="2020-03-14T14:23:00.000Z"
class="custom-grid-wheel"
></ion-datetime>
</div>
<div class="grid-item">
<h2>Grid Style</h2>
<ion-datetime id="custom-calendar-days" value="2023-06-15" presentation="date"></ion-datetime>
</div>
</div>
</ion-content>
</ion-app>
<script>
const customDatetime = document.querySelector('#custom-calendar-days');
// Mock the current day to always have the same screenshots
const mockToday = '2023-06-10T16:22';
Date = class extends Date {
constructor(...args) {
if (args.length === 0) {
super(mockToday);
} else {
super(...args);
}
}
};
customDatetime.highlightedDates = [
{
date: '2023-06-02',
textColor: 'purple',
backgroundColor: 'pink',
},
{
date: '2023-06-04',
textColor: 'firebrick',
backgroundColor: 'salmon',
},
{
date: '2023-06-06',
textColor: 'blue',
backgroundColor: 'lightblue',
},
];
</script>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Some files were not shown because too many files have changed in this diff Show More