Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,37 @@

All notable changes for each version of this project will be documented in this file.

## Unreleased

### New Features

- **Animations**
- The animation service and the `igniteui-angular/animations` presets run on the native Web Animations API. `@angular/animations` is no longer a peer dependency and `provideAnimations()` is not required for Ignite UI components.
- Presets are callable. Pass overrides directly: `slideInTop({ duration: 1000, fromPosition: 'translateY(100%)' })`. A bare preset (`openAnimation: slideInTop`) keeps its defaults. Every family exports its params interface (`SlideParams`, `ScaleParams`, ...).
- `animation(keyframes, options)` builds a custom `AnimationReferenceMetadata` from Web Animations API keyframes.
- `provideIgxAnimations('auto' | 'always' | 'none')` controls motion globally. `'auto'` (default) honors `prefers-reduced-motion`. `provideIgxNoopAnimations()` disables animations, e.g. in tests.
- `IGX_ANIMATION_SERVICE` is the injection token for the `AnimationService`. Players expose `state` and `started` signals and a `finished$` observable.

### Breaking Changes

- **Animations**
- `useAnimation(preset, { params })` from `@angular/animations` is no longer accepted by `openAnimation`/`closeAnimation` (overlay `PositionSettings`, `ToggleAnimationSettings`, carousel). Use `preset({ ...params })`. The `ng update` migration rewrites these calls, converting `'350ms'`/`'.35s'` durations to milliseconds and `AnimationReferenceMetadata` type annotations to `AnimationInput`.
- `duration` and `delay` are numbers in milliseconds. `easing` stays a CSS easing string.
- `AnimationReferenceMetadata` now means the Web Animations API shape `{ steps: Keyframe[]; options?: KeyframeAnimationOptions }` exported from `igniteui-angular/animations`. Custom animations authored with Angular's `animation()`/`style()`/`animate()` must be rewritten as keyframes.
- `IAnimationParams` is replaced by `AnimationParams` plus the per-family params interfaces. `AnimationUtil` is replaced by `reverseAnimation()`, `isHorizontalAnimation()` and `isVerticalAnimation()`, which also work on parameterized presets.
- `IgxAngularAnimationService` and `IgxAngularAnimationPlayer` are removed. Inject `IGX_ANIMATION_SERVICE` instead. `AnimationService.buildAnimation()` is now `build()`.
- `AnimationPlayer`: `hasStarted()` is the `started` signal, `animationEnd` is `finished$`, `init()` and `animationStart` are removed, `pause()` is added. `finished$` is delivered asynchronously and never fires on `reset()` or `destroy()`.
- `NoopAnimationsModule`/`provideNoopAnimations()` no longer disable Ignite UI animations in tests. Use `provideIgxNoopAnimations()`.

### Behavioral Changes

- **Animations** - `prefers-reduced-motion: reduce` disables Ignite UI animations by default. Opt out with `provideIgxAnimations('always')`.

### Bug Fixes

- `IgxGridComponent`
- Pressing Tab on the filtering row's condition icon closes the conditions dropdown instead of reopening it.

## 22.2.0

### New Features
Expand Down
17 changes: 0 additions & 17 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@
},
"private": true,
"dependencies": {
"@angular/animations": "^22.0.0",
"@angular/common": "^22.0.0",
"@angular/compiler": "^22.0.0",
"@angular/core": "^22.0.0",
Expand Down
2 changes: 0 additions & 2 deletions projects/bundle-test/src/app/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { NavigationError, provideRouter, withNavigationErrorHandler } from '@ang

import { routes } from './app.routes';
import { provideClientHydration, withNoIncrementalHydration } from '@angular/platform-browser';
import { provideAnimations } from '@angular/platform-browser/animations';

export const appConfig: ApplicationConfig = {
providers: [
Expand All @@ -12,7 +11,6 @@ export const appConfig: ApplicationConfig = {
// force failed routes to throw & fail the SSG part of the build
withNavigationErrorHandler((e: NavigationError) => { throw e; })
),
provideAnimations(),
provideClientHydration(withNoIncrementalHydration())
]
};
2 changes: 0 additions & 2 deletions projects/igniteui-angular-elements/src/utils/injector-ref.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { createEnvironmentInjector, EnvironmentInjector, getPlatform, importProvidersFrom, provideZonelessChangeDetection } from '@angular/core';
import { BrowserModule, platformBrowser } from '@angular/platform-browser';
import { provideAnimations } from '@angular/platform-browser/animations';
import { IgxIconBroadcastService } from '../lib/icon.broadcast.service';
import { ELEMENTS_TOKEN , provideIgniteIntl} from 'igniteui-angular/core';

Expand All @@ -27,7 +26,6 @@ const injector = createEnvironmentInjector([
provideZonelessChangeDetection(),
importProvidersFrom(BrowserModule),
// Elements specific:
provideAnimations(),
{ provide: ELEMENTS_TOKEN, useValue: true },
IgxIconBroadcastService,
provideIgniteIntl()
Expand Down
4 changes: 1 addition & 3 deletions projects/igniteui-angular-performance/src/app/app.config.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import { ApplicationConfig, provideBrowserGlobalErrorListeners, provideZoneChangeDetection } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideAnimations } from '@angular/platform-browser/animations';

import { routes } from './app.routes';

export const appConfig: ApplicationConfig = {
providers: [
provideBrowserGlobalErrorListeners(),
provideZoneChangeDetection({ eventCoalescing: true }),
provideRouter(routes),
provideAnimations()
provideRouter(routes)
]
};
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { useAnimation } from '@angular/animations';
import { Component, ViewChild, ChangeDetectionStrategy } from '@angular/core';
import { waitForAsync, TestBed, fakeAsync, ComponentFixture, tick } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { provideIgxNoopAnimations } from 'igniteui-angular/core';
import { IgxExpansionPanelBodyComponent, IgxExpansionPanelComponent, IgxExpansionPanelHeaderComponent, IgxExpansionPanelTitleDirective } from '../../../expansion-panel/src/public_api';
import { IAccordionCancelableEventArgs, IAccordionEventArgs, IgxAccordionComponent } from './accordion.component';
import { slideInLeft, slideOutRight } from 'igniteui-angular/animations';
import { resolveAnimation, slideInLeft, slideOutRight } from 'igniteui-angular/animations';
import { UIInteractions } from 'igniteui-angular/test-utils/ui-interactions.spec';

const ACCORDION_CLASS = 'igx-accordion';
Expand All @@ -19,9 +18,9 @@ describe('Rendering Tests', () => {
waitForAsync(() => {
TestBed.configureTestingModule({
imports: [
NoopAnimationsModule,
IgxAccordionSampleTestComponent
]
],
providers: [provideIgxNoopAnimations()]
}).compileComponents();
})
);
Expand All @@ -44,21 +43,21 @@ describe('Rendering Tests', () => {

it('Should allow overriding animationSettings that are used for expansion panels toggle', () => {
const animationSettingsCustom = {
closeAnimation: useAnimation(slideOutRight, { params: { duration: '100ms', toPosition: 'translateX(25px)' } }),
openAnimation: useAnimation(slideInLeft, { params: { duration: '500ms', fromPosition: 'translateX(-15px)' } })
closeAnimation: slideOutRight({ duration: 100, toPosition: 'translateX(25px)' }),
openAnimation: slideInLeft({ duration: 500, fromPosition: 'translateX(-15px)' })
};

const animationSettingsCustomPanel = {
closeAnimation: useAnimation(slideOutRight, { params: { duration: '200ms', toPosition: 'translateX(25px)' } }),
openAnimation: useAnimation(slideInLeft, { params: { duration: '500ms', fromPosition: 'translateX(-15px)' } })
closeAnimation: slideOutRight({ duration: 200, toPosition: 'translateX(25px)' }),
openAnimation: slideInLeft({ duration: 500, fromPosition: 'translateX(-15px)' })
};

accordion.panels[0].animationSettings = animationSettingsCustomPanel;

accordion.animationSettings = animationSettingsCustom;

for (let i = 0; i < 3; i++) {
expect(accordion.panels[i].animationSettings.closeAnimation.options.params.duration).toEqual('100ms');
expect(resolveAnimation(accordion.panels[i].animationSettings.closeAnimation).options.duration).toEqual(100);
}
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ import { IgxActionStripComponent, IgxActionStripMenuItemDirective } from './acti
import { Component, ViewChild, ElementRef, ViewContainerRef, ChangeDetectionStrategy } from '@angular/core';
import { TestBed, waitForAsync } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { IgxIconComponent } from 'igniteui-angular/icon';
import { ActionStripResourceStringsEN, changei18n } from 'igniteui-angular/core';
import { ActionStripResourceStringsEN, changei18n, provideIgxNoopAnimations } from 'igniteui-angular/core';
import { wait } from '../../../test-utils/ui-interactions.spec';

const ACTION_STRIP_CONTAINER_CSS = 'igx-action-strip__actions';
Expand All @@ -20,12 +19,12 @@ describe('igxActionStrip', () => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [
NoopAnimationsModule,
IgxActionStripComponent,
IgxActionStripTestingComponent,
IgxActionStripMenuTestingComponent,
IgxActionStripCombinedMenuTestingComponent
]
],
providers: [provideIgxNoopAnimations()]
}).compileComponents();
}));

Expand Down
110 changes: 74 additions & 36 deletions projects/igniteui-angular/animations/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# Animations

Ignite UI for Angular includes over 100+ pre-built animations. They are split in 7 groups:
Ignite UI for Angular includes over 100+ pre-built animations. They are split in 8 groups:

- [Fade](https://github.com/IgniteUI/igniteui-angular/tree/master/projects/igniteui-angular/animations/src/fade/README.md)
- [Flip](https://github.com/IgniteUI/igniteui-angular/tree/master/projects/igniteui-angular/animations/src/flip/README.md)
- [Grow](https://github.com/IgniteUI/igniteui-angular/tree/master/projects/igniteui-angular/animations/src/grow/README.md)
- [Miscellaneous](https://github.com/IgniteUI/igniteui-angular/tree/master/projects/igniteui-angular/animations/src/misc/README.md)
- Blink
- Heartbeat
Expand All @@ -14,37 +15,76 @@ Ignite UI for Angular includes over 100+ pre-built animations. They are split in
- [Slide](https://github.com/IgniteUI/igniteui-angular/tree/master/projects/igniteui-angular/animations/src/slide/README.md)
- [Swing](https://github.com/IgniteUI/igniteui-angular/tree/master/projects/igniteui-angular/animations/src/swing/README.md)

Each group accepts a different set of parameters, allowing you to modify the behavior of any of the included animations. Each animation is an [`AnimationReferenceMetadata`](https://angular.io/api/animations/AnimationReferenceMetadata) object as produced by the [`animation`](https://angular.io/api/animations/animation) function provided by Angular.
Animations are built on the [Web Animations API](https://developer.mozilla.org/docs/Web/API/Web_Animations_API). `@angular/animations` is not required.

Reusable animations are designed to make use of animations parameters and the produced animation can be used via the [`useAnimation`](https://angular.io/api/animations/useAnimation) function.
Each animation is an `AnimationPreset`: a callable with defaults. Use it bare, or call it with a partial set of params to override the defaults:

Below is a sample implementation of the fadeIn animation:
``` typescript
import { fadeIn } from "igniteui-angular/animations";

fadeIn
fadeIn({ duration: 1000, startOpacity: 0.2 })
```

Each group exports a params interface (`FadeParams`, `SlideParams`, ...). All extend `AnimationParams`:

``` typescript
interface AnimationParams {
duration: number; // ms
delay: number; // ms
easing: string; // CSS easing
}
```

Calling a preset produces an `AnimationReferenceMetadata`, plain WAAPI keyframes plus timing options:

``` typescript
interface AnimationReferenceMetadata {
steps: Keyframe[];
options?: KeyframeAnimationOptions;
}
```

Below is the implementation of the fadeIn animation:

``` typescript
const base: AnimationMetadata[] = [
style({
opacity: `{{startOpacity}}`
}),
animate(
`{{duration}} {{delay}} {{easing}}`,
style({
opacity: `{{endOpacity}}`
})
)
export interface FadeParams extends AnimationParams {
startOpacity: number;
endOpacity: number;
}

const steps = (p: FadeParams): Keyframe[] => [
{ opacity: p.startOpacity },
{ opacity: p.endOpacity }
];

const baseParams: IAnimationParams = {
delay: "0s",
duration: "350ms",
easing: EaseOut.sine,
export const fadeIn = definePreset<FadeParams>('fadeIn', {
delay: 0,
duration: 350,
easing: EaseOut.Sine,
endOpacity: 1,
startOpacity: 0
};
}, steps);
```

## Custom animations

Wrap raw keyframes with `animation`:

``` typescript
import { animation } from "igniteui-angular/animations";

const fadeIn: AnimationReferenceMetadata = animation(base, {
params: { ...baseParams }
});
const custom = animation(
[{ opacity: 0 }, { opacity: 1 }],
{ duration: 300, easing: "ease-out" }
);
```

## Utilities

- `reverseAnimation(input)` - mirrored counterpart with the same overrides, e.g. `slideInLeft({ duration: 1000 })` becomes `slideInRight({ duration: 1000 })`. Unknown inputs come back unchanged.
- `isHorizontalAnimation(input)` / `isVerticalAnimation(input)` - axis the preset moves along.

N.B.:
Some of the animations from the Flip, Rotate, and Swing groups require the parent, containing the elements being animated, to have [`perspective`](https://developer.mozilla.org/en/docs/Web/CSS/perspective) as part of its CSS properties.

Expand All @@ -53,25 +93,23 @@ Some of the animations from the Flip, Rotate, and Swing groups require the paren
Ignite UI for Angular includes a set of timing functions that can be used to ease in or out an animation.
There are three main timing function groups - **EaseIn**, **EaseOut**, and **EaseInOut**; each containing the following timings:

- quad
- cubic
- quart
- quint
- sine
- expo
- circ
- back
- Quad
- Cubic
- Quart
- Quint
- Sine
- Expo
- Circ
- Back

Each is a CSS `cubic-bezier()` string. Any CSS easing string works as well.

To use a specific timing function, import it first:
``` typescript
``` typescript
import { EaseOut } from "igniteui-angular/animations";
```
and then use it as value for the easing param in any animation:

``` typescript
useAnimation(fadeIn, {
params: {
easing: EaseOut.back
}
});
fadeIn({ easing: EaseOut.Back });
```
Loading
Loading