diff --git a/core/src/components.d.ts b/core/src/components.d.ts index 81ccd9db23..14d14454de 100644 --- a/core/src/components.d.ts +++ b/core/src/components.d.ts @@ -2043,6 +2043,10 @@ export namespace Components { * The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics). */ "color"?: Color; + /** + * If `true`, the user cannot interact with the picker. + */ + "disabled": boolean; /** * A list of options to be displayed in the picker */ @@ -6683,6 +6687,10 @@ declare namespace LocalJSX { * The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics). */ "color"?: Color; + /** + * If `true`, the user cannot interact with the picker. + */ + "disabled"?: boolean; /** * A list of options to be displayed in the picker */ diff --git a/core/src/components/datetime/datetime.tsx b/core/src/components/datetime/datetime.tsx index d2c6cd6d0b..599dd718d1 100644 --- a/core/src/components/datetime/datetime.tsx +++ b/core/src/components/datetime/datetime.tsx @@ -1538,7 +1538,7 @@ export class Datetime implements ComponentInterface { } private renderCombinedDatePickerColumn() { - const { defaultParts, workingParts, locale, minParts, maxParts, todayParts, isDateEnabled } = this; + const { defaultParts, disabled, workingParts, locale, minParts, maxParts, todayParts, isDateEnabled } = this; const activePart = this.getActivePartsWithFallback(); @@ -1617,6 +1617,7 @@ export class Datetime implements ComponentInterface { { @@ -1728,7 +1729,7 @@ export class Datetime implements ComponentInterface { return []; } - const { workingParts } = this; + const { disabled, workingParts } = this; const activePart = this.getActivePartsWithFallback(); @@ -1736,6 +1737,7 @@ export class Datetime implements ComponentInterface { { @@ -1772,7 +1774,7 @@ export class Datetime implements ComponentInterface { return []; } - const { workingParts } = this; + const { disabled, workingParts } = this; const activePart = this.getActivePartsWithFallback(); @@ -1780,6 +1782,7 @@ export class Datetime implements ComponentInterface { { @@ -1815,7 +1818,7 @@ export class Datetime implements ComponentInterface { return []; } - const { workingParts } = this; + const { disabled, workingParts } = this; const activePart = this.getActivePartsWithFallback(); @@ -1823,6 +1826,7 @@ export class Datetime implements ComponentInterface { { @@ -1888,7 +1892,7 @@ export class Datetime implements ComponentInterface { } private renderHourPickerColumn(hoursData: PickerColumnItem[]) { - const { workingParts } = this; + const { disabled, workingParts } = this; if (hoursData.length === 0) return []; const activePart = this.getActivePartsWithFallback(); @@ -1896,6 +1900,7 @@ export class Datetime implements ComponentInterface { return ( { diff --git a/core/src/components/datetime/test/disabled/datetime.spec.tsx b/core/src/components/datetime/test/disabled/datetime.spec.tsx new file mode 100644 index 0000000000..9d6f6c8553 --- /dev/null +++ b/core/src/components/datetime/test/disabled/datetime.spec.tsx @@ -0,0 +1,39 @@ +import { h } from '@stencil/core'; +import { newSpecPage } from '@stencil/core/testing'; + +import { Datetime } from '../../../datetime/datetime'; +import { PickerColumnInternal } from '../../../picker-column-internal/picker-column-internal'; +import { PickerInternal } from '../../../picker-internal/picker-internal'; + +describe('ion-datetime disabled', () => { + beforeEach(() => { + // IntersectionObserver isn't available in test environment + const mockIntersectionObserver = jest.fn(); + mockIntersectionObserver.mockReturnValue({ + observe: () => null, + unobserve: () => null, + disconnect: () => null, + }); + global.IntersectionObserver = mockIntersectionObserver; + }); + + it('picker should be disabled in prefer wheel mode', async () => { + const page = await newSpecPage({ + components: [Datetime, PickerColumnInternal, PickerInternal], + template: () => ( + + ), + }); + + await page.waitForChanges(); + + const datetime = page.body.querySelector('ion-datetime')!; + const columns = datetime.shadowRoot!.querySelectorAll('ion-picker-column-internal'); + + await expect(columns.length).toEqual(4); + + columns.forEach((column) => { + expect(column.disabled).toBe(true); + }); + }); +}); diff --git a/core/src/components/datetime/test/disabled/index.html b/core/src/components/datetime/test/disabled/index.html index 764d3a42ca..b0a8ac364b 100644 --- a/core/src/components/datetime/test/disabled/index.html +++ b/core/src/components/datetime/test/disabled/index.html @@ -66,6 +66,11 @@

Inline - No Default Value

+ +
+

Inline - Prefer Wheel

+ +
diff --git a/core/src/components/picker-column-internal/test/disabled/picker-column-internal.e2e.ts b/core/src/components/picker-column-internal/test/disabled/picker-column-internal.e2e.ts index 9629f4345d..5e6464c22a 100644 --- a/core/src/components/picker-column-internal/test/disabled/picker-column-internal.e2e.ts +++ b/core/src/components/picker-column-internal/test/disabled/picker-column-internal.e2e.ts @@ -35,7 +35,7 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => { * This behavior does not vary across modes/directions. */ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => { - test.describe(title('picker-column-internal: disabled'), () => { + test.describe(title('picker-column-internal: disabled items'), () => { test('all picker items should be enabled by default', async ({ page }) => { await page.setContent( ` @@ -55,9 +55,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => config ); - const pickerItems = page.locator( - 'ion-picker-column-internal .picker-item:not(.picker-item-empty, .picker-item-disabled)' - ); + const pickerItems = page.locator('ion-picker-column-internal .picker-item:not(.picker-item-empty, [disabled])'); expect(await pickerItems.count()).toBe(3); }); @@ -80,7 +78,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => config ); - const disabledItem = page.locator('ion-picker-column-internal .picker-item.picker-item-disabled'); + const disabledItem = page.locator('ion-picker-column-internal .picker-item[disabled]'); await expect(disabledItem).not.toBeEnabled(); }); test('disabled picker item should not be considered active', async ({ page }) => { @@ -130,7 +128,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => await page.waitForChanges(); const disabledItem = page.locator('ion-picker-column-internal .picker-item[data-value="b"]'); - await expect(disabledItem).toHaveClass(/picker-item-disabled/); + await expect(disabledItem).toBeDisabled(); await expect(disabledItem).not.toHaveClass(/picker-item-active/); }); test('defaulting the value to a disabled item should not cause that item to be active', async ({ page }) => { @@ -154,8 +152,42 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => ); const disabledItem = page.locator('ion-picker-column-internal .picker-item[data-value="b"]'); - await expect(disabledItem).toHaveClass(/picker-item-disabled/); + await expect(disabledItem).toBeDisabled(); await expect(disabledItem).not.toHaveClass(/picker-item-active/); }); }); }); + +/** + * This behavior does not vary across directions. + */ +configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => { + test.describe(title('picker-column-internal: disabled column rendering'), () => { + test.beforeEach(async ({ page }) => { + await page.goto('/src/components/picker-column-internal/test/disabled', config); + }); + + test('disabled column should not have visual regressions', async ({ page }) => { + const disabledColumn = page.locator('#column-disabled'); + await page.waitForChanges(); + + await expect(disabledColumn).toHaveScreenshot(screenshot('picker-internal-disabled-column')); + }); + }); +}); + +/** + * This behavior does not vary across modes/directions. + */ +configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => { + test.describe(title('picker-column-internal: disabled column'), () => { + test.beforeEach(async ({ page }) => { + await page.goto('/src/components/picker-column-internal/test/disabled', config); + }); + + test('item in disabled column should not be interactive', async ({ page }) => { + const secondItem = page.locator('#column-disabled .picker-item:not(.picker-item-empty)').nth(1); + await expect(secondItem).toBeDisabled(); + }); + }); +}); diff --git a/core/src/components/picker-column-internal/test/disabled/picker-column-internal.e2e.ts-snapshots/picker-internal-disabled-column-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/picker-column-internal/test/disabled/picker-column-internal.e2e.ts-snapshots/picker-internal-disabled-column-ios-ltr-Mobile-Chrome-linux.png new file mode 100644 index 0000000000..2553d3aefd Binary files /dev/null and b/core/src/components/picker-column-internal/test/disabled/picker-column-internal.e2e.ts-snapshots/picker-internal-disabled-column-ios-ltr-Mobile-Chrome-linux.png differ diff --git a/core/src/components/picker-column-internal/test/disabled/picker-column-internal.e2e.ts-snapshots/picker-internal-disabled-column-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/picker-column-internal/test/disabled/picker-column-internal.e2e.ts-snapshots/picker-internal-disabled-column-ios-ltr-Mobile-Firefox-linux.png new file mode 100644 index 0000000000..da5bca77aa Binary files /dev/null and b/core/src/components/picker-column-internal/test/disabled/picker-column-internal.e2e.ts-snapshots/picker-internal-disabled-column-ios-ltr-Mobile-Firefox-linux.png differ diff --git a/core/src/components/picker-column-internal/test/disabled/picker-column-internal.e2e.ts-snapshots/picker-internal-disabled-column-ios-ltr-Mobile-Safari-linux.png b/core/src/components/picker-column-internal/test/disabled/picker-column-internal.e2e.ts-snapshots/picker-internal-disabled-column-ios-ltr-Mobile-Safari-linux.png new file mode 100644 index 0000000000..7939d8892d Binary files /dev/null and b/core/src/components/picker-column-internal/test/disabled/picker-column-internal.e2e.ts-snapshots/picker-internal-disabled-column-ios-ltr-Mobile-Safari-linux.png differ diff --git a/core/src/components/picker-column-internal/test/disabled/picker-column-internal.e2e.ts-snapshots/picker-internal-disabled-column-md-ltr-Mobile-Chrome-linux.png b/core/src/components/picker-column-internal/test/disabled/picker-column-internal.e2e.ts-snapshots/picker-internal-disabled-column-md-ltr-Mobile-Chrome-linux.png new file mode 100644 index 0000000000..6968e26058 Binary files /dev/null and b/core/src/components/picker-column-internal/test/disabled/picker-column-internal.e2e.ts-snapshots/picker-internal-disabled-column-md-ltr-Mobile-Chrome-linux.png differ diff --git a/core/src/components/picker-column-internal/test/disabled/picker-column-internal.e2e.ts-snapshots/picker-internal-disabled-column-md-ltr-Mobile-Firefox-linux.png b/core/src/components/picker-column-internal/test/disabled/picker-column-internal.e2e.ts-snapshots/picker-internal-disabled-column-md-ltr-Mobile-Firefox-linux.png new file mode 100644 index 0000000000..02bc29af22 Binary files /dev/null and b/core/src/components/picker-column-internal/test/disabled/picker-column-internal.e2e.ts-snapshots/picker-internal-disabled-column-md-ltr-Mobile-Firefox-linux.png differ diff --git a/core/src/components/picker-column-internal/test/disabled/picker-column-internal.e2e.ts-snapshots/picker-internal-disabled-column-md-ltr-Mobile-Safari-linux.png b/core/src/components/picker-column-internal/test/disabled/picker-column-internal.e2e.ts-snapshots/picker-internal-disabled-column-md-ltr-Mobile-Safari-linux.png new file mode 100644 index 0000000000..d94af6fdb6 Binary files /dev/null and b/core/src/components/picker-column-internal/test/disabled/picker-column-internal.e2e.ts-snapshots/picker-internal-disabled-column-md-ltr-Mobile-Safari-linux.png differ