Skip to content
Merged
22 changes: 21 additions & 1 deletion core/src/components/datetime/datetime.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,16 @@ export class Datetime implements ComponentInterface {
private clearFocusVisible?: () => void;
private overlayIsPresenting = false;

/**
* Whether to highlight the active day with a solid circle (as opposed
* to the outline circle around today). If you don't specify an initial
* value for the datetime, it doesn't automatically init to a default to
* avoid unwanted change events firing. If the solid circle were still
* shown then, it would look like a date had already been selected, which
* is misleading UX.
*/
private highlightActiveParts = false;

private parsedMinuteValues?: number[];
private parsedHourValues?: number[];
private parsedMonthValues?: number[];
Expand Down Expand Up @@ -1058,6 +1068,7 @@ export class Datetime implements ComponentInterface {
};

private processValue = (value?: string | null) => {
this.highlightActiveParts = !!value;
const valueToProcess = value || getToday();
const { month, day, year, hour, minute, tzOffset } = parseDate(valueToProcess);

Expand Down Expand Up @@ -1349,6 +1360,7 @@ export class Datetime implements ComponentInterface {
}

private renderMonth(month: number, year: number) {
const { highlightActiveParts } = this;
const yearAllowed = this.parsedYearValues === undefined || this.parsedYearValues.includes(year);
const monthAllowed = this.parsedMonthValues === undefined || this.parsedMonthValues.includes(month);
const isCalMonthDisabled = !yearAllowed || !monthAllowed;
Expand Down Expand Up @@ -1424,7 +1436,7 @@ export class Datetime implements ComponentInterface {
class={{
'calendar-day-padding': day === null,
'calendar-day': true,
'calendar-day-active': isActive,
'calendar-day-active': isActive && highlightActiveParts,
'calendar-day-today': isToday,
}}
aria-selected={ariaSelected}
Expand All @@ -1434,6 +1446,14 @@ export class Datetime implements ComponentInterface {
return;
}

/**
* Note that for datetimes with confirm/cancel buttons, the value
* isn't updated until you call confirm(). We need to bring the
* solid circle back on day click for UX reasons, rather than only
* show the circle if `value` is truthy.
*/
this.highlightActiveParts = true;

this.setWorkingParts({
...this.workingParts,
month,
Expand Down
30 changes: 30 additions & 0 deletions core/src/components/datetime/test/basic/datetime.e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { expect } from '@playwright/test';
import type { E2EPage } from '@utils/test/playwright';
import { test } from '@utils/test/playwright';

test.describe('datetime: selecting a day', () => {
const testHighlight = async (page: E2EPage, datetimeID: string) => {
const today = new Date();
await page.goto('/src/components/datetime/test/basic');

const todayBtn = page.locator(
`#${datetimeID} .calendar-day[data-day='${today.getDate()}'][data-month='${today.getMonth() + 1}']`
);

expect(todayBtn).toHaveClass(/calendar-day-today/);
expect(todayBtn).not.toHaveClass(/calendar-day-active/);

await todayBtn.click();
await page.waitForChanges();

expect(todayBtn).toHaveClass(/calendar-day-active/);
};

test('should not highlight a day until one is selected', async ({ page }) => {
await testHighlight(page, 'inline-datetime-no-value');
});

test('should not highlight a day until one is selected, with default-buttons', async ({ page }) => {
await testHighlight(page, 'custom-datetime');
});
});
5 changes: 5 additions & 0 deletions core/src/components/datetime/test/basic/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,11 @@ <h2>Inline</h2>
<ion-datetime value="2020-03-14T14:23:00.000Z" id="inline-datetime"></ion-datetime>
</div>

<div class="grid-item">
<h2>Inline - No Default Value</h2>
<ion-datetime id="inline-datetime-no-value"></ion-datetime>
</div>

<div class="grid-item">
<h2>Popover</h2>
<ion-button onclick="presentPopover(defaultPopover, event)">Present Popover</ion-button>
Expand Down