Taiga UI 5 is out!

Slides LAYOUT

Examples API GitHub

On this page

A component for displaying dynamic content animated between states. Use negative value for tuiSlides to indicate backward direction, positive for forward direction and 0 for static crossfade.

Important: each child must be exactly one DOM element.

Crossfade

Static crossfading of slides with slight delay for smoother overlap.
First slide
First slide First slide First slide First slide First slide First slide First slide First slide First slide First slide
    
      
    
    
      <div tuiGroup>
    <button
        appearance="secondary"
        iconStart="@tui.chevron-left"
        size="m"
        tuiIconButton
        type="button"
        [disabled]="!index"
        (click)="index = index - 1"
    >
        Previous
    </button>
    <button
        appearance="secondary"
        iconStart="@tui.chevron-right"
        size="m"
        tuiIconButton
        type="button"
        [disabled]="index === items.length - 1"
        (click)="index = index + 1"
    >
        Next
    </button>
</div>
<tui-elastic-container>
    <section tuiSlides>
        @for (item of items; track item) {
            @if ($index === index) {
                <div tuiTitle>
                    {{ item }}
                    <div tuiSubtitle>{{ item.repeat(10) }}</div>
                </div>
            }
        }
    </section>
</tui-elastic-container>

    
    
      [tuiGroup] {
    inline-size: fit-content;
    margin: 0 auto 1rem;
}

[tuiSubtitle] {
    color: var(--tui-text-secondary);
}

[tuiTitle] {
    --tui-duration: 0.6s;

    animation-delay: 0.3s;

    &.tui-leave {
        animation-delay: 0s;
    }
}

    

Stepper

Navigating back and forth using Stepper .

Registration form Tell us about yourself

    
      
    
    
      <tui-stepper
    [activeItemIndex]="index"
    (activeItemIndexChange)="onStep($event)"
>
    <button tuiStep>Personal details</button>
    <button tuiStep>Shipping address</button>
    <button tuiStep>Payment info</button>
</tui-stepper>
<tui-elastic-container>
    <section [tuiSlides]="direction">
        @for (form of forms; track form; let i = $index) {
            @if (i === index) {
                <form
                    appearance="floating"
                    tuiCardLarge
                    tuiForm
                    [formGroup]="form"
                    [id]="`form_${i}`"
                    (ngSubmit)="onSubmit()"
                >
                    <header tuiHeader>
                        <h2 tuiTitle>
                            Registration form
                            <span tuiSubtitle>Tell us about yourself</span>
                        </h2>
                    </header>
                    @for (control of form.controls | keyvalue; track control; let j = $index) {
                        <tui-textfield>
                            <label tuiLabel>{{ control.key }}</label>
                            <input
                                tuiInput
                                [formControlName]="control.key"
                                [tuiAutoFocus]="!!index && !j"
                            />
                        </tui-textfield>
                    }
                </form>
            }
        }
    </section>
</tui-elastic-container>
<footer>
    <button
        appearance="secondary"
        tuiButton
        type="button"
        [disabled]="!index"
        (click)="index = index - 1"
    >
        Back
    </button>

    <button
        tuiButton
        type="submit"
        [attr.form]="`form_${index}`"
    >
        Next
    </button>
</footer>

    
    
      tui-elastic-container {
    padding: 2rem;
    margin: 0 -2rem;
}

footer {
    display: flex;
    justify-content: space-between;
}

    

Routing

Animating nested routes, adding Animated to host directives of route component is required.
    
      <tui-tabs [activeItemIndex]="-1">
    <a
        routerLink="1"
        routerLinkActive
        tuiTab
    >
        Home
    </a>
    <a
        routerLink="2"
        routerLinkActive
        tuiTab
    >
        Notifications
    </a>
    <a
        routerLink="3"
        routerLinkActive
        tuiTab
    >
        Settings
    </a>
</tui-tabs>
<p [tuiSlides]="direction()">
    <router-outlet />
</p>

    

Dialog

Using slides inside a dialog.
    
      
    
    
      <button
    tuiButton
    type="button"
    (click)="onClick()"
>
    Show dialog
</button>
<ng-template let-observer>
    <tui-app-bar tuiAppBarSize>
        @if (step > 1) {
            <button
                tuiButton
                tuiSlot="start"
                type="button"
                (click)="onStep(-1)"
            >
                Back
            </button>
        }
        <progress
            size="s"
            tuiProgressBar
            [max]="3"
            [style.width.rem]="10"
            [value]="step"
        ></progress>
        <button
            tuiButton
            tuiSlot="end"
            type="button"
            (click)="observer.complete()"
        >
            Close
        </button>
    </tui-app-bar>
    <section [tuiSlides]="direction">
        @switch (step) {
            @case (1) {
                <div>
                    <header>Welcome to the slides demo</header>
                    <p>
                        These wrapping components will be animated upon navigating this modal dialog. This works well on
                        both desktop and mobile. In your own layouts watch out for unwanted scrollbars.
                    </p>
                </div>
            }
            @case (2) {
                <div>
                    <header>Header is optional</header>
                    <section [style.margin]="'0 -1rem'">
                        @for (_ of '-'.repeat(5); track $index) {
                            <div tuiCell>
                                <div
                                    appearance="primary"
                                    tuiAvatar="@tui.star"
                                ></div>
                                <div tuiTitle>
                                    Title
                                    <div tuiSubtitle>Description</div>
                                </div>
                            </div>
                        }
                    </section>
                </div>
            }
            @case (3) {
                <div
                    appearance="floating"
                    tuiCardLarge
                >
                    <header tuiHeader>
                        <h1 tuiTitle>
                            Title
                            <span tuiSubtitle>Subtitle</span>
                        </h1>
                        <aside tuiAccessories>
                            <div
                                appearance="primary"
                                tuiAvatar="@tui.star"
                            ></div>
                        </aside>
                    </header>
                    <footer>
                        <button
                            appearance="secondary"
                            size="m"
                            tuiButton
                            type="button"
                        >
                            Label
                        </button>
                    </footer>
                </div>
            }
        }
    </section>
    <footer
        tuiFloatingContainer
        [style.margin-block-start]="'auto'"
    >
        <button
            tuiButton
            type="button"
            (click)="step < 3 ? onStep(1) : observer.complete()"
        >
            {{ step < 3 ? 'Next' : 'OK' }}
        </button>
    </footer>
</ng-template>