diff --git a/src/components/ids-modal/ids-modal.ts b/src/components/ids-modal/ids-modal.ts index ea8e285f71..1e60c7febd 100644 --- a/src/components/ids-modal/ids-modal.ts +++ b/src/components/ids-modal/ids-modal.ts @@ -6,7 +6,7 @@ import Base from './ids-modal-base'; import { stringToBool } from '../../utils/ids-string-utils/ids-string-utils'; import { waitForTransitionEnd } from '../../utils/ids-dom-utils/ids-dom-utils'; -import { cssAnimationTimeout } from '../../utils/ids-timer-utils/ids-timer-utils'; +import { cssTransitionTimeout } from '../../utils/ids-timer-utils/ids-timer-utils'; import zCounter from './ids-modal-z-counter'; import '../ids-popup/ids-popup'; @@ -602,7 +602,7 @@ export default class IdsModal extends Base { * @param {any} e the original event object */ async handleButtonClick(e: any): Promise { - await cssAnimationTimeout(200); + await cssTransitionTimeout(200); if (typeof this.onButtonClick === 'function') { this.onButtonClick(e.target); diff --git a/src/components/ids-swipe-action/ids-swipe-action.ts b/src/components/ids-swipe-action/ids-swipe-action.ts index 3509502b80..903e8f3d8b 100644 --- a/src/components/ids-swipe-action/ids-swipe-action.ts +++ b/src/components/ids-swipe-action/ids-swipe-action.ts @@ -5,7 +5,7 @@ import Base from './ids-swipe-action-base'; import styles from './ids-swipe-action.scss'; -import { cssAnimationTimeout } from '../../utils/ids-timer-utils/ids-timer-utils'; +import { cssTransitionTimeout } from '../../utils/ids-timer-utils/ids-timer-utils'; /** * IDS SwipeAction Component @@ -60,9 +60,9 @@ export default class IdsSwipeAction extends Base { // Fix scroll position this.container.style.visibility = 'hidden'; this.container.style.scrollBehavior = 'auto'; - await cssAnimationTimeout(40); + await cssTransitionTimeout(40); this.container.scrollLeft = 85; - await cssAnimationTimeout(1); + await cssTransitionTimeout(1); this.container.style.scrollBehavior = 'smooth'; this.container.style.visibility = ''; } diff --git a/src/utils/ids-timer-utils/README.md b/src/utils/ids-timer-utils/README.md index 364a99e5fe..4ae1322260 100644 --- a/src/utils/ids-timer-utils/README.md +++ b/src/utils/ids-timer-utils/README.md @@ -4,11 +4,22 @@ These utilities provide performance-friendly alternatives to `setTimeout` and `s `requestAnimationTimeout` and `requestAnimationInterval` behave similarly to the built-in browser APIs. A `FrameRequestLoopHandler` object is returned, which wraps a number value representing a `timeoutId`. In the event `requestAnimationFrame` isn't available in the browser, these utils will fall back to `setTimeout` and `setInterval` respectively. +`cssTransitionTimeout` is another timeout method that uses a CSS transition and waits for events. A duration can be passed to set the `transition-duration` property of an hidden, animated element. When the transition completes, the specified callback is run. + Note that these utils should be used sparingly, and extra care should be taken to use async/await, CSS animations, or other alternatives to arbitrary timeouts where possible. ## Code Examples -### Timeouts +### `cssTransitionTimeout` + +```ts +import { cssTransitionTimeout } from 'ids-enterprise-wc/utils/ids-timer-utils/ids-timer-utils'; + +await cssTransitionTimeout(200); +// Do something after 200ms +``` + +### `requestAnimationTimeout` ```ts import { requestAnimationTimeout, clearAnimationTimeout } from 'ids-enterprise-wc/utils/ids-timer-utils/ids-timer-utils'; @@ -28,7 +39,7 @@ It's also possible to prematurely cancel this behavior: clearAnimationTimeout(timeout); ``` -### Intervals +### `requestAnimationInterval` ```ts import { requestAnimationInterval, clearAnimationInterval } from 'ids-enterprise-wc/utils/ids-timer-utils/ids-timer-utils'; diff --git a/src/utils/ids-timer-utils/ids-timer-utils.ts b/src/utils/ids-timer-utils/ids-timer-utils.ts index 555f1aec87..46b2ce8007 100644 --- a/src/utils/ids-timer-utils/ids-timer-utils.ts +++ b/src/utils/ids-timer-utils/ids-timer-utils.ts @@ -84,9 +84,9 @@ export function clearAnimationTimeout(handle: FrameRequestLoopHandler) { * @param {number} timeout the transition duration in ms * @returns {Promise} resolved when the CSS transition completes */ -export const cssAnimationTimeout = async (timeout: number): Promise => new Promise((resolve) => { +export const cssTransitionTimeout = async (timeout: number): Promise => new Promise((resolve) => { const el = document.createElement('div'); - el.classList.add('ids-animation-timer'); + el.classList.add('ids-transition-timeout'); el.style.setProperty('display', 'block'); el.style.setProperty('position', 'absolute'); el.style.setProperty('visibility', 'hidden'); diff --git a/test/core/ids-timer-utils-func-test.ts b/test/core/ids-timer-utils-func-test.ts index c7ad923e72..b0a136ebd5 100644 --- a/test/core/ids-timer-utils-func-test.ts +++ b/test/core/ids-timer-utils-func-test.ts @@ -4,6 +4,7 @@ import { clearAnimationInterval, clearAnimationTimeout, + cssTransitionTimeout, requestAnimationInterval, requestAnimationTimeout, } from '../../src/utils/ids-timer-utils/ids-timer-utils'; @@ -11,7 +12,10 @@ import type { FrameRequestLoopHandler } from '../../src/utils/ids-timer-utils/id import wait from '../helpers/wait'; import waitForTimeout from '../helpers/wait-for-timeout'; -describe('IdsTimerUtils tests', () => { +import '../../src/components/ids-modal/ids-modal'; +import '../../src/components/ids-modal-button/ids-modal-button'; + +describe('IdsTimerUtils tests (requestAnimationFrame)', () => { let el: HTMLDivElement | null; beforeEach(() => { @@ -69,3 +73,15 @@ describe('IdsTimerUtils tests', () => { await waitForTimeout(() => expect(count).toBeLessThan(4)); }); }); + +describe('IdsTimerUtils (CSS Transitions)', () => { + it.skip('can execute functions after a CSS transition completes', async () => { + expect(document.querySelector('.ids-transition-timeout')).toBe(null); + + // Kickoff a timeout (don't wait for this one) + await cssTransitionTimeout(200); + + // Hidden tested elements should be cleaned up + expect(document.querySelector('.ids-transition-timeout')).toBe(null); + }); +});