# addons.md ```bash npm i @taiga-ui/addon-charts // Components for various charts, graphs and visualizations npm i @taiga-ui/addon-commerce // Money-related extension with currencies, credit card inputs and validators npm i @taiga-ui/addon-mobile // Components and tools specific to mobile version of the app npm i @taiga-ui/addon-table // Interactive table component and related utilities npm i @taiga-ui/addon-doc // Taiga UI based library for developing documentation portals for Angular libraries npm i @taiga-ui/layout // Layout components ``` --- # angular-json-styles.md ```json { "projects": { "my-project": { "architect": { "build": { "options": { "styles": [ "@taiga-ui/core/styles/taiga-ui-theme.less", "@taiga-ui/core/styles/taiga-ui-fonts.less", "@taiga-ui/addon-mobile/styles/taiga-ui-mobile.less" // optional ] } } } } } } ``` --- # app-standalone.md ```ts import {TuiRoot} from '@taiga-ui/core'; // .. @Component({ standalone: true, selector: 'app-root', imports: [ TuiRoot, // ... ], templateUrl: './app.component.html', }) export class App {} ``` --- # app-template.md ```html ``` --- # assets.md ```json { "projects": { "my-project": { "architect": { "build": { // ... "assets": [ { "glob": "**/*", "input": "node_modules/@taiga-ui/icons/src", "output": "assets/taiga-ui/icons" } ] } } } } } ``` --- # components-styles.md ```ts @Component({ //..., styleUrls: ['./my.component.scss', './my.component.less'], }) export class Example {} ``` --- # import-local-less.md ```less @import '@taiga-ui/core/styles/taiga-ui-local.less'; // other styles ``` --- # main-standalone.md ```ts import {provideAnimations} from '@angular/platform-browser/animations'; import {provideEventPlugins} from '@taiga-ui/event-plugins'; // ... bootstrapApplication(App, { providers: [ provideAnimations(), provideEventPlugins(), //... ], }).catch((err) => console.error(err)); ``` --- # main.md ```bash npm i @taiga-ui/{cdk,core,kit,icons} ``` --- # nx-add.md ```bash npm i taiga-ui nx g taiga-ui:ng-add ``` --- # nx-assets.md ```json { "targets": { "build": { "options": { // ... "assets": [ { "glob": "**/*", "input": "node_modules/@taiga-ui/icons/src", "output": "assets/taiga-ui/icons" } ] } } } } ``` --- # nx-migrate.md ```bash nx migrate @taiga-ui/cdk nx migrate --run-migrations=migrations.json ``` --- # ponyfill.md ```bash npm install css-vars-ponyfill ``` --- # project-json-styles.md ```json { "targets": { "build": { "options": { "styles": [ "@taiga-ui/core/styles/taiga-ui-theme.less", "@taiga-ui/core/styles/taiga-ui-fonts.less", "@taiga-ui/addon-mobile/styles/taiga-ui-mobile.less" // optional ] } } } } ``` --- # components/Accordion - **Package**: `EXPERIMENTAL` - **Type**: components ### How to Use (Import) ```ts import {TuiAccordion} from '@taiga-ui/experimental'; // ... @Component({ standalone: true, imports: [ // ... TuiAccordion, ], // ... }) export class Example {} ``` ### How to Use (Template) ```html Development kit consisting of the low level tools and abstractions used to develop Taiga UI Angular entities Basic elements needed to develop components, directives and more using Taiga UI design system The main set of components used to build Taiga UI based Angular applications ``` ### Example ```html Development kit consisting of the low level tools and abstractions used to develop Taiga UI Angular entities Basic elements needed to develop components, directives and more using Taiga UI design system ``` ### API | Property | Type | Description | |----------|-----|----------| | [closeOthers] | `boolean` | Other sections are closed when user opens one | | [size] | `TuiSizeS | TuiSizeL` | Size | | [(tuiAccordion)] | `boolean` | Individual item open state | ### Usage Examples #### Basic **Template:** ```html {{ item.value }} ``` **TypeScript:** ```ts import {KeyValuePipe, NgForOf} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAccordion} from '@taiga-ui/experimental'; @Component({ standalone: true, imports: [KeyValuePipe, NgForOf, TuiAccordion], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected readonly data = { 'Taiga UI cdk': 'Development kit consisting of the low level tools and abstractions used to develop Taiga UI Angular entities', 'Taiga UI core': 'Basic elements needed to develop components, directives and more using Taiga UI design system', 'Taiga UI kit': 'The main set of components used to build Taiga UI based Angular applications', }; } ``` #### Custom **Template:** ```html
{{ operation.title }} {{ operation.subtitle }} {{ operation.sum | tuiAmount: '$' : 'left' | async }} {{ operation.time }}
``` **TypeScript:** ```ts import {AsyncPipe, KeyValuePipe, NgForOf, NgIf} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAmountPipe} from '@taiga-ui/addon-commerce'; import {TuiButton, TuiTitle} from '@taiga-ui/core'; import {TuiAccordion} from '@taiga-ui/experimental'; import {TuiAvatar} from '@taiga-ui/kit'; import {TuiCell} from '@taiga-ui/layout'; interface Operation { title: string; subtitle?: string; sum?: number; time?: string; } @Component({ standalone: true, imports: [ AsyncPipe, KeyValuePipe, NgForOf, NgIf, TuiAccordion, TuiAmountPipe, TuiAvatar, TuiButton, TuiCell, TuiTitle, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly operations = { Today: [], Yesterday: [ { title: 'Cashback', subtitle: 'Pot of gold', sum: 237, time: '19:32', }, { title: 'Failed to load', }, ], 'January 6, 2021': [ { title: 'Salary', subtitle: 'Account number ••••237', sum: 43256, time: '11:02', }, { title: 'Shaman Hat', subtitle: 'Insurrection Apparel', sum: -99, time: '09:11', }, { title: 'Shaman Makeup', subtitle: 'Insurrection Apparel', sum: -75, time: '09:11', }, ], }; protected getIcon(operation: Operation): string { if (!operation.sum) { return '@tui.triangle-alert'; } return operation.sum > 0 ? '@tui.thumbs-up' : '@tui.thumbs-down'; } protected sum(operations: readonly Operation[]): number { return operations.reduce((acc, {sum}) => acc + (sum || 0), 0); } protected orderBy(): number { return 0; } } ``` #### Single **Template:** ```html Development kit consisting of the low level tools and abstractions used to develop Taiga UI Angular entities ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAccordion} from '@taiga-ui/experimental'; @Component({ standalone: true, imports: [TuiAccordion], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example {} ``` #### Eager and Lazy **Template:** ```html I'm lazy content I'm eager content ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAccordion} from '@taiga-ui/experimental'; @Component({ standalone: true, imports: [TuiAccordion], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example {} ``` #### Nested **Template:** ```html Development kit consisting of the low level tools and abstractions used to develop Taiga UI Angular entities The main set of components used to build Taiga UI based Angular applications Basic elements needed to develop components, directives and more using Taiga UI design system ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAccordion} from '@taiga-ui/experimental'; @Component({ standalone: true, imports: [TuiAccordion], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example {} ``` #### Connected **Template:** ```html {{ item.value.text }} ``` **TypeScript:** ```ts import {KeyValuePipe, NgForOf} from '@angular/common'; import {Component} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {tuiArrayToggle} from '@taiga-ui/cdk'; import {TuiTitle} from '@taiga-ui/core'; import {TuiAccordion} from '@taiga-ui/experimental'; import {TuiAvatar, TuiCheckbox, TuiConnected} from '@taiga-ui/kit'; import {TuiCell} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ FormsModule, KeyValuePipe, NgForOf, TuiAccordion, TuiAvatar, TuiCell, TuiCheckbox, TuiConnected, TuiTitle, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly steps = { 'First steps': { text: 'Getting to know your workplace', steps: ['Looks around', 'Talk to colleagues', 'Have lunch'], }, 'Work day': { text: 'Start working', steps: ['Open the project', 'Read the documentation', 'Start coding'], }, Mastery: { text: 'Become a pro', steps: ['Write tests', 'Refactor the code', 'Deploy the project'], }, }; protected selected = this.steps['First steps'].steps.concat( this.steps['Work day'].steps[0] || '', ); protected isChecked(steps: readonly string[]): boolean { return steps.every((step) => this.selected.includes(step)); } protected toggle(step: string): void { this.selected = tuiArrayToggle(this.selected, step); } protected orderBy(): number { return 0; } } ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; import {type TuiSizeL, type TuiSizeS} from '@taiga-ui/core'; import {TuiAccordion} from '@taiga-ui/experimental'; @Component({ standalone: true, imports: [TuiAccordion, TuiDemo], templateUrl: './index.html', changeDetection, }) export default class Page { protected readonly examples = [ 'Basic', 'Custom', 'Single', 'Eager and Lazy', 'Nested', 'Connected', ]; protected readonly sizeVariants: ReadonlyArray = ['s', 'm', 'l']; protected size = this.sizeVariants[2]!; protected closeOthers = true; protected open = false; } ``` --- # components/ActionBar - **Package**: `KIT` - **Type**: components It is an element on the bottom of screen to show actions by multiselect of some items. It works with custom content. ### How to Use (Import) ```ts import {TuiActionBar} from '@taiga-ui/kit'; // ... @Component({ standalone: true, imports: [ TuiActionBar, // ... ], // ... }) export class App {} ``` ### How to Use (Template) ```html content ``` ### Usage Examples #### Size M **Template:** ```html
Selected: {{ selected }} of {{ items.length }}
``` **TypeScript:** ```ts import {NgIf} from '@angular/common'; import {Component, inject} from '@angular/core'; import {toSignal} from '@angular/core/rxjs-interop'; import {FormControl, ReactiveFormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiRepeatTimes} from '@taiga-ui/cdk'; import { TuiBreakpointService, TuiButton, TuiDataList, TuiDropdown, TuiIcon, TuiLink, } from '@taiga-ui/core'; import {TuiActionBar, TuiFilter, TuiItemsWithMore} from '@taiga-ui/kit'; import {map} from 'rxjs'; @Component({ standalone: true, imports: [ NgIf, ReactiveFormsModule, TuiActionBar, TuiButton, TuiDataList, TuiDropdown, TuiFilter, TuiIcon, TuiItemsWithMore, TuiLink, TuiRepeatTimes, ], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected items = ['one', 'two', 'three', 'four']; protected control = new FormControl([]); protected expanded = false; protected readonly isMobile = toSignal( inject(TuiBreakpointService).pipe(map((size) => size === 'mobile')), ); protected get value(): string[] { return this.control.value || []; } protected get open(): boolean { return this.value.length > 0; } protected get selected(): number { return this.value.length; } protected toggleSelect(): void { this.control.setValue(this.selected < this.items.length ? this.items : []); } protected close(): void { this.control.setValue([]); this.expanded = false; } } ``` #### Size S **Template:** ```html Table bar opened ``` **TypeScript:** ```ts import {Component, inject, signal} from '@angular/core'; import {toSignal} from '@angular/core/rxjs-interop'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiBreakpointService, TuiButton} from '@taiga-ui/core'; import {TuiActionBar} from '@taiga-ui/kit'; import {map} from 'rxjs'; @Component({ standalone: true, imports: [TuiActionBar, TuiButton], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected open = signal(false); protected readonly isMobile = toSignal( inject(TuiBreakpointService).pipe(map((size) => size === 'mobile')), ); } ``` #### Top position **Template:** ```html Table bar on top opened ``` **TypeScript:** ```ts import {Component, inject, signal} from '@angular/core'; import {toSignal} from '@angular/core/rxjs-interop'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiBreakpointService, TuiButton} from '@taiga-ui/core'; import {TuiActionBar} from '@taiga-ui/kit'; import {map} from 'rxjs'; @Component({ standalone: true, imports: [TuiActionBar, TuiButton], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected open = signal(false); protected readonly isMobile = toSignal( inject(TuiBreakpointService).pipe(map((size) => size === 'mobile')), ); } ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; @Component({ standalone: true, imports: [TuiDemo], templateUrl: './index.html', styleUrls: ['./index.less'], changeDetection, }) export default class Page { protected readonly examples = ['Size M', 'Size S', 'Top position']; } ``` ### LESS ```less .label { inline-size: 6.25rem; } ``` --- # components/Alert - **Package**: `CORE` - **Type**: components Built-in implementation of notifications Position on screen can be configured by providing margins with TUI_ALERT_POSITION token. Default value is 2rem 3rem 0 auto . ### Example ```html ``` ### API | Property | Type | Description | |----------|-----|----------| | [content] | `PolymorpheusContent` | Content | | [appearance] | `string` | Appearance | | [label] | `string` | Heading | | [data] | `number` | | | [autoClose] | `TuiHandler | number` | Auto close timeout, 0 for no auto close | | [closeable] | `boolean` | Has close button | | [icon] | `PolymorpheusContent` | Icon | ### Usage Examples #### Text **Template:** ```html ``` **TypeScript:** ```ts import {Component, inject} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAlertService, TuiButton} from '@taiga-ui/core'; @Component({ standalone: true, imports: [TuiButton], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { private readonly alerts = inject(TuiAlertService); protected showNotification(): void { this.alerts .open('Basic HTML', {label: 'With a heading!'}) .subscribe(); } } ``` #### Template **Template:** ```html

Your balance: {{ money | tuiAmount: 'RUB' | async }}

Notifications can be shown with template

Your balance: {{ money | tuiAmount: 'RUB' | async }}

If there are many templates, you can use ViewChildren instead of ViewChild or set them IDs with "#" (see code of this sample)

Your balance: {{ money | tuiAmount: 'RUB' | async }}

``` **TypeScript:** ```ts import {AsyncPipe} from '@angular/common'; import {Component, inject, type TemplateRef, ViewChild} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAmountPipe} from '@taiga-ui/addon-commerce'; import {type TuiAlertContext, TuiAlertService, TuiButton} from '@taiga-ui/core'; import {PolymorpheusTemplate} from '@taiga-ui/polymorpheus'; @Component({ standalone: true, imports: [AsyncPipe, PolymorpheusTemplate, TuiAmountPipe, TuiButton], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { private readonly alerts = inject(TuiAlertService); @ViewChild('withdrawTemplate') protected withdrawTemplate?: TemplateRef; @ViewChild('depositTemplate') protected depositTemplate?: TemplateRef; protected money = 1000; protected showWithdrawAlert(): void { this.alerts .open(this.withdrawTemplate || '', { label: 'A template sample', appearance: 'warning', autoClose: 0, }) .subscribe(); } protected showDepositAlert(): void { this.alerts .open(this.depositTemplate || '', { label: 'A template sample', appearance: 'positive', autoClose: 0, }) .subscribe(); } protected withdraw(): void { this.money -= 100; } protected deposit(): void { this.money += 100; } } ``` #### Component **Template:** ```html

This notification will be removed after router change (see TypeScript tab)

``` **TypeScript:** ```ts import {NgForOf} from '@angular/common'; import {Component, inject} from '@angular/core'; import {Router} from '@angular/router'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {type TuiPopover} from '@taiga-ui/cdk'; import {type TuiAlertOptions, TuiAlertService, TuiButton} from '@taiga-ui/core'; import {injectContext, PolymorpheusComponent} from '@taiga-ui/polymorpheus'; import {switchMap, takeUntil} from 'rxjs'; @Component({ standalone: true, imports: [NgForOf, TuiButton], template: `

Yes?

`, changeDetection, }) export class AlertExample { protected readonly context = injectContext, boolean>>(); } @Component({ standalone: true, imports: [TuiButton], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { private readonly alerts = inject(TuiAlertService); private readonly notification = this.alerts .open(new PolymorpheusComponent(AlertExample), { label: 'Question', appearance: 'negative', autoClose: 0, }) .pipe( switchMap((response) => this.alerts.open(`Got a value — ${response}`, {label: 'Information'}), ), takeUntil(inject(Router).events), ); protected showNotification(): void { this.notification.subscribe(); } } ``` #### Component with data **Template:** ```html ``` **TypeScript:** ```ts import {AsyncPipe} from '@angular/common'; import {Component, inject} from '@angular/core'; import {Router} from '@angular/router'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAmountPipe} from '@taiga-ui/addon-commerce'; import {type TuiPopover} from '@taiga-ui/cdk'; import {type TuiAlertOptions, TuiAlertService, TuiButton, TuiLink} from '@taiga-ui/core'; import {injectContext, PolymorpheusComponent} from '@taiga-ui/polymorpheus'; import {switchMap, takeUntil} from 'rxjs'; @Component({ standalone: true, imports: [AsyncPipe, TuiAmountPipe, TuiButton, TuiLink], template: ` Your balance: {{ value | tuiAmount: 'RUB' | async }}
`, changeDetection, }) export class AlertExampleWithData { protected readonly context = injectContext, number>>(); protected value = this.context.data; protected increaseBalance(): void { this.value += 10; } } @Component({ standalone: true, imports: [TuiButton], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { private readonly alerts = inject(TuiAlertService); private readonly notification = this.alerts .open(new PolymorpheusComponent(AlertExampleWithData), { label: 'Heading is so long that it should be shown in two lines of text', data: 237, appearance: 'warning', autoClose: 0, }) .pipe( switchMap((response) => this.alerts.open(`Got a value — ${response}`, {label: 'Information'}), ), takeUntil(inject(Router).events), ); protected showNotification(): void { this.notification.subscribe(); } } ``` #### Component with custom label **Template:** ```html

``` **TypeScript:** ```ts import {Component, inject} from '@angular/core'; import {Router} from '@angular/router'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {type TuiPopover} from '@taiga-ui/cdk'; import {type TuiAlertOptions, TuiAlertService, TuiButton, TuiIcon} from '@taiga-ui/core'; import { injectContext, PolymorpheusComponent, PolymorpheusOutlet, PolymorpheusTemplate, } from '@taiga-ui/polymorpheus'; import {takeUntil} from 'rxjs'; @Component({ standalone: true, imports: [TuiIcon], template: ` `, changeDetection, }) class CustomLabel {} @Component({ standalone: true, imports: [PolymorpheusOutlet, PolymorpheusTemplate], template: `

Start content

{{ text }}

End content

`, changeDetection, }) class AlertExampleWithCustomLabel { protected readonly context = injectContext, boolean>>(); } @Component({ standalone: true, selector: 'tui-alerts-example-5', imports: [TuiButton], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { private readonly router = inject(Router); private readonly alerts = inject(TuiAlertService); private readonly notification = this.alerts .open(new PolymorpheusComponent(AlertExampleWithCustomLabel), { label: ({appearance}) => appearance === 'negative' ? 'Error label from function' : 'Info label from function', appearance: 'negative', autoClose: 0, }) .pipe(takeUntil(this.router.events)); private readonly notificationWithCustomLabel = this.alerts .open(new PolymorpheusComponent(AlertExampleWithCustomLabel), { label: new PolymorpheusComponent(CustomLabel), appearance: 'warning', autoClose: 0, }) .pipe(takeUntil(this.router.events)); protected showNotification(): void { this.notification.subscribe(); } protected showNotificationWithCustomLabel(): void { this.notificationWithCustomLabel.subscribe(); } } ``` #### Directive **Template:** ```html This is a declarative directive alert ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAlert, TuiButton} from '@taiga-ui/core'; @Component({ standalone: true, selector: 'tui-alerts-example-6', imports: [TuiAlert, TuiButton], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected show = false; } ``` #### Concurrency limit **Template:** ```html ``` **TypeScript:** ```ts import {Component, inject} from '@angular/core'; import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAlertService, TuiButton} from '@taiga-ui/core'; import {mergeAll, type Observable, Subject} from 'rxjs'; const MAX_CONCURRENT = 3; @Component({ standalone: true, imports: [TuiButton], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { private readonly alerts = inject(TuiAlertService); private readonly queue$ = new Subject>(); private i = 0; constructor() { this.queue$.pipe(mergeAll(MAX_CONCURRENT), takeUntilDestroyed()).subscribe(); } protected showNotification(): void { this.queue$.next( this.alerts.open( `It is impossible to show more than ${MAX_CONCURRENT} alerts concurrently!
` + `Index: ${this.i++}`, {label: 'Use power of RxJS!'}, ), ); } } ``` ### TypeScript ```ts import {Component, inject, INJECTOR} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {DemoRoute} from '@demo/routes'; import {TuiDemo} from '@demo/utils'; import {type TuiPopoverContext} from '@taiga-ui/cdk'; import { TUI_NOTIFICATION_OPTIONS, type TuiAlertOptions, TuiAlertService, TuiButton, } from '@taiga-ui/core'; import {PolymorpheusComponent, type PolymorpheusContent} from '@taiga-ui/polymorpheus'; import {switchMap} from 'rxjs'; import {AlertExampleWithData} from './examples/4'; @Component({ standalone: true, imports: [TuiButton, TuiDemo], templateUrl: './index.html', changeDetection, }) export default class Page { private readonly alerts = inject(TuiAlertService); private readonly defaultIcon = inject(TUI_NOTIFICATION_OPTIONS).icon; protected readonly routes = DemoRoute; protected readonly examples = [ 'Text', 'Template', 'Component', 'Component with data', 'Component with custom label', 'Directive', 'Concurrency limit', ]; protected readonly method = import('./examples/import/method.md?raw'); protected readonly exampleServiceUsage = import( './examples/import/service-usage.md?raw' ); protected readonly exampleServiceUsageComponent = import( './examples/import/service-usage-component.md?raw' ); protected readonly exampleCustomAlert = import( './examples/import/custom-alert.md?raw' ); protected readonly exampleLazyModule = import('./examples/import/lazy-module.md?raw'); protected readonly exampleOptions = import('./examples/import/define-options.md?raw'); protected data = 100; protected label = 'Heading'; protected readonly appearanceVariants = [ 'info', 'positive', 'negative', 'warning', 'neutral', ]; protected appearance = this.appearanceVariants[0]!; protected readonly iconVariants = ['Default', '@tui.heart']; protected icon = this.iconVariants[0]!; protected readonly contentVariants = ['String', 'Component']; protected content = this.contentVariants[0]!; protected readonly autoCloseVariants = [0, 3000, 5000, 1000, 500]; protected autoClose = this.autoCloseVariants[1]!; protected closeable = true; protected readonly component = new PolymorpheusComponent( AlertExampleWithData, inject(INJECTOR), ); protected get selectedContent(): PolymorpheusContent< TuiAlertOptions & TuiPopoverContext > { return this.content === 'String' ? this.content : this.component; } protected showNotification(): void { this.alerts .open(this.selectedContent, { label: this.label, data: this.data, appearance: this.appearance, autoClose: this.autoClose, closeable: this.closeable, icon: this.icon === this.iconVariants[0] ? this.defaultIcon : this.icon, }) .pipe( switchMap((response) => this.alerts.open(response, { label: 'Notification responded with:', }), ), ) .subscribe(); } } ``` --- # components/AppBar - **Package**: `LAYOUT` - **Type**: components Component for the main app header ### How to Use (Import) ```ts import {TuiAppBar} from '@taiga-ui/layout'; // ... @Component({ standalone: true, imports: [ // ... TuiAppBar, ], // ... }) export class Example {} ``` ### How to Use (Template) ```html
Page title
``` ### Usage Examples #### Mobile — medium size **Template:** ```html

iOS

Taiga UI Taiga UI — Components library Taiga UI

Android

Taiga UI Taiga UI — Components library Taiga UI
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiPlatform} from '@taiga-ui/cdk'; import {TuiButton, TuiTitle} from '@taiga-ui/core'; import {TuiAppBar} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [TuiAppBar, TuiButton, TuiPlatform, TuiTitle], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Desktop — large size **Template:** ```html Taiga UI ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiButton, TuiTitle} from '@taiga-ui/core'; import {TuiProgress} from '@taiga-ui/kit'; import {TuiAppBar} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [TuiAppBar, TuiButton, TuiProgress, TuiTitle], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Variants **Template:** ```html

Customization

Taiga UI

Centered Android

``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiPlatform} from '@taiga-ui/cdk'; import {TuiButton, TuiTitle} from '@taiga-ui/core'; import {TuiFade, TuiProgress} from '@taiga-ui/kit'; import {TuiAppBar} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [TuiAppBar, TuiButton, TuiFade, TuiPlatform, TuiProgress, TuiTitle], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Dialog **Template:** ```html

I'm a stepper

Step {{ step }}

``` **TypeScript:** ```ts import {Component, inject, type TemplateRef} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAppearance, TuiButton, TuiDialogService, TuiTitle} from '@taiga-ui/core'; import {TuiProgress} from '@taiga-ui/kit'; import {TuiAppBar, TuiCardLarge, TuiHeader} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ TuiAppBar, TuiAppearance, TuiButton, TuiCardLarge, TuiHeader, TuiProgress, TuiTitle, ], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { private readonly dialogs = inject(TuiDialogService); protected step = 0; protected open(template: TemplateRef): void { this.step = 0; this.dialogs .open(template, { label: '', size: 'fullscreen', closeable: false, dismissible: false, }) .subscribe(); } } ``` #### Dynamic header **Template:** ```html
Title 1
Subtitle
Title
Description
Title 2
Title
Description
Title 3 Long title
Title
Description
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiPlatform, TuiRepeatTimes} from '@taiga-ui/cdk'; import {TuiTitle} from '@taiga-ui/core'; import {TuiAvatar, TuiSegmented} from '@taiga-ui/kit'; import {TuiAppBar, TuiCell, TuiDynamicHeader, TuiHeader} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ TuiAppBar, TuiAvatar, TuiCell, TuiDynamicHeader, TuiHeader, TuiPlatform, TuiRepeatTimes, TuiSegmented, TuiTitle, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected activeItemIndex = 0; } ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; @Component({ standalone: true, imports: [TuiDemo], templateUrl: './index.html', changeDetection, }) export default class Page { protected readonly examples = [ 'Mobile — medium size', 'Desktop — large size', 'Variants', 'Dialog', 'Dynamic header', ]; } ``` --- # components/ArcChart - **Package**: `ADDON-CHARTS` - **Type**: components ### How to Use (Import) ```ts import {TuiArcChart} from '@taiga-ui/addon-charts'; // ... @Component({ standalone: true, imports: [ // ... TuiArcChart, ], // ... }) export class Example {} ``` ### How to Use (Template) ```html ``` ### Example ```html ``` ### API | Property | Type | Description | |----------|-----|----------| | [max] | `number` | Maximum value | | [maxLabel] | `string` | Label for maximum value | | [minLabel] | `string` | Label for minimum value | | [size] | `TuiSizeXL` | Size | | [value] | `readonly number[]` | Value | | [(activeItemIndex)] | `number` | Index of selected arc | ### Usage Examples #### Sizes **Template:** ```html
Total value Total value
Label
{{ 123456 | tuiAmount: 'RUB' | async }}
Not bad!
``` **TypeScript:** ```ts import {AsyncPipe} from '@angular/common'; import {Component} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiArcChart} from '@taiga-ui/addon-charts'; import {TuiAmountPipe} from '@taiga-ui/addon-commerce'; import {TuiNumberFormat, TuiTextfield} from '@taiga-ui/core'; import {TuiInputNumber} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [ AsyncPipe, FormsModule, TuiAmountPipe, TuiArcChart, TuiInputNumber, TuiNumberFormat, TuiTextfield, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly value = [40, 30, 20, 10]; protected activeItemIndex = NaN; public onTextfieldChange(value: number | null): void { this.activeItemIndex = value ?? NaN; } } ``` #### Stacked **Template:** ```html
+20%
For filling in last name
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiArcChart} from '@taiga-ui/addon-charts'; import {tuiSum} from '@taiga-ui/cdk'; @Component({ standalone: true, imports: [TuiArcChart], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly value = [13769, 12367, 10172, 3018, 2592]; protected readonly sum = tuiSum(...this.value); } ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; import {TuiArcChart} from '@taiga-ui/addon-charts'; import {type TuiSizeXL} from '@taiga-ui/core'; @Component({ standalone: true, imports: [TuiArcChart, TuiDemo], templateUrl: './index.html', styleUrls: ['./index.less'], changeDetection, }) export default class Page { protected readonly examples = ['Sizes', 'Stacked']; protected readonly valueVariants = [ [42], [40, 30, 20, 10], [13769, 10172, 3018, 2592], ]; protected value = this.valueVariants[0]!; protected readonly maxVariants = [100, 10000, 50000]; protected max = this.maxVariants[0]!; protected readonly sizeVariants: readonly TuiSizeXL[] = ['m', 'l', 'xl']; protected size = this.sizeVariants[0]!; protected minLabel = '0%'; protected maxLabel = '100%'; protected activeItemIndex = NaN; } ``` ### LESS ```less .chart { margin: 0 auto; } ``` --- # components/Avatar - **Package**: `KIT` - **Type**: components ### How to Use (Import) ```ts import {Component} from '@angular/core'; import {TuiAvatar} from '@taiga-ui/kit'; // ... @Component({ standalone: true, imports: [ // ... TuiAvatar, ], }) export class Example {} ``` ### How to Use (Template) ```html Batman ``` ### Example ```html ``` ### API | Property | Type | Description | |----------|-----|----------| | round | `boolean` | Use round shape | | size | `TuiSizeS | TuiSizeL` | Size | | src | `SafeResourceUrl | string | null` | which would be styled differently from initials and fade if overflown | ### Usage Examples #### Content types **Template:** ```html

Icon Starts with @tui.

Colored icon Use tuiIcon pipe to resolve name

Image

Initials

Content

99+ Alex Inkin
``` **TypeScript:** ```ts import {AsyncPipe} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiFallbackSrcPipe, TuiIconPipe, TuiTitle} from '@taiga-ui/core'; import {TuiAvatar} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [AsyncPipe, TuiAvatar, TuiFallbackSrcPipe, TuiIconPipe, TuiTitle], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Colors **Template:** ```html
Fading
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAutoColorPipe} from '@taiga-ui/core'; import {TuiAvatar, TuiFade} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiAutoColorPipe, TuiAvatar, TuiFade], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Sizes **Template:** ```html
{{ size | uppercase }}
``` **TypeScript:** ```ts import {NgForOf, UpperCasePipe} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAvatar} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [NgForOf, TuiAvatar, UpperCasePipe], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly sizes = ['xxl', 'xl', 'l', 'm', 's', 'xs'] as const; protected readonly names = ['Jason Statham', 'Silvester Stallone', 'Jackie Chan']; } ``` #### Stacking **Template:** ```html 99+ ``` **TypeScript:** ```ts import {NgForOf} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import { TuiAutoColorPipe, TuiInitialsPipe, type TuiSizeXS, type TuiSizeXXL, } from '@taiga-ui/core'; import {TuiAvatar, TuiAvatarStack} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [NgForOf, TuiAutoColorPipe, TuiAvatar, TuiAvatarStack, TuiInitialsPipe], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected readonly names = ['Jason Statham', 'Silvester Stallone', 'Jackie Chan']; protected readonly sizes: ReadonlyArray = [ 'xxl', 'xl', 'l', 'm', 's', 'xs', ]; } ``` #### Options with DI **Template:** ```html ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAvatar, tuiAvatarOptionsProvider} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiAvatar], templateUrl: './index.html', encapsulation, changeDetection, providers: [tuiAvatarOptionsProvider({size: 'l'})], }) export default class Example {} ``` #### Labeled **Template:** ```html ``` **TypeScript:** ```ts import {AsyncPipe} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiFallbackSrcPipe} from '@taiga-ui/core'; import {TuiAvatar, TuiAvatarLabeled} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [AsyncPipe, TuiAvatar, TuiAvatarLabeled, TuiFallbackSrcPipe], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Outline **Template:** ```html Alex Inkin ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAvatar, TuiAvatarOutline} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiAvatar, TuiAvatarOutline], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` ### TypeScript ```ts import {Component, inject} from '@angular/core'; import {DomSanitizer, type SafeResourceUrl} from '@angular/platform-browser'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; import {type TuiSizeXS, type TuiSizeXXL} from '@taiga-ui/core'; import {TuiAvatar} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiAvatar, TuiDemo], templateUrl: './index.html', changeDetection, }) export default class Page { private readonly sanitizer = inject(DomSanitizer); protected readonly examples = [ 'Content types', 'Colors', 'Sizes', 'Stacking', 'Options with DI', 'Labeled', 'Outline', ]; protected readonly sizes: ReadonlyArray = [ 'xs', 's', 'm', 'l', 'xl', 'xxl', ]; protected size = this.sizes[3]!; protected readonly srcVariants: ReadonlyArray = [ 'MW', 'https://avatars.githubusercontent.com/u/11832552', 'https://taiga-ui.dev/assets/images/test-not-found.png', '@tui.user', this.sanitizer.bypassSecurityTrustResourceUrl( 'https://avatars.githubusercontent.com/u/10106368', ), ]; protected src = this.srcVariants[0]!; protected round = true; } ``` --- # components/Axes - **Package**: `ADDON-CHARTS` - **Type**: components Just axes for charts ### How to Use (Import) ```ts import {TuiAxes} from '@taiga-ui/addon-charts'; // ... @Component({ standalone: true, imports: [ // ... TuiAxes, ], // ... }) export class Example {} ``` ### How to Use (Template) ```html ``` ### Example ```html ``` ### API | Property | Type | Description | |----------|-----|----------| | [axisX] | `TuiLineType` | Axis X | | [axisXLabels] | `ReadonlyArray` | — no stroke | | [axisY] | `TuiLineType` | Axis Y | | [axisYInset] | `boolean` | Inset of labels on axis Y | | [axisYLabels] | `readonly string[]` | Labels for Y | | [axisYName] | `string` | Name of Y axis | | [axisYSecondaryInset] | `boolean` | Inset labels for Y | | [axisYSecondaryLabels] | `readonly string[]` | Secondary Y axis labels | | [axisYSecondaryName] | `string` | Secondary Y axis name | | [horizontalLines] | `number` | Horizontal lines number | | [horizontalLinesHandler] | `TuiLineHandler` | Horizontal lines type handler | | [verticalLines] | `number` | Number of vertical lines | | [verticalLinesHandle] | `TuiLineHandler` | Vertical lines type handler | ### Usage Examples #### Cool one **Template:** ```html ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAxes, type TuiLineHandler} from '@taiga-ui/addon-charts'; @Component({ standalone: true, imports: [TuiAxes], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly axisXLabels = ['Jan 2019', 'Feb', 'Mar', '']; protected readonly axisYLabels = ['', '25%', '50%', '75%', '100%']; protected readonly axisYSecondaryLabels = ['80 k', '100 k', '120 k']; protected readonly verticalLinesHandler: TuiLineHandler = (index, total) => index === total - 1 ? 'none' : 'dashed'; } ``` #### With bars **Template:** ```html

{{ getSetName(index) }} {{ (item[setIndex] || 0) * 1000 | tuiAmount: 'RUB' | async }}

``` **TypeScript:** ```ts import {AsyncPipe, NgForOf} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import { TUI_ALWAYS_DASHED, TUI_ALWAYS_NONE, TuiAxes, TuiBarChart, } from '@taiga-ui/addon-charts'; import {TuiAmountPipe} from '@taiga-ui/addon-commerce'; import {tuiCeil, tuiPure} from '@taiga-ui/cdk'; import {TuiHint} from '@taiga-ui/core'; const BENJI = 100; @Component({ standalone: true, imports: [AsyncPipe, NgForOf, TuiAmountPipe, TuiAxes, TuiBarChart, TuiHint], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { private readonly setNames = ['cdk', 'core', 'kit', 'charts']; protected readonly value: ReadonlyArray<[number, number, number, number]> = [ [10, 20, 3, 7], [15, 18, 24, 1], [34, 23, 12, 9], [30, 14, 18, 14], ]; protected readonly maxValue = 40; protected readonly axisYSecondaryLabels = [ '', `${this.getMax(this.value) / 2} k`, `${this.getMax(this.value)} k`, ]; protected readonly axisXLabels = ['Q1', 'Q2', 'Q3', 'Q4']; protected readonly horizontalLinesHandler = TUI_ALWAYS_DASHED; protected readonly verticalLinesHandler = TUI_ALWAYS_NONE; protected getPercent(set: [number, number, number, number]): number { return (BENJI * Math.max(...set)) / this.getMax(this.value); } protected getSetName(index: number): string { return this.setNames[index] ?? ''; } @tuiPure private getMax(value: ReadonlyArray<[number, number, number, number]>): number { return tuiCeil( value.reduce((max, value) => Math.max(...value, max), 0), -1, ); } } ``` #### With horizontal bars **Template:** ```html
``` **TypeScript:** ```ts import {NgForOf} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAxes, TuiBar} from '@taiga-ui/addon-charts'; @Component({ standalone: true, imports: [NgForOf, TuiAxes, TuiBar], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly axisXLabels = ['0', '25', '50', '75', '100']; protected readonly value = [50, 24, 36, 95]; protected readonly largest = 100; protected getHeight(value: number): number { return Math.abs((value * 100) / this.largest); } } ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; import { TUI_ALWAYS_DASHED, TUI_ALWAYS_SOLID, TuiAxes, type TuiLineHandler, type TuiLineType, } from '@taiga-ui/addon-charts'; @Component({ standalone: true, imports: [TuiAxes, TuiDemo], templateUrl: './index.html', styleUrls: ['./index.less'], changeDetection, }) export default class Page { protected readonly examples = ['Cool one', 'With bars', 'With horizontal bars']; protected readonly lineVariants: readonly TuiLineType[] = [ 'solid', 'dashed', 'none', 'hidden', ]; protected readonly labelsXVariants: ReadonlyArray> = [ [], ['', '25%', '50%', '100%', ''], ['One', 'Two', 'Three', ''], ['One', null, '', 'Two and a half', 'Three', null, ''], ]; protected readonly labelsYVariants: ReadonlyArray = [ [], ['', '25%', '50%', '100%'], ['One', 'Two', 'Three'], ['One', '', 'Two and a half', 'Three'], ]; protected readonly handlerVariants: readonly TuiLineHandler[] = [ TUI_ALWAYS_SOLID, TUI_ALWAYS_DASHED, (index) => (index % 2 ? 'dashed' : 'solid'), ]; protected axisX = this.lineVariants[0]!; protected axisXLabels = this.labelsXVariants[0]!; protected axisY = this.lineVariants[0]!; protected axisYInset = false; protected axisYLabels = this.labelsYVariants[0]!; protected axisYName = ''; protected axisYSecondaryInset = false; protected axisYSecondaryLabels = this.labelsYVariants[0]!; protected axisYSecondaryName = ''; protected horizontalLines = 0; protected horizontalLinesHandler = this.handlerVariants[0]!; protected verticalLines = 0; protected verticalLinesHandler = this.handlerVariants[1]!; } ``` ### LESS ```less .axes { block-size: 12.5rem; } ``` --- # components/Badge - **Package**: `KIT` - **Type**: components Component for displaying text, pictures and icons. ### How to Use (Import) ```ts import {Component} from '@angular/core'; import {TuiBadge} from '@taiga-ui/kit'; // ... @Component({ standalone: true, imports: [ // ... TuiBadge, ], }) export class Example {} ``` ### How to Use (Template) ```html {{ value }} ``` ### Example ```html

Taiga UI
Taiga UI market

``` ### API | Property | Type | Description | |----------|-----|----------| | [size] | `TuiSizeL` | Size | | [appearance] | `TuiStatus` | Appearance | ### Usage Examples #### Basic **Template:** ```html Default Primary Accent Success Error Warning Warning Neutral Info

Custom status

Custom

Use CSS for support colors

Taiga

Sizes

Success Success Success Success ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiRepeatTimes} from '@taiga-ui/cdk'; import {TuiBadge, TuiStatus} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiBadge, TuiRepeatTimes, TuiStatus], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Sizes **Template:** ```html x-large large medium small ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiBadge} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiBadge], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example {} ``` #### Content type (mobile platform) **Template:** ```html

Value with icon

x-large large medium small

Icon only

Image

market market market market
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiPlatform} from '@taiga-ui/cdk'; import {TuiIcon} from '@taiga-ui/core'; import {TuiBadge} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiBadge, TuiIcon, TuiPlatform], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Long value **Template:** ```html
Very long value in badge
Very long value in badge
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiBadge, TuiFade} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiBadge, TuiFade], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Customization **Template:** ```html 10 000 000 $ Taiga ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiBadge} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiBadge], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Options with DI **Template:** ```html 10 000 000 $ ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiBadge, tuiBadgeOptionsProvider} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiBadge], templateUrl: './index.html', encapsulation, changeDetection, providers: [tuiBadgeOptionsProvider({appearance: 'primary'})], }) export default class Example {} ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; import {type TuiSizeS, type TuiSizeXL} from '@taiga-ui/core'; import {TuiBadge, TuiFade, TuiRadioList} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [FormsModule, TuiBadge, TuiDemo, TuiFade, TuiRadioList], templateUrl: './index.html', changeDetection, }) export default class Page { protected readonly appearanceVariants = [ '', 'accent', 'primary', 'custom', 'positive', 'negative', 'warning', 'info', 'neutral', ]; protected appearance = this.appearanceVariants[0]!; protected readonly sizeVariants: ReadonlyArray = [ 's', 'm', 'l', 'xl', ]; protected size: TuiSizeS | TuiSizeXL = this.sizeVariants[1]!; protected contentTypeVariants = ['text', 'with icon', 'image']; protected contentType = this.contentTypeVariants[0]!; } ``` --- # components/BadgeNotification - **Package**: `KIT` - **Type**: components Simple non-interactive badge. Used in headers, cells, cards, avatars to indicate notifications, such as new messages ### How to Use (Import) ```ts import {Component} from '@angular/core'; import {TuiBadgeNotification} from '@taiga-ui/kit'; // ... @Component({ standalone: true, imports: [ // ... TuiBadgeNotification, ], }) export class Example {} ``` ### How to Use (Template) ```html 10 ``` ### Example ```html 11 ``` ### API | Property | Type | Description | |----------|-----|----------| | [size] | `TuiSizeL` | Size | ### Usage Examples #### Basic **Template:** ```html

Desktop

9 9 9 9

Android

9 9 9 9

IOS

9 9 9 9

``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiPlatform} from '@taiga-ui/cdk'; import {TuiBadgeNotification} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiBadgeNotification, TuiPlatform], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Custom color **Template:** ```html 10 11 12 ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiBadgeNotification} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiBadgeNotification], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; import {TuiLabel, type TuiSizeL, type TuiSizeXS} from '@taiga-ui/core'; import {TuiBadgeNotification} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiBadgeNotification, TuiDemo, TuiLabel], templateUrl: './index.html', changeDetection, }) export default class Example { protected readonly sizeVariants: ReadonlyArray = [ 'l', 'm', 's', 'xs', ]; protected size: TuiSizeL | TuiSizeXS = this.sizeVariants[0]!; } ``` --- # components/BadgedContent - **Package**: `KIT` - **Type**: components BadgedContent is a wrapper for other components to add badges and notifications to them. ### How to Use (Import) ```ts import {Component} from '@angular/core'; import {TuiBadgedContent} from '@taiga-ui/kit'; // ... @Component({ standalone: true, imports: [ // ... TuiBadgedContent, ], }) export class Example {} ``` ### How to Use (Template) ```html 1 1 ``` ### Example ```html 1 ``` ### API | Property | Type | Description | |----------|-----|----------| | style.--t-radius | `string` | Border radius | ### Usage Examples #### Basic **Template:** ```html 99 120 99 ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiIcon} from '@taiga-ui/core'; import {TuiAvatar, TuiBadge, TuiBadgedContent, TuiBadgeNotification} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiAvatar, TuiBadge, TuiBadgedContent, TuiBadgeNotification, TuiIcon], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Rounded content **Template:** ```html 8 Taiga 99 ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiIcon} from '@taiga-ui/core'; import {TuiAvatar, TuiBadge, TuiBadgedContent, TuiBadgeNotification} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiAvatar, TuiBadge, TuiBadgedContent, TuiBadgeNotification, TuiIcon], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### With different components **Template:** ```html Input text ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiButton, TuiIcon} from '@taiga-ui/core'; import {TuiBadge, TuiBadgedContent, TuiBadgeNotification} from '@taiga-ui/kit'; import {TuiInputModule} from '@taiga-ui/legacy'; @Component({ standalone: true, imports: [ TuiBadge, TuiBadgedContent, TuiBadgeNotification, TuiButton, TuiIcon, TuiInputModule, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### With image **Template:** ```html icon icon ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAvatar, TuiBadgedContent} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiAvatar, TuiBadgedContent], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` ### TypeScript ```ts import {AsyncPipe} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; import {TuiFallbackSrcPipe} from '@taiga-ui/core'; import {TuiAvatar, TuiBadgedContent, TuiBadgeNotification} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [ AsyncPipe, TuiAvatar, TuiBadgedContent, TuiBadgeNotification, TuiDemo, TuiFallbackSrcPipe, ], templateUrl: './index.html', changeDetection, }) export default class Example { protected radiusVariants = ['0.75rem', '50%']; protected radius = this.radiusVariants[0]!; protected readonly examples = [ 'Basic', 'Rounded content', 'With different components', 'With image', ]; } ``` --- # components/Bar - **Package**: `ADDON-CHARTS` - **Type**: components A bar for bar chart ### How to Use (Import) ```ts import {TuiBar} from '@taiga-ui/addon-charts'; // ... @Component({ standalone: true, imports: [ // ... TuiBar, ], // ... }) export class Example {} ``` ### How to Use (Template) ```html ``` ### Example ```html ``` ### API | Property | Type | Description | |----------|-----|----------| | [size] | `TuiSizeS | TuiSizeL` | Size | | [value] | `readonly number[]` | An array of segments | ### Usage Examples #### Basic **Template:** ```html ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiBar} from '@taiga-ui/addon-charts'; @Component({ standalone: true, imports: [TuiBar], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Segments **Template:** ```html ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiBar} from '@taiga-ui/addon-charts'; @Component({ standalone: true, imports: [TuiBar], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly value = [30, 15, 10]; } ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; import {TuiBar} from '@taiga-ui/addon-charts'; import {type TuiSizeL, type TuiSizeS} from '@taiga-ui/core'; @Component({ standalone: true, imports: [TuiBar, TuiDemo], templateUrl: './index.html', styleUrls: ['./index.less'], changeDetection, }) export default class Page { protected readonly examples = ['Basic', 'Segments']; protected readonly sizeVariants: ReadonlyArray = ['s', 'm', 'l']; protected size = this.sizeVariants[1]!; protected readonly valueVariants = [ [30, 20, 10], [237, 50, 10, 5, 1], ]; protected value = this.valueVariants[0]!; } ``` ### LESS ```less .bar { block-size: 6.25rem; } ``` --- # components/BarChart - **Package**: `ADDON-CHARTS` - **Type**: components Bar chart that can be used as a content to axes . ### How to Use (Import) ```ts import {TuiBarChart} from '@taiga-ui/addon-charts'; //... @Component({ standalone: true, imports: [ // ... TuiBarChart, ], //... }) export class Example {} ``` ### How to Use (Template) ```html ``` ### Example ```html ``` ### API | Property | Type | Description | |----------|-----|----------| | [collapsed] | `boolean` | Shows data set in a single bar | | [max] | `number` | Sets chart max manually | | [size] | `TuiSizeS | TuiSizeL | null` | for autosize) | | [value] | `ReadonlyArray` | Array of segments | | (tapColumn) | `number` | Bar column click/enter event | ### Usage Examples #### With axes **Template:** ```html ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAxes, TuiBarChart} from '@taiga-ui/addon-charts'; import {tuiCeil} from '@taiga-ui/cdk'; @Component({ standalone: true, imports: [TuiAxes, TuiBarChart], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly value = [ [3660, 8281, 1069, 9034, 5797, 6918, 8495, 3234, 6204, 1392, 2088, 8637, 8779], [3952, 3671, 3781, 5323, 3537, 4107, 2962, 3320, 8632, 4755, 9130, 1195, 3574], ]; protected readonly labelsX = ['Jan 2019', 'Feb', 'Mar', '']; protected readonly labelsY = ['0', '10 000']; protected getHeight(max: number): number { return (max / tuiCeil(max, -3)) * 100; } } ``` #### Same values with collapsed mode **Template:** ```html
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAxes, TuiBarChart} from '@taiga-ui/addon-charts'; import {type TuiContext} from '@taiga-ui/cdk'; import {tuiFormatNumber, TuiHint, TuiTextfield} from '@taiga-ui/core'; import {TuiChevron, TuiDataListWrapper, TuiSelect} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [ FormsModule, TuiAxes, TuiBarChart, TuiChevron, TuiDataListWrapper, TuiHint, TuiSelect, TuiTextfield, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly value = [ [1000, 8000, 4000, 3000, 4000], [6000, 2000, 4500, 7000, 5000], ]; protected readonly labelsX = ['Jan 2021', 'Feb', 'Mar', '']; protected readonly labelsY = ['0', '10 000']; protected readonly appearances = ['dark', 'error']; protected appearance = this.appearances[0]!; protected readonly hint = ({$implicit}: TuiContext): string => this.value .reduce( (result, set) => `${result}$${tuiFormatNumber(set[$implicit] ?? 0)}\n`, '', ) .trim(); } ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {DemoRoute} from '@demo/routes'; import {TuiDemo} from '@demo/utils'; import {TuiBarChart} from '@taiga-ui/addon-charts'; import {type TuiSizeL, type TuiSizeS} from '@taiga-ui/core'; @Component({ standalone: true, imports: [TuiBarChart, TuiDemo], templateUrl: './index.html', styleUrls: ['./index.less'], changeDetection, }) export default class Page { protected collapsed = false; protected readonly sizeVariants: ReadonlyArray = ['s', 'm', 'l']; protected size: TuiSizeL | TuiSizeS | null = null; protected max = 0; protected readonly valueVariants = [ [ [30000, 20500, 12345], [12422, 16124, 22424], ], [ [30, 65, 30, 80, 54], [98, 48, 33, 25, 11], [55, 10, 27, 36, 73], ], ]; protected value = this.valueVariants[0]!; protected readonly routes = DemoRoute; } ``` ### LESS ```less .chart { block-size: 12.5rem; } ``` --- # components/BarSet - **Package**: `ADDON-CHARTS` - **Type**: components A group of bars for bar chart ### How to Use (Import) ```ts import {TuiBarSet} from '@taiga-ui/addon-charts'; // ... @Component({ standalone: true, imports: [ // ... TuiBarSet, ], }) // ... export class Example {} ``` ### How to Use (Template) ```html
``` ### Example ```html ``` ### API | Property | Type | Description | |----------|-----|----------| | [collapsed] | `boolean` | Shows data set in a single bar | | [size] | `TuiSizeS | TuiSizeL | null` | for autosize) | | [value] | `readonly number[]` | Array of segments | ### Usage Examples #### Dynamic size **Template:** ```html ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiBarSet} from '@taiga-ui/addon-charts'; @Component({ standalone: true, imports: [TuiBarSet], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly value = [30, 15, 10]; } ``` #### Fixed size **Template:** ```html ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiBarSet} from '@taiga-ui/addon-charts'; @Component({ standalone: true, imports: [TuiBarSet], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly value = [30, 15, 10]; } ``` #### With negative values **Template:** ```html ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiBarSet} from '@taiga-ui/addon-charts'; @Component({ standalone: true, imports: [TuiBarSet], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly value = [30, -15]; } ``` #### Horizontal **Template:** ```html
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiBarSet} from '@taiga-ui/addon-charts'; @Component({ standalone: true, imports: [TuiBarSet], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly value = [30, 45, 12, 6, 20]; } ``` #### With value label **Template:** ```html {{ sum | tuiFormatNumber | async }} ``` **TypeScript:** ```ts import {AsyncPipe} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiBarSet} from '@taiga-ui/addon-charts'; import {TuiFormatNumberPipe} from '@taiga-ui/core'; @Component({ standalone: true, imports: [AsyncPipe, TuiBarSet, TuiFormatNumberPipe], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly value = [451, 302, 203, 124, 65]; protected readonly sum = this.value.reduce((a, b) => a + b, 0); } ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; import {TuiBarSet} from '@taiga-ui/addon-charts'; import {type TuiSizeL, type TuiSizeS} from '@taiga-ui/core'; @Component({ standalone: true, imports: [TuiBarSet, TuiDemo], templateUrl: './index.html', styleUrls: ['./index.less'], changeDetection, }) export default class Page { protected readonly examples = [ 'Dynamic size', 'Fixed size', 'With negative values', 'Horizontal', 'With value label', ]; protected collapsed = false; protected readonly sizeVariants: ReadonlyArray = ['s', 'm', 'l']; protected size: TuiSizeL | TuiSizeS | null = null; protected readonly valueVariants = [ [30, 20, 10], [237, -50, 10, 5, 1], ]; protected value = this.valueVariants[0]!; } ``` ### LESS ```less .bars { block-size: 10rem; inline-size: 6.25rem; box-shadow: 0 1px var(--tui-border-normal); } ``` --- # components/Block - **Package**: `KIT` - **Type**: components Block is a special presentation of a checkbox/radiobutton which can display actual control or be a control itself ### How to Use (Import) ```ts import {FormsModule, ReactiveFormsModule} from '@angular/forms'; import {TuiBlock, TuiCheckbox} from '@taiga-ui/kit'; // ... @Component({ standalone: true, imports: [ // ... FormsModule, TuiBlock, TuiCheckbox, // or TuiRadio ], // ... }) export class Example {} ``` ### How to Use (Template) ```html ``` ### Example ```html ``` ### API | Property | Type | Description | |----------|-----|----------| | [tuiBlock] | `TuiSizeL | TuiSizeS` | Size of the block | ### Usage Examples #### Sizes **Template:** ```html
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {FormControl, FormGroup, ReactiveFormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiIcon, TuiTitle} from '@taiga-ui/core'; import {TuiBlock, TuiCheckbox, TuiRadio, TuiTooltip} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [ ReactiveFormsModule, TuiBlock, TuiCheckbox, TuiIcon, TuiRadio, TuiTitle, TuiTooltip, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly testForm = new FormGroup({ testValue1: new FormControl(true), testValue2: new FormControl({value: false, disabled: true}), testValue3: new FormControl({value: true, disabled: true}), testValue4: new FormControl(false), testValue5: new FormControl(), }); } ``` #### Groups **Template:** ```html

Horizontal group

Vertical group

Without checkbox indicators

``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {FormControl, FormGroup, ReactiveFormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiGroup} from '@taiga-ui/core'; import {TuiBlock, TuiFade, TuiRadio} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [ReactiveFormsModule, TuiBlock, TuiFade, TuiGroup, TuiRadio], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly testForm = new FormGroup({ testValue: new FormControl('orange'), }); } ``` #### Custom **Template:** ```html
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {FormControl, FormGroup, ReactiveFormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiIcon, TuiTitle} from '@taiga-ui/core'; import {TuiAvatar, TuiBlock, TuiCheckbox, TuiSwitch, TuiTooltip} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [ ReactiveFormsModule, TuiAvatar, TuiBlock, TuiCheckbox, TuiIcon, TuiSwitch, TuiTitle, TuiTooltip, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly testForm = new FormGroup({ testValue1: new FormControl(false), testValue2: new FormControl(false), testValue3: new FormControl(false), testValue4: new FormControl(false), }); } ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {TuiDocAppearance} from '@demo/components/appearance'; import {TuiDocIcons} from '@demo/components/icons'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; import {type TuiSizeL, type TuiSizeS, TuiTitle} from '@taiga-ui/core'; import {TuiBlock, TuiSwitch} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [ FormsModule, TuiBlock, TuiDemo, TuiDocAppearance, TuiDocIcons, TuiSwitch, TuiTitle, ], templateUrl: './index.html', changeDetection, }) export default class Example { protected readonly examples = ['Sizes', 'Groups', 'Custom']; protected readonly sizes: ReadonlyArray = ['s', 'm', 'l']; protected readonly appearances = ['outline-grayscale', 'secondary']; protected value = false; protected size = this.sizes[2]!; } ``` --- # components/BlockDetails - **Package**: `LAYOUT` - **Type**: components Layout directive for describing details. For example, transaction details ### How to Use (Import) ```ts import {Component} from '@angular/core'; import {TuiBlockDetails} from '@taiga-ui/layout'; // ... @Component({ standalone: true, imports: [ // ... TuiBlockDetails, ], }) export class Example {} ``` ### How to Use (Template) ```html

Title
Subtitle

{{ amount }} | tuiAmount: 'USD' | async }} description comment Badge
``` ### Usage Examples #### Full **Template:** ```html

John W
money transfers

{{ -1050 | tuiAmount: 'USD' | async }} today extra subtitle Birthday gift
private fast
Pending
``` **TypeScript:** ```ts import {AsyncPipe} from '@angular/common'; import {Component, inject} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAmountPipe} from '@taiga-ui/addon-commerce'; import {TUI_IS_MOBILE} from '@taiga-ui/cdk'; import {TuiIcon, TuiTitle} from '@taiga-ui/core'; import {TuiAvatar, TuiBadge, TuiComment} from '@taiga-ui/kit'; import {TuiBlockDetails} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ AsyncPipe, TuiAmountPipe, TuiAvatar, TuiBadge, TuiBlockDetails, TuiComment, TuiIcon, TuiTitle, ], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected readonly isMobile = inject(TUI_IS_MOBILE); } ``` #### Customization **Template:** ```html

Auchan
grocery • MMC 5350

{{ 0.5 | tuiAmount: 'USD' | async }} promotion (long value with fade) cashback

Uber
taxi • MMC 5550

{{ -10.5 | tuiAmount: 'USD' | async }}
``` **TypeScript:** ```ts import {AsyncPipe} from '@angular/common'; import {Component, inject} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {tuiAmountOptionsProvider, TuiAmountPipe} from '@taiga-ui/addon-commerce'; import {TUI_IS_MOBILE} from '@taiga-ui/cdk'; import {TuiTitle} from '@taiga-ui/core'; import {TuiAvatar, TuiBadge, TuiFade} from '@taiga-ui/kit'; import {TuiBlockDetails} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ AsyncPipe, TuiAmountPipe, TuiAvatar, TuiBadge, TuiBlockDetails, TuiFade, TuiTitle, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, providers: [tuiAmountOptionsProvider({sign: 'always'})], }) export default class Example { protected readonly isMobile = inject(TUI_IS_MOBILE); } ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; @Component({ standalone: true, imports: [TuiDemo], templateUrl: './index.html', changeDetection, }) export default class Page {} ``` --- # components/BlockStatus - **Package**: `LAYOUT` - **Type**: components Component for status screens, result screens and zero screens ### How to Use (Import) ```ts import {TuiBlockStatus} from '@taiga-ui/layout'; // ... @Component({ standalone: true, imports: [ // ... TuiBlockStatus, ], // ... }) export class Example {} ``` ### How to Use (Template) ```html

Title

Description
``` ### Example ```html hidden content

Title

Description
``` ### API | Property | Type | Description | |----------|-----|----------| | [card] | `boolean` | Enable border radius and padding for card view | | [size] | `TuiSizeL` | Size (for desktop only) | ### Usage Examples #### Basic **Template:** ```html not found

Not found

Try to find by number
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiBlockStatus} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [TuiBlockStatus], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example {} ``` #### With actions **Template:** ```html survived

Something has been achieved

You can do something with it, or you can not do it. And the description text can be quite long.
``` **TypeScript:** ```ts import {AsyncPipe, NgIf} from '@angular/common'; import {Component, inject} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiBreakpointService, TuiButton, type TuiSizeL} from '@taiga-ui/core'; import {TuiBlockStatus} from '@taiga-ui/layout'; import {map, type Observable} from 'rxjs'; @Component({ standalone: true, imports: [AsyncPipe, NgIf, TuiBlockStatus, TuiButton], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected readonly breakpointService = inject(TuiBreakpointService); protected size$: Observable = this.breakpointService.pipe( map((key) => (key === 'mobile' ? 'm' : 'l')), ); } ``` #### Cards **Template:** ```html
hidden content We hide the unwanted block something wrong Something happened in this block
``` **TypeScript:** ```ts import {AsyncPipe, NgIf} from '@angular/common'; import {Component, inject} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiBreakpointService, TuiButton, type TuiSizeL} from '@taiga-ui/core'; import {TuiBlockStatus} from '@taiga-ui/layout'; import {map, type Observable} from 'rxjs'; @Component({ standalone: true, imports: [AsyncPipe, NgIf, TuiBlockStatus, TuiButton], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly breakpointService = inject(TuiBreakpointService); protected size$: Observable = this.breakpointService.pipe( map((key) => (key === 'mobile' ? 'm' : 'l')), ); } ``` #### Customization **Template:** ```html
You can put other content instead of image using tui-block-content css class Alex Inkin

Alex Inkin

``` **TypeScript:** ```ts import {NgFor} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAutoColorPipe, TuiButton, TuiInitialsPipe} from '@taiga-ui/core'; import {TuiAvatar, TuiAvatarStack} from '@taiga-ui/kit'; import {TuiBlockStatus} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ NgFor, TuiAutoColorPipe, TuiAvatar, TuiAvatarStack, TuiBlockStatus, TuiButton, TuiInitialsPipe, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly users = [ 'Alex Inkin', 'Vladimir Potekhin', 'Nikita Barsukov', 'Maxim Ivanov', ]; } ``` #### Mobile **Template:** ```html
hidden content We hide the unwanted block something wrong Something happened in this block Something happened in this block
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiPlatform} from '@taiga-ui/cdk'; import {TuiButton} from '@taiga-ui/core'; import {TuiBlockStatus} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [TuiBlockStatus, TuiButton, TuiPlatform], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Desktop medium **Template:** ```html survived

There is nothing here yet

To get started, create a server
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiButton} from '@taiga-ui/core'; import {TuiBlockStatus} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [TuiBlockStatus, TuiButton], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example {} ``` #### Empty image block **Template:** ```html

Something happened in this block

Try again later
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiButton} from '@taiga-ui/core'; import {TuiBlockStatus} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [TuiBlockStatus, TuiButton], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example {} ``` #### Empty description block **Template:** ```html
hidden content

No operations

hidden content

No operations

``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiButton} from '@taiga-ui/core'; import {TuiBlockStatus} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [TuiBlockStatus, TuiButton], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; import {TuiButton, type TuiSizeL} from '@taiga-ui/core'; import {TuiBlockStatus} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [TuiBlockStatus, TuiButton, TuiDemo], templateUrl: './index.html', changeDetection, }) export default class Example { protected card = false; protected readonly sizes: TuiSizeL[] = ['l', 'm']; protected size: TuiSizeL = this.sizes[0] || 'l'; protected readonly examples = [ 'Basic', 'With actions', 'Cards', 'Customization', 'Mobile', 'Desktop medium', 'Empty image block', 'Empty description block', ]; } ``` --- # components/BottomSheet - **Package**: `ADDON-MOBILE` - **Type**: components A non-modal draggable sheet ### How to Use (Import) ```ts import {TuiBottomSheet} from '@taiga-ui/addon-mobile'; // ... @Component({ standalone: true, imports: [ // ... TuiBottomSheet, ], // ... }) export class Example {} ``` ### How to Use (Template) ```html Content ``` ### API | Property | Type | Description | |----------|-----|----------| | [stops] | `readonly string[]` | Scroll snap stops | ### Usage Examples #### Basic **Template:** ```html
What's up?
``` **TypeScript:** ```ts import {NgForOf} from '@angular/common'; import {Component, ElementRef, ViewChild} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiBottomSheet} from '@taiga-ui/addon-mobile'; import {TuiAppearance, TuiButton, TuiScrollbar, TuiTextfield} from '@taiga-ui/core'; import {TuiMessage, TuiTextarea} from '@taiga-ui/kit'; import {TuiCardLarge} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ FormsModule, NgForOf, TuiAppearance, TuiBottomSheet, TuiButton, TuiCardLarge, TuiMessage, TuiScrollbar, TuiTextarea, TuiTextfield, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { @ViewChild(TuiBottomSheet, {read: ElementRef}) private readonly sheet?: ElementRef; protected messages = ['Check that awesome bottom sheet out!']; protected value = ''; protected onClick(message: string): void { this.messages = this.messages.concat(message); this.sheet?.nativeElement.scrollTo({top: 0, behavior: 'smooth'}); } protected onSubmit(): void { this.messages = this.messages.concat(this.value); this.value = ''; } } ``` #### Reacting to scroll **Template:** ```html

London United Kingdom

Population 8,866,180
Area 1,572 square km
Time zone UTC+00:00 (Greenwich Mean Time)
Established 47 AD
London is the capital and largest city of both England and the United Kingdom, with a population of 8,866,180 in 2022. Its wider metropolitan area is the largest in Western Europe, with a population of 14.9 million. London stands on the River Thames in southeast England, at the head of a 50-mile (80 km) tidal estuary down to the North Sea, and has been a major settlement for nearly 2,000 years. Its ancient core and financial centre, the City of London, was founded by the Romans and has retained its medieval boundaries. The City of Westminster, to the west of the City of London, has been the centuries-long host of the national government and parliament. London grew rapidly in the 19th century, becoming the world's largest city at the time. Since the 19th century, the name "London" has referred to the metropolis around the City of London.
``` **TypeScript:** ```ts import {Component, type ElementRef, ViewChild} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiBottomSheet} from '@taiga-ui/addon-mobile'; import {TuiButton, TuiTitle} from '@taiga-ui/core'; import {TuiHeader} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [TuiBottomSheet, TuiButton, TuiHeader, TuiTitle], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { @ViewChild('buttons') protected readonly button?: ElementRef; protected readonly stops = ['112px'] as const; protected onScroll({clientHeight, scrollTop}: HTMLElement): void { const offset = Number.parseInt(this.stops[0], 10); const top = Math.min(scrollTop, clientHeight - offset); const transform = `translate3d(0, ${-top}px, 0)`; this.button?.nativeElement.style.setProperty('transform', transform); } } ``` #### Stops **Template:** ```html
Taiga UI Give us a Star

All work and no play makes Jack a dull boy

All work and no play makes Jack a dull boy
``` **TypeScript:** ```ts import {NgIf} from '@angular/common'; import {Component} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiBottomSheet} from '@taiga-ui/addon-mobile'; import {TuiRepeatTimes} from '@taiga-ui/cdk'; import {TuiButton} from '@taiga-ui/core'; import {TuiAccordion} from '@taiga-ui/experimental'; import {TuiBlock, TuiCheckbox} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [ FormsModule, NgIf, TuiAccordion, TuiBlock, TuiBottomSheet, TuiButton, TuiCheckbox, TuiRepeatTimes, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected show = true; } ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; @Component({ standalone: true, imports: [TuiDemo], templateUrl: './index.html', changeDetection, }) export default class Page { protected readonly examples = ['Basic', 'Reacting to scroll', 'Stops']; } ``` --- # components/Breadcrumbs - **Package**: `KIT` - **Type**: components Navigation element that shows a path from root page to the current ### How to Use (Import) ```ts import {TuiItem} from '@taiga-ui/cdk'; import {TuiBreadcrumbs} from '@taiga-ui/kit'; // ... @Component({ standalone: true, imports: [ // ... TuiItem, TuiBreadcrumbs, ], // ... }) export class Example {} ``` ### How to Use (Template) ```html {{ item.caption }} ``` ### Example ```html ``` ### API | Property | Type | Description | |----------|-----|----------| | [itemsLimit] | `number` | Limit on visible items | | [size] | `TuiSizeL` | Text size | ### Usage Examples #### Basic **Template:** ```html {{ item.caption }} {{ item.caption }} ``` **TypeScript:** ```ts import {NgFor} from '@angular/common'; import {Component} from '@angular/core'; import {RouterLink} from '@angular/router'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiItem} from '@taiga-ui/cdk'; import {TuiLink} from '@taiga-ui/core'; import {TuiBreadcrumbs} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [NgFor, RouterLink, TuiBreadcrumbs, TuiItem, TuiLink], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected items = [ { caption: 'Selects', routerLink: '/components/select', }, { caption: 'Multi', routerLink: '/components/multi-select', }, { caption: 'With tags', routerLink: '/components/multi-select', }, { caption: 'Current', routerLink: '/navigation/breadcrumbs', routerLinkActiveOptions: {exact: true}, }, ]; } ``` #### Overflow **Template:** ```html

Truncate Using .text-truncate() mixin


Fade Combining .text-truncate() mixin with Fade directive


Scroll Putting Fade directive on entire component


Collapse Using itemsLimit: number

``` **TypeScript:** ```ts import {NgForOf} from '@angular/common'; import {Component} from '@angular/core'; import {RouterLink} from '@angular/router'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {DemoRoute} from '@demo/routes'; import {TuiItem} from '@taiga-ui/cdk'; import {TuiHint, TuiLink, TuiTitle} from '@taiga-ui/core'; import {TuiBreadcrumbs, tuiBreadcrumbsOptionsProvider, TuiFade} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [ NgForOf, RouterLink, TuiBreadcrumbs, TuiFade, TuiHint, TuiItem, TuiLink, TuiTitle, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, providers: [tuiBreadcrumbsOptionsProvider({icon: '/'})], }) export default class Example { protected readonly fade = DemoRoute.Fade; protected readonly items = [ 'First item', 'Very very long second item that must overflow', 'Third item', 'One last super long item that is never gonna fit', ]; } ``` ### TypeScript ```ts import {Component, inject} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; import {TuiItem} from '@taiga-ui/cdk'; import {TuiLink, type TuiSizeL} from '@taiga-ui/core'; import {TUI_BREADCRUMBS_OPTIONS, TuiBreadcrumbs} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiBreadcrumbs, TuiDemo, TuiItem, TuiLink], templateUrl: './index.html', changeDetection, }) export default class Example { private readonly options = inject(TUI_BREADCRUMBS_OPTIONS); protected readonly examples = ['Basic', 'Overflow']; protected readonly items = [ 'Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5', 'Item 6', 'Item 7', 'Item 8', ]; protected readonly sizeVariants: readonly TuiSizeL[] = ['m', 'l']; protected size: TuiSizeL = this.options.size; protected itemsLimit = this.options.itemsLimit; } ``` --- # components/Button - **Package**: `CORE` - **Type**: components ### How to Use (Import) ```ts import {Component} from '@angular/core'; import {TuiButton} from '@taiga-ui/core'; // ... @Component({ standalone: true, imports: [ // ... TuiButton, ], }) export class Example {} ``` ### How to Use (Template) ```html Press me ``` ### Example ```html ``` ### API | Property | Type | Description | |----------|-----|----------| | [size] | `TuiSizeXS | TuiSizeL` | Size of the button | | [loading] | `boolean` | ) | ### Usage Examples #### Sizes **Template:** ```html ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiButton} from '@taiga-ui/core'; @Component({ standalone: true, imports: [TuiButton], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Appearance **Template:** ```html
See Appearance directive for more.
Use tuiAppearanceMode to emulate :checked / :invalid CSS state for outline appearance:
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {RouterLink} from '@angular/router'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {DemoRoute} from '@demo/routes'; import {TuiButton, TuiLink} from '@taiga-ui/core'; @Component({ standalone: true, imports: [RouterLink, TuiButton, TuiLink], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly routes = DemoRoute; } ``` #### Icons **Template:** ```html ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiButton, TuiIcon} from '@taiga-ui/core'; import {TuiAvatar} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiAvatar, TuiButton, TuiIcon], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Loading **Template:** ```html ``` **TypeScript:** ```ts import {AsyncPipe} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TUI_FALSE_HANDLER} from '@taiga-ui/cdk'; import {TuiButton} from '@taiga-ui/core'; import {TuiButtonLoading} from '@taiga-ui/kit'; import {map, startWith, Subject, switchMap, timer} from 'rxjs'; @Component({ standalone: true, imports: [AsyncPipe, TuiButton, TuiButtonLoading], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected readonly trigger$ = new Subject(); protected readonly loading$ = this.trigger$.pipe( switchMap(() => timer(2000).pipe(map(TUI_FALSE_HANDLER), startWith('Loading'))), ); } ``` #### Options with DI **Template:** ```html ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiButton, tuiButtonOptionsProvider} from '@taiga-ui/core'; @Component({ standalone: true, imports: [TuiButton], templateUrl: './index.html', encapsulation, changeDetection, providers: [tuiButtonOptionsProvider({size: 's'})], }) export default class Example {} ``` #### Vertical **Template:** ```html ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiButton} from '@taiga-ui/core'; import {TuiAvatar, TuiFade} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiAvatar, TuiButton, TuiFade], templateUrl: './index.html', styles: [':host { display: flex; gap: 1rem; align-items: flex-start; }'], encapsulation, changeDetection, }) export default class Example {} ``` #### Two labels **Template:** ```html

``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiButton} from '@taiga-ui/core'; import {TuiFade} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiButton, TuiFade], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {TuiDocAppearance} from '@demo/components/appearance'; import {TuiDocIcons} from '@demo/components/icons'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; import {TuiButton, type TuiSizeL, type TuiSizeXS} from '@taiga-ui/core'; import {TuiButtonLoading} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiButton, TuiButtonLoading, TuiDemo, TuiDocAppearance, TuiDocIcons], templateUrl: './index.html', changeDetection, }) export default class Page { protected readonly examples = [ 'Sizes', 'Appearance', 'Icons', 'Loading', 'Options with DI', 'Vertical', 'Two labels', ]; protected readonly sizes: ReadonlyArray = ['xs', 's', 'm', 'l']; protected size = this.sizes[3]!; protected loading = false; } ``` --- # components/ButtonClose - **Package**: `KIT` - **Type**: components ### How to Use (Import) ```ts import {Component} from '@angular/core'; import {TuiButton} from '@taiga-ui/core'; import {TuiButtonClose} from '@taiga-ui/kit'; // ... @Component({ standalone: true, imports: [ // ... TuiButton, TuiButtonClose, ], }) export class Example {} ``` ### How to Use (Template) ```html ``` ### Usage Examples #### Basic **Template:** ```html ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiButton} from '@taiga-ui/core'; import {TuiButtonClose} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiButton, TuiButtonClose], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; @Component({ standalone: true, imports: [TuiDemo], templateUrl: './index.html', changeDetection, }) export default class Page {} ``` --- # components/ButtonGroup - **Package**: `KIT` - **Type**: components ### How to Use (Import) ```ts import {Component} from '@angular/core'; import {TuiButton} from '@taiga-ui/core'; import {TuiButtonGroup} from '@taiga-ui/kit'; // ... @Component({ standalone: true, imports: [ // ... TuiButton, TuiButtonGroup, ], }) export class Example {} ``` ### How to Use (Template) ```html
``` ### Usage Examples #### Elevated **Template:** ```html
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAppearance, TuiIcon} from '@taiga-ui/core'; import {TuiButtonGroup, TuiIconBadge} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiAppearance, TuiButtonGroup, TuiIcon, TuiIconBadge], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Flat **Template:** ```html
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAppearance, TuiIcon} from '@taiga-ui/core'; import {TuiButtonGroup} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiAppearance, TuiButtonGroup, TuiIcon], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Dark **Template:** ```html
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiIcon} from '@taiga-ui/core'; import {TuiButtonGroup} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiButtonGroup, TuiIcon], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Swiped animation **Template:** ```html

BANK {{ item.title }}

{{ item.content }}
``` **TypeScript:** ```ts import {NgForOf, NgIf} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiIcon, TuiTitle} from '@taiga-ui/core'; import { TuiBadge, TuiButtonGroup, TuiCarousel, TuiElasticContainer, TuiPagination, } from '@taiga-ui/kit'; import {TuiCardMedium} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ NgForOf, NgIf, TuiBadge, TuiButtonGroup, TuiCardMedium, TuiCarousel, TuiElasticContainer, TuiIcon, TuiPagination, TuiTitle, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected index = 0; protected opacity = 1; protected readonly items = [ { title: 'RUB Account', content: '10 000 ₽', gradient: 'linear-gradient(334.83deg, #7d8ca0 0%, #647382 100%)', color: '#7d8ca0', }, { title: 'USD Account', content: '2 000 000 $', gradient: 'linear-gradient(-90deg, #cf77f3 0%, #009bff 47%, #2ac9db 100%)', color: 'rgb(0, 155, 255)', }, { title: 'EUR Account', content: '30 000 €', gradient: 'linear-gradient(135deg, #1AC07E, #DEA683)', color: 'rgb(158 178 129)', }, ]; } ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; @Component({ standalone: true, imports: [TuiDemo], templateUrl: './index.html', changeDetection, }) export default class Page { protected readonly examples = ['Elevated', 'Flat', 'Dark', 'Swiped animation']; } ``` --- # components/Calendar - **Package**: `CORE` - **Type**: components A simple calendar. If you want a textfield with date, see InputDate and InputDateRange ### How to Use (Import) ```ts import {TuiCalendar} from '@taiga-ui/core'; // ... @Component({ standalone: true, imports: [ // ... TuiCalendar, ], // ... }) export class Example {} ``` ### How to Use (Template) ```html ``` ### Example ```html ``` ### API | Property | Type | Description | |----------|-----|----------| | [disabledItemHandler] | `TuiBooleanHandler` | | | [showAdjacent] | `boolean` | Show adjacent months days | | [(hoveredItem)] | `TuiDay | null` | Hovered date | | [markerHandler] | `TuiMarkerHandler | null` | A handler that gets date and returns null or a tuple with circled marker colors | | [max] | `TuiDay | null` | Maximal date to choose | | [maxViewedMonth] | `TuiMonth | null` | Maximal month to access | | [min] | `TuiDay | null` | Minimum date to choose | | [minViewedMonth] | `TuiMonth | null` | Minimum month to access | | [(month)] | `TuiMonth` | Current month | | [value] | `TuiDay | TuiDayRange | null` | Selected day or range | | (dayClick) | `TuiDay` | Date click | ### Usage Examples #### Basic **Template:** ```html
Chosen date: {{ value }}
``` **TypeScript:** ```ts import {NgIf} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {type TuiDay} from '@taiga-ui/cdk'; import {TuiCalendar} from '@taiga-ui/core'; @Component({ standalone: true, imports: [NgIf, TuiCalendar], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected value: TuiDay | null = null; protected onDayClick(day: TuiDay): void { this.value = day; } } ``` #### Range **Template:** ```html
Chosen dates: {{ value }}
``` **TypeScript:** ```ts import {NgIf} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {type TuiDay, TuiDayRange, TuiMonth} from '@taiga-ui/cdk'; import {TuiCalendar} from '@taiga-ui/core'; @Component({ standalone: true, imports: [NgIf, TuiCalendar], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected value: TuiDayRange | null = null; protected firstMonth = TuiMonth.currentLocal(); protected middleMonth = TuiMonth.currentLocal().append({month: 1}); protected lastMonth = TuiMonth.currentLocal().append({month: 2}); protected hoveredItem: TuiDay | null = null; protected onDayClick(day: TuiDay): void { if (!this.value?.isSingleDay) { this.value = new TuiDayRange(day, day); } this.value = TuiDayRange.sort(this.value.from, day); } protected onMonthChangeFirst(month: TuiMonth): void { this.firstMonth = month; this.middleMonth = month.append({month: 1}); this.lastMonth = month.append({month: 2}); } protected onMonthChangeMiddle(month: TuiMonth): void { this.firstMonth = month.append({month: -1}); this.middleMonth = month; this.lastMonth = month.append({month: 1}); } protected onMonthChangeLast(month: TuiMonth): void { this.firstMonth = month.append({month: -2}); this.middleMonth = month.append({month: -1}); this.lastMonth = month; } } ``` #### With markers **Template:** ```html
Chosen dates: {{ value }}
``` **TypeScript:** ```ts import {NgIf} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {type TuiDay, TuiDayRange, TuiMonth} from '@taiga-ui/cdk'; import {TuiCalendar, type TuiMarkerHandler} from '@taiga-ui/core'; const TWO_DOTS: [string, string] = [ 'var(--tui-background-accent-1)', 'var(--tui-status-info)', ]; const ONE_DOT: [string] = ['var(--tui-status-positive)']; @Component({ standalone: true, imports: [NgIf, TuiCalendar], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected value: TuiDayRange | null = null; protected firstMonth = TuiMonth.currentLocal(); protected middleMonth = TuiMonth.currentLocal().append({month: 1}); protected lastMonth = TuiMonth.currentLocal().append({month: 2}); protected hoveredItem: TuiDay | null = null; protected readonly markerHandler: TuiMarkerHandler = (day: TuiDay) => // Attention: do not create new arrays in handler, use constants instead day.day % 2 === 0 ? TWO_DOTS : ONE_DOT; protected onDayClick(day: TuiDay): void { if (!this.value?.isSingleDay) { this.value = new TuiDayRange(day, day); } this.value = TuiDayRange.sort(this.value.from, day); } protected onMonthChangeFirst(month: TuiMonth): void { this.firstMonth = month; this.middleMonth = month.append({month: 1}); this.lastMonth = month.append({month: 2}); } protected onMonthChangeMiddle(month: TuiMonth): void { this.firstMonth = month.append({month: -1}); this.middleMonth = month; this.lastMonth = month.append({month: 1}); } protected onMonthChangeLast(month: TuiMonth): void { this.firstMonth = month.append({month: -2}); this.middleMonth = month.append({month: -1}); this.lastMonth = month; } } ``` #### Localization **Template:** ```html ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiDayOfWeek} from '@taiga-ui/cdk'; import {TUI_FIRST_DAY_OF_WEEK, TuiCalendar} from '@taiga-ui/core'; @Component({ standalone: true, imports: [TuiCalendar], templateUrl: './index.html', encapsulation, changeDetection, providers: [ { provide: TUI_FIRST_DAY_OF_WEEK, useValue: TuiDayOfWeek.Sunday, }, ], }) export default class Example {} ``` #### Color customization **Template:** ```html ``` **TypeScript:** ```ts import {Component, ViewEncapsulation} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {type TuiDay, type TuiHandler} from '@taiga-ui/cdk'; import {TUI_DAY_TYPE_HANDLER, TuiCalendar} from '@taiga-ui/core'; const handler: TuiHandler = (day: TuiDay) => { if (day.day === 10) { return 'holiday'; } return day.isWeekend ? 'weekend' : 'weekday'; }; @Component({ standalone: true, imports: [TuiCalendar], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation: ViewEncapsulation.None, changeDetection, providers: [{provide: TUI_DAY_TYPE_HANDLER, useValue: handler}], }) export default class Example {} ``` #### Select multiple dates **Template:** ```html
Chosen dates: {{ value }}
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {type TuiDay} from '@taiga-ui/cdk'; import {TuiCalendar} from '@taiga-ui/core'; @Component({ standalone: true, imports: [TuiCalendar], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected value: readonly TuiDay[] = []; protected onDayClick(day: TuiDay): void { this.value = this.value.find((item) => item.daySame(day)) ? this.value.filter((item) => !item.daySame(day)) : this.value.concat(day); } } ``` #### Open in year view **Template:** ```html
Chosen date: {{ value }}
``` **TypeScript:** ```ts import {NgIf} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {type TuiDay} from '@taiga-ui/cdk'; import {TuiCalendar} from '@taiga-ui/core'; @Component({ standalone: true, imports: [NgIf, TuiCalendar], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected value: TuiDay | null = null; protected onDayClick(day: TuiDay): void { this.value = day; } } ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {RouterModule} from '@angular/router'; import {changeDetection} from '@demo/emulate/change-detection'; import {DemoRoute} from '@demo/routes'; import {TuiDemo} from '@demo/utils'; import { TUI_FALSE_HANDLER, TUI_FIRST_DAY, TUI_LAST_DAY, type TuiBooleanHandler, TuiDay, TuiDayRange, TuiMonth, } from '@taiga-ui/cdk'; import {TuiCalendar, type TuiMarkerHandler} from '@taiga-ui/core'; const TWO_DOTS: [string, string] = [ 'var(--tui-background-accent-1)', 'var(--tui-status-info)', ]; const ONE_DOT: [string] = ['var(--tui-status-positive)']; @Component({ standalone: true, imports: [RouterModule, TuiCalendar, TuiDemo], templateUrl: './index.html', changeDetection, }) export default class Example { protected readonly examples = [ 'Basic', 'Range', 'With markers', 'Localization', 'Color customization', 'Select multiple dates', 'Open in year view', ]; protected showAdjacent = true; protected readonly minVariants = [ TUI_FIRST_DAY, new TuiDay(2017, 2, 5), new TuiDay(1900, 0, 1), ]; protected min = this.minVariants[0]!; protected readonly maxVariants = [ TUI_LAST_DAY, new TuiDay(2020, 3, 30), new TuiDay(2300, 0, 1), ]; protected max = this.maxVariants[0]!; protected readonly minViewedMonthVariants = [ new TuiMonth(0, 0), new TuiMonth(2017, 2), new TuiMonth(1900, 0), ]; protected minViewedMonth = this.minViewedMonthVariants[0]!; protected readonly maxViewedMonthVariants = [ TUI_LAST_DAY, new TuiMonth(2020, 3), new TuiMonth(2300, 0), ]; protected maxViewedMonth = this.maxViewedMonthVariants[0]!; protected readonly disabledItemHandlerVariants: ReadonlyArray< TuiBooleanHandler > = [TUI_FALSE_HANDLER, ({day}) => day % 3 === 0]; protected disabledItemHandler = this.disabledItemHandlerVariants[0]!; protected readonly markerHandlerVariants: readonly TuiMarkerHandler[] = [ (day: TuiDay) => (day.day % 2 === 0 ? TWO_DOTS : ONE_DOT), ]; protected markerHandler: TuiMarkerHandler | null = null; protected readonly valueVariants: ReadonlyArray = [ TuiDay.currentLocal(), new TuiDayRange(TuiDay.currentLocal(), TuiDay.currentLocal().append({day: 3})), new TuiDay(2020, 3, 21), ]; protected value: TuiDay | TuiDayRange | null = null; protected month = TuiMonth.currentLocal(); protected hoveredItem: TuiDay | null = null; protected readonly routes = DemoRoute; } ``` --- # components/CalendarMonth - **Package**: `KIT` - **Type**: components Month picker component. If you want a textfield, see InputMonth ### How to Use (Import) ```ts import {TuiCalendarMonth} from '@taiga-ui/kit'; // ... @Component({ standalone: true, imports: [ // ... TuiCalendarMonth, ], // ... }) export class Example {} ``` ### How to Use (Template) ```html ``` ### Example ```html ``` ### API | Property | Type | Description | |----------|-----|----------| | [disabledItemHandler] | `TuiBooleanHandler` | | | [max] | `TuiMonth | null` | Maximal month | | [min] | `TuiMonth | null` | Minimal month | | [maxLength] | `number` | Maximum length | | [minLength] | `number` | Minimum length | | [value] | `TuiMonth | TuiMonthRange | null` | A single month or a range of months | | [(year)] | `TuiYear` | Current year | | (monthClick) | `TuiMonth` | Selected month | ### Usage Examples #### Basic **Template:** ```html

Selected month: {{ value }}

Hovered month: {{ hoveredMonth }}

``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {type TuiMonth} from '@taiga-ui/cdk'; import {TuiCalendarMonth} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiCalendarMonth], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected value: TuiMonth | null = null; protected hoveredMonth: TuiMonth | null = null; protected onMonthClick(month: TuiMonth): void { this.value = month; } protected onMonthHovered(month: TuiMonth | null): void { this.hoveredMonth = month; } } ``` #### Range **Template:** ```html

Selected value: {{ value }}

``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiMonth, TuiMonthRange} from '@taiga-ui/cdk'; import {TuiCalendarMonth, tuiCalendarMonthOptionsProvider} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiCalendarMonth], templateUrl: './index.html', encapsulation, changeDetection, providers: [tuiCalendarMonthOptionsProvider({rangeMode: true})], }) export default class Example { protected value: TuiMonth | TuiMonthRange | null = null; protected max = TuiMonth.currentLocal().append({year: 1}); protected min = new TuiMonth(2019, 7); protected onMonthClick(month: TuiMonth): void { this.value = this.value instanceof TuiMonth ? TuiMonthRange.sort(this.value, month) : month; } } ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {RouterModule} from '@angular/router'; import {changeDetection} from '@demo/emulate/change-detection'; import {DemoRoute} from '@demo/routes'; import {TuiDemo} from '@demo/utils'; import { TUI_FALSE_HANDLER, TUI_FIRST_DAY, TUI_LAST_DAY, type TuiBooleanHandler, TuiDay, TuiMonth, TuiMonthRange, TuiYear, } from '@taiga-ui/cdk'; import {TuiLink} from '@taiga-ui/core'; import {TuiCalendarMonth} from '@taiga-ui/kit'; import {TuiInputMonthRangeModule} from '@taiga-ui/legacy'; @Component({ standalone: true, imports: [RouterModule, TuiCalendarMonth, TuiDemo, TuiInputMonthRangeModule, TuiLink], templateUrl: './index.html', changeDetection, }) export default class Example { protected readonly examples = ['Basic', 'Range']; protected readonly minVariants = [ TUI_FIRST_DAY, new TuiMonth(2019, 2), new TuiMonth(2007, 0), ]; protected readonly maxVariants = [ TUI_LAST_DAY, new TuiMonth(2020, 2), new TuiMonth(2023, 0), new TuiMonth(2019, 4), ]; protected min = this.minVariants[0]!; protected max = this.maxVariants[0]!; protected maxLength = 0; protected minLength = 0; protected readonly disabledItemHandlerVariants: ReadonlyArray< TuiBooleanHandler > = [TUI_FALSE_HANDLER, ({month}) => month % 3 === 0]; protected disabledItemHandler = this.disabledItemHandlerVariants[0]!; protected readonly valueVariants: ReadonlyArray = [ TuiDay.currentLocal(), new TuiMonthRange( TuiDay.currentLocal(), TuiDay.currentLocal().append({month: 3}), ), new TuiMonth(2007, 2), ]; protected value: TuiMonth | TuiMonthRange | null = null; protected readonly yearVariants: readonly TuiYear[] = [ TuiDay.currentLocal(), new TuiYear(2007), ]; protected year = this.yearVariants[0]!; protected readonly routes = DemoRoute; } ``` --- # components/CalendarRange - **Package**: `KIT` - **Type**: components Component for choosing date range in calendar ### How to Use (Import) ```ts import {TuiCalendarRange} from '@taiga-ui/kit'; // ... @Component({ standalone: true, imports: [ // ... TuiCalendarRange, ], // ... }) export class Example {} ``` ### How to Use (Template) ```html ``` ### Example ```html ``` ### API | Property | Type | Description | |----------|-----|----------| | [defaultViewedMonth] | `TuiMonth` | Default month to show | | [disabledItemHandler] | `TuiBooleanHandler` | | | [items] | `TuiDayRangePeriod[]` | Fixed intervals (shows 2 calendars with empty array) | | [markerHandler] | `TuiMarkerHandler | null` | A handler that gets date and returns null or a tuple with circled marker colors | | [min] | `TuiDay | null` | Min date | | [max] | `TuiDay | null` | Max date | | [minLength] | `TuiDayLike | null` | Minimal length of range | | [maxLength] | `TuiDayLike | null` | Maximal length of range | | (rangeChange) | `TuiDayRange` | Selected date range | ### Usage Examples #### Basic **Template:** ```html ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiCalendarRange} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiCalendarRange], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example {} ``` #### With value **Template:** ```html ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiDay, TuiDayRange} from '@taiga-ui/cdk'; import {TUI_CALENDAR_DATE_STREAM, TuiCalendarRange} from '@taiga-ui/kit'; import {of} from 'rxjs'; export const calendarStream$ = of( new TuiDayRange(new TuiDay(2019, 2, 11), new TuiDay(2019, 2, 14)), ); @Component({ standalone: true, imports: [TuiCalendarRange], templateUrl: './index.html', encapsulation, changeDetection, providers: [ { provide: TUI_CALENDAR_DATE_STREAM, useValue: calendarStream$, }, ], }) export default class Example {} ``` #### With ranges **Template:** ```html ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiCalendarRange, tuiCreateDefaultDayRangePeriods} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiCalendarRange], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected items = tuiCreateDefaultDayRangePeriods(); } ``` #### Localization **Template:** ```html ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiDayOfWeek} from '@taiga-ui/cdk'; import {TUI_FIRST_DAY_OF_WEEK} from '@taiga-ui/core'; import {TuiCalendarRange} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiCalendarRange], templateUrl: './index.html', encapsulation, changeDetection, providers: [ { provide: TUI_FIRST_DAY_OF_WEEK, useValue: TuiDayOfWeek.Sunday, }, ], }) export default class Example {} ``` #### With another range switcher **Template:** ```html

You are seeing {{ selected }}.

``` **TypeScript:** ```ts import {NgIf} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiDay, TuiDayRange} from '@taiga-ui/cdk'; import {TuiLink} from '@taiga-ui/core'; import {TuiCalendarRange, TuiDayRangePeriod} from '@taiga-ui/kit'; const today = TuiDay.currentLocal(); const startOfWeek = today.append({day: -today.dayOfWeek()}); const startOfMonth = today.append({day: 1 - today.day}); const startOfQuarter = startOfMonth.append({month: -(startOfMonth.month % 3)}); @Component({ standalone: true, imports: [NgIf, TuiCalendarRange, TuiLink], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected readonly items = [ new TuiDayRangePeriod( new TuiDayRange(today.append({day: -30}), today), 'Default', ), new TuiDayRangePeriod(new TuiDayRange(startOfWeek, today), 'Week'), new TuiDayRangePeriod(new TuiDayRange(startOfMonth, today), 'Month'), new TuiDayRangePeriod(new TuiDayRange(startOfQuarter, today), 'Quarter'), ]; protected selected: TuiDayRangePeriod | null = this.default; protected value: TuiDayRange | null = this.default.range; public get default(): TuiDayRangePeriod { return this.items[0]!; } public get isDefault(): boolean { return this.selected === this.default; } public get isSelected(): boolean { return !!this.items.find((item) => item === this.selected); } public get isLastVisible(): boolean { return this.selected === this.items[this.items.length - 1]; } public get opposite(): TuiDayRangePeriod | null { if (!this.isSelected) { return null; } switch (this.selected) { case this.default: return null; case this.items[1]: return this.items[2]!; case this.items[2]: return this.items[3]!; case this.items[3]: return null; default: return null; } } public onValue(value: TuiDayRange | null): void { this.value = value; } public reset(): void { this.selected = this.default; this.value = this.selected.range; } public toggle(): void { this.selected = this.opposite; this.value = this.selected?.range ?? null; } } ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {DemoRoute} from '@demo/routes'; import {TuiDemo} from '@demo/utils'; import { TUI_FALSE_HANDLER, TUI_FIRST_DAY, TUI_LAST_DAY, type TuiBooleanHandler, TuiDay, type TuiDayLike, TuiMonth, } from '@taiga-ui/cdk'; import {TuiLink, type TuiMarkerHandler} from '@taiga-ui/core'; import { TuiCalendarRange, tuiCreateDefaultDayRangePeriods, type TuiDayRangePeriod, } from '@taiga-ui/kit'; const TWO_DOTS: [string, string] = [ 'var(--tui-background-accent-1)', 'var(--tui-status-info)', ]; const ONE_DOT: [string] = ['var(--tui-status-positive)']; @Component({ standalone: true, imports: [TuiCalendarRange, TuiDemo, TuiLink], templateUrl: './index.html', changeDetection, }) export default class Example { protected readonly examples = [ 'Basic', 'With value', 'With ranges', 'Localization', 'With another range switcher', ]; protected readonly minVariants = [ TUI_FIRST_DAY, new TuiDay(2017, 2, 5), new TuiDay(1900, 0, 1), ]; protected readonly maxVariants = [ TUI_LAST_DAY, new TuiDay(2018, 9, 30), new TuiDay(2020, 2, 5), new TuiDay(2300, 0, 1), TuiDay.currentLocal(), ]; protected readonly disabledItemHandlerVariants: ReadonlyArray< TuiBooleanHandler > = [TUI_FALSE_HANDLER, ({day}) => day % 3 === 0]; protected readonly defaultViewedMonthVariants: readonly TuiMonth[] = [ TuiMonth.currentLocal(), TuiMonth.currentLocal().append({month: 1}), new TuiMonth(2007, 5), ]; protected readonly itemsVariants: ReadonlyArray = [ [], tuiCreateDefaultDayRangePeriods(), ]; protected readonly minLengthVariants: readonly TuiDayLike[] = [ {day: 3}, {day: 15}, {month: 1}, {month: 1, day: 1}, ]; protected readonly maxLengthVariants: readonly TuiDayLike[] = [ {day: 5}, {month: 1}, {year: 1}, ]; protected readonly markerHandlerVariants: readonly TuiMarkerHandler[] = [ (day: TuiDay) => (day.day % 2 === 0 ? TWO_DOTS : ONE_DOT), ]; protected markerHandler: TuiMarkerHandler | null = null; protected min: TuiDay = this.minVariants[0]!; protected max: TuiDay = this.maxVariants[0]!; protected cleaner = false; protected disabledItemHandler = this.disabledItemHandlerVariants[0]!; protected items = this.itemsVariants[0]!; protected defaultViewedMonth = this.defaultViewedMonthVariants[0]!; protected minLength: TuiDayLike | null = null; protected maxLength: TuiDayLike | null = null; protected readonly routes = DemoRoute; } ``` --- # components/CardCollapsed - **Package**: `LAYOUT` - **Type**: components ### How to Use (Import) ```ts import {TuiButton, TuiTitle} from '@taiga-ui/core'; import {TuiExpand, TuiChevron} from '@taiga-ui/kit'; import {TuiCard, TuiHeader} from '@taiga-ui/layout'; // ... @Component({ standalone: true, imports: [ // ... TuiCard, TuiHeader, TuiTitle, TuiButton, TuiChevron, TuiExpand, ], }) export class Example {} ``` ### How to Use (Template) ```html

Title

Subtitle

...
``` ### Usage Examples #### Basic **Template:** ```html

[31344] Error finding account number when executing the deal

Some clients could encounter an error “Account not found” when selecting the account on the checkout screen

Status
Pending
Category
Angular Open Source
Project Version Description
Taiga UI 4.32.0 Angular UI kit for awesome people
Maskito 3.5.0 Holy Grail of input masking for the Web
I'm just another card
``` **TypeScript:** ```ts import {Component, signal} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiTable} from '@taiga-ui/addon-table'; import {TuiButton, TuiIcon, TuiLink, TuiTitle} from '@taiga-ui/core'; import {TuiExpand} from '@taiga-ui/experimental'; import {TuiBadge, TuiChevron} from '@taiga-ui/kit'; import {TuiCard, TuiHeader} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ TuiBadge, TuiButton, TuiCard, TuiChevron, TuiExpand, TuiHeader, TuiIcon, TuiLink, TuiTable, TuiTitle, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { public readonly collapsed = signal(true); } ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; @Component({ standalone: true, imports: [TuiDemo], templateUrl: './index.html', changeDetection, }) export default class Example { protected readonly examples = ['Basic']; } ``` --- # components/CardLarge - **Package**: `LAYOUT` - **Type**: components ### How to Use (Import) ```ts import {Component} from '@angular/core'; import {TuiAppearance} from '@taiga-ui/core'; import {TuiCardLarge} from '@taiga-ui/layout'; // ... @Component({ standalone: true, imports: [ // ... TuiAppearance, TuiCardLarge, ], }) export class Example {} ``` ### How to Use (Template) ```html

Header

``` ### Usage Examples #### Basic **Template:** ```html

Desktop

Header

Replace me

Header

Replace me

iOS/Android

Header

Replace me

Header

Replace me
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiPlatform} from '@taiga-ui/cdk'; import {TuiAppearance, TuiButton, TuiLink, TuiTitle} from '@taiga-ui/core'; import {TuiBadge} from '@taiga-ui/kit'; import {TuiCardLarge, TuiHeader} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ TuiAppearance, TuiBadge, TuiButton, TuiCardLarge, TuiHeader, TuiLink, TuiPlatform, TuiTitle, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Image **Template:** ```html

Title Subtitle

Title Subtitle

``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiButton, TuiTitle} from '@taiga-ui/core'; import {TuiButtonClose} from '@taiga-ui/kit'; import {TuiCardLarge, TuiHeader} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [TuiButton, TuiButtonClose, TuiCardLarge, TuiHeader, TuiTitle], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Cell with close **Template:** ```html

iOS/Android

Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit.
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiPlatform} from '@taiga-ui/cdk'; import {TuiAppearance, TuiButton, TuiTitle} from '@taiga-ui/core'; import {TuiAvatar, TuiButtonClose, TuiFade} from '@taiga-ui/kit'; import {TuiCardLarge, TuiCell, TuiHeader} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ TuiAppearance, TuiAvatar, TuiButton, TuiButtonClose, TuiCardLarge, TuiCell, TuiFade, TuiHeader, TuiPlatform, TuiTitle, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Paddings and radii **Template:** ```html

Desktop

Normal Radius: 24, padding: 24

Compact Radius: 16, padding: 20

iOS/Android

Normal Radius: 24, padding: 20

Compact Radius: 16, padding: 16

``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiPlatform} from '@taiga-ui/cdk'; import {TuiAppearance, TuiButton, TuiTitle} from '@taiga-ui/core'; import {TuiCardLarge, TuiHeader} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [TuiAppearance, TuiButton, TuiCardLarge, TuiHeader, TuiPlatform, TuiTitle], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example {} ``` #### Map **Template:** ```html

Title Subtitle

``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAppearance, TuiButton, TuiTitle} from '@taiga-ui/core'; import {TuiCardLarge, TuiHeader} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [TuiAppearance, TuiButton, TuiCardLarge, TuiHeader, TuiTitle], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example {} ``` #### In portal **Template:** ```html

Leave your feedback It will only take 3 minutes

Why so?

``` **TypeScript:** ```ts import {NgIf} from '@angular/common'; import {Component, signal} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAnimated, TuiAutoFocus} from '@taiga-ui/cdk'; import {TuiAppearance, TuiButton, TuiPopup, TuiTextfield, TuiTitle} from '@taiga-ui/core'; import {TuiRating, TuiTextarea} from '@taiga-ui/kit'; import {TuiCardLarge} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ FormsModule, NgIf, TuiAnimated, TuiAppearance, TuiAutoFocus, TuiButton, TuiCardLarge, TuiPopup, TuiRating, TuiTextarea, TuiTextfield, TuiTitle, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly step = signal(0); protected rating = 0; protected comment = ''; protected close(): void { this.rating = 0; this.comment = ''; this.step.set(0); } } ``` #### Avatar **Template:** ```html

Desktop

Title Subtitle

iOS/Android

Title Subtitle

``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiPlatform} from '@taiga-ui/cdk'; import {TuiAppearance, TuiButton, TuiTitle} from '@taiga-ui/core'; import {TuiAvatar} from '@taiga-ui/kit'; import {TuiCardLarge, TuiHeader} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ TuiAppearance, TuiAvatar, TuiButton, TuiCardLarge, TuiHeader, TuiPlatform, TuiTitle, ], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example {} ``` #### Single item **Template:** ```html
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAppearance, TuiIcon, TuiSurface, TuiTitle} from '@taiga-ui/core'; import {TuiAvatar} from '@taiga-ui/kit'; import {TuiCardLarge, TuiCell, TuiHeader} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ TuiAppearance, TuiAvatar, TuiCardLarge, TuiCell, TuiHeader, TuiIcon, TuiSurface, TuiTitle, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Cards List **Template:** ```html

Title Subtitle

Title Subtitle

``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiRepeatTimes} from '@taiga-ui/cdk'; import {TuiAppearance, TuiButton, TuiIcon, TuiTitle} from '@taiga-ui/core'; import {TuiCardLarge, TuiCardMedium, TuiHeader} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ TuiAppearance, TuiButton, TuiCardLarge, TuiCardMedium, TuiHeader, TuiIcon, TuiRepeatTimes, TuiTitle, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Cell List **Template:** ```html

Title Subtitle

Title
Description
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiRepeatTimes} from '@taiga-ui/cdk'; import {TuiAppearance, TuiButton, TuiTitle} from '@taiga-ui/core'; import {TuiAvatar} from '@taiga-ui/kit'; import {TuiCardLarge, TuiCell, TuiHeader} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ TuiAppearance, TuiAvatar, TuiButton, TuiCardLarge, TuiCell, TuiHeader, TuiRepeatTimes, TuiTitle, ], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example {} ``` #### Cell List (2 columns) **Template:** ```html

Title Subtitle

Title
Description
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiRepeatTimes} from '@taiga-ui/cdk'; import {TuiAppearance, TuiButton, TuiTitle} from '@taiga-ui/core'; import {TuiAvatar} from '@taiga-ui/kit'; import {TuiCardLarge, TuiCell, TuiHeader} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ TuiAppearance, TuiAvatar, TuiButton, TuiCardLarge, TuiCell, TuiHeader, TuiRepeatTimes, TuiTitle, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Cell List (actions) **Template:** ```html

Title Subtitle

``` **TypeScript:** ```ts import {NgForOf} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiRepeatTimes} from '@taiga-ui/cdk'; import { TuiAppearance, TuiDataList, TuiDropdown, TuiIcon, TuiLink, TuiTitle, } from '@taiga-ui/core'; import {TuiAvatar} from '@taiga-ui/kit'; import {TuiCardLarge, TuiCell, TuiHeader} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ NgForOf, TuiAppearance, TuiAvatar, TuiCardLarge, TuiCell, TuiDataList, TuiDropdown, TuiHeader, TuiIcon, TuiLink, TuiRepeatTimes, TuiTitle, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Cell List (headless) **Template:** ```html
Title
Description
Title
Description
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiRepeatTimes} from '@taiga-ui/cdk'; import {TuiAppearance, TuiButton, TuiTitle} from '@taiga-ui/core'; import {TuiAvatar} from '@taiga-ui/kit'; import {TuiCardLarge, TuiCell} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ TuiAppearance, TuiAvatar, TuiButton, TuiCardLarge, TuiCell, TuiRepeatTimes, TuiTitle, ], templateUrl: './index.html', styles: [':host { display: flex; flex-direction: column; gap: 2rem}'], encapsulation, changeDetection, }) export default class Example {} ``` #### Footer alignment **Template:** ```html

Title

Title
Description

Title

Some text
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAppearance, TuiButton, TuiTitle} from '@taiga-ui/core'; import {TuiAvatar} from '@taiga-ui/kit'; import {TuiCardLarge, TuiCell, TuiHeader} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ TuiAppearance, TuiAvatar, TuiButton, TuiCardLarge, TuiCell, TuiHeader, TuiTitle, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; @Component({ standalone: true, imports: [TuiDemo], templateUrl: './index.html', changeDetection, }) export default class Example { protected readonly examples = [ 'Basic', 'Avatar', 'Single item', 'Cards List', 'Cell List', 'Cell List (2 columns)', 'Cell List (actions)', 'Cell List (headless)', 'Footer alignment', 'Image', 'Cell with close', 'Paddings and radii', 'Map', 'In portal', ]; } ``` --- # components/CardMedium - **Package**: `LAYOUT` - **Type**: components A layout component used to create various cards for the interface. Define visual styles of the cards yourself or combine with Surface for visual presets. ### How to Use (Import) ```ts import {Component} from '@angular/core'; import {TuiCardMedium} from '@taiga-ui/layout'; // ... @Component({ standalone: true, imports: [ // ... TuiCardMedium, ], }) export class Example {} ``` ### How to Use (Template) ```html

Title Subtitle

``` ### Usage Examples #### Avatar and text **Template:** ```html

Title Subtitle

Title Subtitle

Title Subtitle

``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAppearance, TuiTitle} from '@taiga-ui/core'; import {TuiAvatar} from '@taiga-ui/kit'; import {TuiCardMedium} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [TuiAppearance, TuiAvatar, TuiCardMedium, TuiTitle], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Icon **Template:** ```html

Title Subtitle

Title Subtitle

``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAppearance, TuiIcon, TuiTitle} from '@taiga-ui/core'; import {TuiCardMedium} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [TuiAppearance, TuiCardMedium, TuiIcon, TuiTitle], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Badge **Template:** ```html
10 %

Title Subtitle

Title Subtitle

10 %
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAppearance, TuiIcon, TuiTitle} from '@taiga-ui/core'; import {TuiBadge} from '@taiga-ui/kit'; import {TuiCardMedium} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [TuiAppearance, TuiBadge, TuiCardMedium, TuiIcon, TuiTitle], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Stacking **Template:** ```html

Title Subtitle

Title Subtitle

``` **TypeScript:** ```ts import {AsyncPipe, NgForOf} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import { TuiAppearance, TuiAutoColorPipe, TuiFallbackSrcPipe, TuiTitle, } from '@taiga-ui/core'; import {TuiAvatar, TuiAvatarStack} from '@taiga-ui/kit'; import {TuiCardMedium} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ AsyncPipe, NgForOf, TuiAppearance, TuiAutoColorPipe, TuiAvatar, TuiAvatarStack, TuiCardMedium, TuiFallbackSrcPipe, TuiTitle, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly urls = [ 'https://avatars.githubusercontent.com/u/11832552', 'https://avatars.githubusercontent.com/u/10106368', 'https://avatars.githubusercontent.com/u/46284632', ]; } ``` #### Customization **Template:** ```html

Poster Cinema, concerts, theaters and sports up to 25%

10%

Flights

10%

Google -2.7%

$3,605.2

Microsoft -12.44%

$1,095.3
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiIcon, TuiSurface, TuiTitle} from '@taiga-ui/core'; import {TuiBadge} from '@taiga-ui/kit'; import {TuiCardMedium} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [TuiBadge, TuiCardMedium, TuiIcon, TuiSurface, TuiTitle], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Long text **Template:** ```html
Lorem Ipsum is simply dummy text of the printing and typesetting industry. It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text.
Text without fade out when overflow content
It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text.
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAppearance, TuiHint, TuiTitle} from '@taiga-ui/core'; import {TuiFade} from '@taiga-ui/kit'; import {TuiCardMedium} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [TuiAppearance, TuiCardMedium, TuiFade, TuiHint, TuiTitle], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Selectable **Template:** ```html ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiThumbnailCard} from '@taiga-ui/addon-commerce'; import {TuiRipple} from '@taiga-ui/addon-mobile'; import {TuiSurface} from '@taiga-ui/core'; import {TuiFade} from '@taiga-ui/kit'; import {TuiCardMedium} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ FormsModule, TuiCardMedium, TuiFade, TuiRipple, TuiSurface, TuiThumbnailCard, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected value = 0; } ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {DemoRoute} from '@demo/routes'; import {TuiDemo} from '@demo/utils'; @Component({ standalone: true, imports: [TuiDemo], templateUrl: './index.html', changeDetection, }) export default class Example { protected readonly examples = [ 'Avatar and text', 'Icon', 'Badge', 'Stacking', 'Customization', 'Long text', 'Selectable', ]; protected readonly surface = DemoRoute.Surface; } ``` --- # components/Carousel - **Package**: `KIT` - **Type**: components Carousel allows you to rotate through arbitrary items. Multiple items can be shown simultaneously. ### How to Use (Import) ```ts import {TuiCarousel} from '@taiga-ui/kit'; // ... @Component({ standalone: true, imports: [ // ... TuiCarousel, ], // ... }) export class Example {} ``` ### How to Use (Template) ```html
Slide 1
Slide 2
Slide 3
``` ### Example ```html
{{ item }}
``` ### API | Property | Type | Description | |----------|-----|----------| | [draggable] | `boolean` | Whether or not slider can be dragged by clicking and holding | | [duration] | `number` | Duration in milliseconds for each slide for automatic rotation (use 0 to disable automatic rotation) | | [itemsCount] | `number` | Number of slides shown at the same time | | [(index)] | `number` | Current index | ### Usage Examples #### Single **Template:** ```html

{{ item }}

Wiki
``` **TypeScript:** ```ts import {NgFor} from '@angular/common'; import {Component, inject} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiButton} from '@taiga-ui/core'; import {TuiCarousel, TuiPagination} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [NgFor, TuiButton, TuiCarousel, TuiPagination], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected index = 2; protected readonly items = inject('Pythons' as any); } ``` #### Multiple **Template:** ```html ``` **TypeScript:** ```ts import {NgFor} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiCarousel} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [NgFor, TuiCarousel], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected index = 0; protected readonly items = [ 'angular.svg', 'avatar.jpg', 'angular.svg', 'avatar.jpg', 'angular.svg', 'avatar.jpg', ]; } ``` #### Custom **Template:** ```html

Monty Python and the Holy Grail

King Arthur and his Knights of the Round Table embark on a surreal, low-budget search for the Holy Grail, encountering many, very silly obstacles.

Failed to load

``` **TypeScript:** ```ts import {AsyncPipe} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAmountPipe} from '@taiga-ui/addon-commerce'; import {TuiButton, TuiLoader} from '@taiga-ui/core'; import {TuiAvatar, TuiCarousel} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [AsyncPipe, TuiAmountPipe, TuiAvatar, TuiButton, TuiCarousel, TuiLoader], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Carousel inside dialog **Template:** ```html

Carousel is awesome

It can show arbitrary content and it's very easy to control

Pagination

You can use Pagination component with size 's' together with it

Buttons

Use tuiCarouselButtons directive to setup navigation buttons

``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {RouterLink} from '@angular/router'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {DemoRoute} from '@demo/routes'; import {TuiButton, TuiDialog, TuiLink} from '@taiga-ui/core'; import {TuiCarousel, TuiPagination} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [RouterLink, TuiButton, TuiCarousel, TuiDialog, TuiLink, TuiPagination], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly routes = DemoRoute; protected open = false; protected index = 0; protected get background(): string { switch (this.index) { case 0: return 'url(https://cdn.tvc.ru/pictures/mood/bw/194/22.jpg)'; case 1: return 'url(https://ic.pics.livejournal.com/ruhtal/6943012/12468/12468_900.jpg)'; default: return 'url(https://cdn.motor1.com/images/mgl/28bxz/s1/ford-carousel.jpg)'; } } protected onClick(): void { this.index = 0; this.open = true; } protected navigate(delta: number): void { this.index = (this.index + delta) % 3; } } ``` #### Vertical alignment **Template:** ```html

{{ item.title }}

{{ item.content }}
``` **TypeScript:** ```ts import {NgFor} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiCarousel, TuiPagination} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [NgFor, TuiCarousel, TuiPagination], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected index = 0; protected readonly itemsCount = 3; protected readonly items = [ {title: 'First', content: 'First content'}, {title: 'Title #2', content: 'Much more content here so the height is bigger'}, {title: 'Title III', content: 'Small item again'}, {title: 'Title four', content: 'Relatively ling content here'}, {title: 'Fifth item', content: 'Tiny text'}, {title: '6', content: "That one's short too"}, {title: 'Lucky 7', content: 'This takes about two lines or so'}, {title: 'Eighth card', content: 'Almost the last one'}, {title: 'X', content: 'This is the longest item there is in this list'}, ]; protected get rounded(): number { return Math.floor(this.index / this.itemsCount); } protected onIndex(index: number): void { this.index = index * this.itemsCount; } } ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; import {TuiRepeatTimes} from '@taiga-ui/cdk'; import {TuiButton} from '@taiga-ui/core'; import {TuiCarousel} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiButton, TuiCarousel, TuiDemo, TuiRepeatTimes], templateUrl: './index.html', styleUrls: ['./index.less'], changeDetection, }) export default class Example { protected readonly examples = [ 'Single', 'Multiple', 'Custom', 'Carousel inside dialog', 'Vertical alignment', ]; protected readonly durationVariants = [0, 3000, 10000]; protected readonly itemPaddingVariants = [null, '0 10px', '0']; protected draggable = false; protected duration = this.durationVariants[0]!; protected itemPadding: string | null = this.itemPaddingVariants[0]!; protected index = 0; protected itemsCount = 1; } ``` ### LESS ```less @import '@taiga-ui/core/styles/taiga-ui-local'; .carousel { margin: 0 2.5rem; border: 1px solid var(--tui-background-accent-1); } .plate { display: flex; font: var(--tui-font-heading-3); flex-direction: column; align-items: flex-start; inline-size: 100%; block-size: 7.5rem; padding: 1.75rem; box-sizing: border-box; background: var(--tui-background-neutral-1); } .button { margin-block-start: 0.5rem; } ``` --- # components/Cell - **Package**: `LAYOUT` - **Type**: components ### How to Use (Import) ```ts import {Component} from '@angular/core'; import {TuiCell} from '@taiga-ui/layout'; // ... @Component({ imports: [ // ... TuiCell, ], }) export class Example {} ``` ### How to Use (Template) ```html
Title
Subtitle
``` ### Example ```html
Title
Description
Secondary title
Another description
``` ### API | Property | Type | Description | |----------|-----|----------| | [tuiCell] | `'l' | 'm' | 's'` | Layout size | | [tuiCellHeight] | `'normal' | 'compact' | 'spacious'` | Height mode | ### Usage Examples #### Basic **Template:** ```html
Title
Description
Secondary title
Another description
``` **TypeScript:** ```ts import {NgFor} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiTitle} from '@taiga-ui/core'; import {TuiAvatar} from '@taiga-ui/kit'; import {TuiCell} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [NgFor, TuiAvatar, TuiCell, TuiTitle], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly sizes = ['s', 'm', 'l'] as const; } ``` #### Label **Template:** ```html ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiIcon, TuiTitle} from '@taiga-ui/core'; import {TuiAvatar, TuiBadge, TuiBadgedContent, TuiSwitch} from '@taiga-ui/kit'; import {TuiCell} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ FormsModule, TuiAvatar, TuiBadge, TuiBadgedContent, TuiCell, TuiIcon, TuiSwitch, TuiTitle, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected incoming = false; protected outgoing = true; } ``` #### Left side **Template:** ```html
$30 our of $100
Saving for a Benjamin Franklin portrait
+$30
 
+2
Waterplea
100 ₽ Music
Buy
1234
Primary Card
**** **** **** 1234
Poster
Ridley Scott, 1982
Blade Runner
A blade runner must pursue and terminate four replicants who stole a ship in space and have returned to Earth to find their creator.
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiThumbnailCard} from '@taiga-ui/addon-commerce'; import {TuiIcon, TuiLink, TuiTitle} from '@taiga-ui/core'; import { TuiAvatar, TuiAvatarStack, TuiBadge, TuiCheckbox, TuiProgress, } from '@taiga-ui/kit'; import {TuiCell} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ FormsModule, TuiAvatar, TuiAvatarStack, TuiBadge, TuiCell, TuiCheckbox, TuiIcon, TuiLink, TuiProgress, TuiThumbnailCard, TuiTitle, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected value = false; } ``` #### Right side **Template:** ```html
Notifications
3
Read
Salary
Enough
Sky's the limit
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiIcon, TuiLoader, TuiTitle} from '@taiga-ui/core'; import { TuiAvatar, TuiBadgeNotification, TuiCheckbox, TuiSensitive, TuiTooltip, } from '@taiga-ui/kit'; import {TuiCell} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ FormsModule, TuiAvatar, TuiBadgeNotification, TuiCell, TuiCheckbox, TuiIcon, TuiLoader, TuiSensitive, TuiTitle, TuiTooltip, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected value = false; } ``` #### Long content **Template:** ```html
Long title in a cell will wrap to multiple lines and so will the subtitle
Use tuiAccessories to keep your side content properly aligned if you have many lines of text
Alternatively you can use fade to hide extra text using nowrap CSS
Works the same for subtitle when fade directive is applied to the top
Works with the right side
Works with fade on both sides
You can control proportions
Proportions are controlled with flex
Flex shrink is set to 70-30 by default
Alexander
Taiga UI developer
+$1000
Bonus for tuiCell component
Awesome!
Main account
USD
By default unless arrested
$123 456
Careful, content may overlap
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiIcon, TuiTitle} from '@taiga-ui/core'; import {TuiAvatar, TuiBadge, TuiBadgeNotification, TuiFade} from '@taiga-ui/kit'; import {TuiCell} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ TuiAvatar, TuiBadge, TuiBadgeNotification, TuiCell, TuiFade, TuiIcon, TuiTitle, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Actions **Template:** ```html
Single action
Description of the action
Multiple actions
With no content on the right
Hover over
Put it before the right side
``` **TypeScript:** ```ts import {NgFor} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiButton, TuiDropdown, TuiGroup, TuiTitle} from '@taiga-ui/core'; import {TuiDataListWrapper} from '@taiga-ui/kit'; import {TuiCell} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ NgFor, TuiButton, TuiCell, TuiDataListWrapper, TuiDropdown, TuiGroup, TuiTitle, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly items = [ { icon: '@tui.phone', toString: () => 'Call now', }, { icon: '@tui.star', toString: () => 'Add to favorites', }, { icon: '@tui.trash', toString: () => 'Remove item', }, ]; } ``` #### Combinations **Template:** ```html Don't forget import TuiCardLarge

Inside a block

``` **TypeScript:** ```ts import {NgFor} from '@angular/common'; import {Component} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAppearance, TuiNotification, TuiTextfield, TuiTitle} from '@taiga-ui/core'; import {TuiAvatar, TuiChevron, TuiDataListWrapper, TuiSelect} from '@taiga-ui/kit'; import {TuiCardLarge, TuiCell} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ FormsModule, NgFor, TuiAppearance, TuiAvatar, TuiCardLarge, TuiCell, TuiChevron, TuiDataListWrapper, TuiNotification, TuiSelect, TuiTextfield, TuiTitle, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly items = [ { icon: '@tui.eye', title: 'Show more', subtitle: 'Ctrl + Shift + M', }, { icon: '@tui.mail', title: 'Send message', subtitle: 'Keep it short', }, { icon: '@tui.lock', title: 'Access', subtitle: 'Block your account', }, ]; protected value = this.items[0]!; } ``` #### Connected **Template:** ```html Can be attached as host directive: hostDirectives: [TuiConnected]

Inside a block

``` **TypeScript:** ```ts import {NgFor} from '@angular/common'; import {Component} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAppearance, TuiIcon, TuiNotification, TuiTitle} from '@taiga-ui/core'; import { TuiAvatar, TuiBadge, TuiBadgedContent, TuiConnected, TuiDataListWrapper, TuiSwitch, } from '@taiga-ui/kit'; import {TuiCardLarge, TuiCell} from '@taiga-ui/layout'; import {TuiSelectModule, TuiTextfieldControllerModule} from '@taiga-ui/legacy'; @Component({ standalone: true, imports: [ FormsModule, NgFor, TuiAppearance, TuiAvatar, TuiBadge, TuiBadgedContent, TuiCardLarge, TuiCell, TuiConnected, TuiDataListWrapper, TuiIcon, TuiNotification, TuiSelectModule, TuiSwitch, TuiTextfieldControllerModule, TuiTitle, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly items = [ { icon: '@tui.eye', title: 'Show more', subtitle: 'Ctrl + Shift + M', }, { icon: '@tui.mail', title: 'Send message', subtitle: 'Allow outgoing unusual call that can change your life in an unusual way', }, { icon: '@tui.lock', title: 'Access', subtitle: 'Block your account', }, ]; protected value = this.items[0]!; protected incoming = false; protected outgoing = true; } ``` #### Disabled state **Template:** ```html
Hover over
Put it before the right side
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAppearance, TuiButton, TuiIcon, TuiLoader, TuiTitle} from '@taiga-ui/core'; import {TuiBadgeNotification, TuiCheckbox, TuiTooltip} from '@taiga-ui/kit'; import {TuiCell} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ FormsModule, TuiAppearance, TuiBadgeNotification, TuiButton, TuiCell, TuiCheckbox, TuiIcon, TuiLoader, TuiTitle, TuiTooltip, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected value = false; } ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; import {tuiDocExampleOptionsProvider} from '@taiga-ui/addon-doc'; import {TuiTitle} from '@taiga-ui/core'; import {TuiAvatar} from '@taiga-ui/kit'; import {TuiCell, type TuiCellOptions} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [TuiAvatar, TuiCell, TuiDemo, TuiTitle], templateUrl: './index.html', styleUrls: ['./index.less'], changeDetection, providers: [tuiDocExampleOptionsProvider({fullsize: true})], }) export default class Example { protected sizes = ['l', 'm', 's'] as const; protected size: TuiCellOptions['size'] = this.sizes[0]; protected heights = ['normal', 'compact', 'spacious'] as const; protected height: TuiCellOptions['height'] = this.heights[0]; protected readonly examples = [ 'Basic', 'Label', 'Left side', 'Right side', 'Long content', 'Actions', 'Combinations', 'Connected', 'Disabled state', ]; } ``` ### LESS ```less :host { tui-doc-demo::ng-deep .t-content { background: var(--tui-background-neutral-1); } [tuiCell] { background: var(--tui-background-elevation-1); } } ``` --- # components/Checkbox - **Package**: `KIT` - **Type**: components A checkbox component that is able to imitate native control on mobile platforms. Use --tui-background-accent-2 CSS variable to customize color of native control emulation ### How to Use (Import) ```ts import {Component} from '@angular/core'; import {TuiCheckbox} from '@taiga-ui/kit'; // ... @Component({ standalone: true, imports: [ // ... TuiCheckbox, ], }) export class Example {} ``` ### How to Use (Template) ```html ``` ### Usage Examples #### Platforms Add import of @taiga-ui/addon-mobile/styles/taiga-ui-mobile.less to your encapsulated global styles to enable power of TuiPlatform directive. **Template:** ```html
{{ platform }}
``` **TypeScript:** ```ts import {NgForOf} from '@angular/common'; import {Component, type OnInit} from '@angular/core'; import {FormControl, FormsModule, ReactiveFormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiPlatform} from '@taiga-ui/cdk'; import {type TuiSizeS} from '@taiga-ui/core'; import {TuiCheckbox} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [FormsModule, NgForOf, ReactiveFormsModule, TuiCheckbox, TuiPlatform], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example implements OnInit { protected readonly platforms: ReadonlyArray<'android' | 'ios' | 'web'> = [ 'web', 'web', 'ios', 'android', ]; protected readonly invalidTrue = new FormControl(true, () => ({invalid: true})); protected readonly invalidFalse = new FormControl(false, () => ({invalid: true})); public ngOnInit(): void { this.invalidTrue.markAsTouched(); this.invalidFalse.markAsTouched(); } protected getSize(first: boolean): TuiSizeS { return first ? 'm' : 's'; } } ``` #### Decorative **Template:** ```html

``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiButton} from '@taiga-ui/core'; import {TuiCheckbox} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiButton, TuiCheckbox], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected checked = false; } ``` #### Form **Template:** ```html

{{ currentQuestion + 1 }}. {{ questionTitles[currentQuestion] }}

Your answers

{{ i + 1 }}. {{ questionTitles[i] }}

``` **TypeScript:** ```ts import {NgForOf, NgIf} from '@angular/common'; import {Component} from '@angular/core'; import {FormControl, FormGroup, FormsModule, ReactiveFormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiButton} from '@taiga-ui/core'; import {TuiCheckbox} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [FormsModule, NgForOf, NgIf, ReactiveFormsModule, TuiButton, TuiCheckbox], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly questionTitles = [ 'What framework do you like?', 'What library do you like?', ]; protected readonly questions = [ ['Angular', 'React', 'Vue'], ['Taiga UI', 'Material UI', 'PrimeNG'], ]; protected currentQuestion = 0; protected results: boolean[][] = []; protected form = new FormGroup({ 0: new FormControl(false), 1: new FormControl(false), 2: new FormControl(false), }); protected nextQuestion(): void { this.currentQuestion++; this.results.push(Object.values(this.form.value).map(Boolean)); this.form = new FormGroup({ 0: new FormControl(false), 1: new FormControl(false), 2: new FormControl(false), }); } } ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; @Component({ standalone: true, imports: [TuiDemo], templateUrl: './index.html', changeDetection, }) export default class Page {} ``` --- # components/Chip - **Package**: `KIT` - **Type**: components Chip component is used to display array data and can also be interactive depending on the tag used. ### How to Use (Import) ```ts import {Component} from '@angular/core'; import {TuiChip} from '@taiga-ui/kit'; // ... @Component({ imports: [ // ... TuiChip, ], }) export class Example {} ``` ### How to Use (Template) ```html {{ value }} ``` ### Example ```html Chip ``` ### API | Property | Type | Description | |----------|-----|----------| | [size] | `TuiSizeXS | TuiSizeL` | Size of the chip | ### Usage Examples #### Basic **Template:** ```html Default appearance is Neutral Primary Accent Positive Negative Warning Info Outline Floating ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiChip} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiChip], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Sizes and content **Template:** ```html
Text
Single icon
Duo icon
Avatar Image
Avatar
Button Button
Badge 1
``` **TypeScript:** ```ts import {NgForOf, NgIf, SlicePipe} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiButton} from '@taiga-ui/core'; import {TuiAvatar, TuiBadge, TuiChip} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [NgForOf, NgIf, SlicePipe, TuiAvatar, TuiBadge, TuiButton, TuiChip], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly sizes = ['m', 's', 'xs', 'xxs'] as const; } ``` #### Interactive **Template:** ```html

Checkbox

Radio

Label outline

Label accent

Button

Close button {{ i + 1 }}

Input

{{ values[i] }}
``` **TypeScript:** ```ts import {Component, inject} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiRepeatTimes} from '@taiga-ui/cdk'; import {TuiAlertService, TuiButton} from '@taiga-ui/core'; import {TuiCheckbox, TuiChip} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [FormsModule, TuiButton, TuiCheckbox, TuiChip, TuiRepeatTimes], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { private readonly alerts = inject(TuiAlertService); protected readonly checked = [true, false, true]; protected readonly values = ['test', 'Some text', 'WOW!']; protected onChip(index: number): void { this.alerts.open(`Clicked chip ${index + 1}`).subscribe(); } protected onX(index: number): void { this.alerts .open(`Removed chip ${index + 1}`, {appearance: 'negative'}) .subscribe(); } } ``` #### Use cases **Template:** ```html
Very long value in chip
{{ 123000 | tuiAmount: 'RUB' | async }}
Very long value in chip
Notifications Customized chip Toggle chip ``` **TypeScript:** ```ts import {AsyncPipe} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAmountPipe} from '@taiga-ui/addon-commerce'; import {TuiButton} from '@taiga-ui/core'; import {TuiBadgedContent, TuiBadgeNotification, TuiChip, TuiFade} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [ AsyncPipe, TuiAmountPipe, TuiBadgedContent, TuiBadgeNotification, TuiButton, TuiChip, TuiFade, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected selected = false; } ``` #### Auto color **Template:** ```html {{ chip }} ``` **TypeScript:** ```ts import {NgForOf} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAutoColorPipe} from '@taiga-ui/core'; import {TuiChip} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [NgForOf, TuiAutoColorPipe, TuiChip], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected chips = [ 'Free', 'Base', 'Pro', 'Enterprise', 'Premium', 'Ultimate', 'Starter', 'Advanced', 'Business', 'Enterprise', 'Personal', 'Standard', 'Essential', 'Professional', 'Deluxe', 'Gold', 'Silver', 'Bronze', 'Plus', 'Basic', ]; } ``` #### Fade in complex designs **Template:** ```html
Supermarkets
{{ 9000 | tuiAmount: 'USD' | async }}
AI
{{ 9870043000 | tuiAmount: 'USD' | async }}
Long category name

Use CSS to set a custom priority for the fade:

Miscellaneous goods
{{ 105000 | tuiAmount: 'USD' | async }}
``` **TypeScript:** ```ts import {AsyncPipe} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAmountPipe} from '@taiga-ui/addon-commerce'; import {TuiAvatar, TuiChip, TuiFade} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [AsyncPipe, TuiAmountPipe, TuiAvatar, TuiChip, TuiFade], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {TuiDocAppearance} from '@demo/components/appearance'; import {TuiDocIcons} from '@demo/components/icons'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; import {type TuiSizeXXS} from '@taiga-ui/core'; import {TuiChip} from '@taiga-ui/kit'; @Component({ standalone: true, selector: 'example-chip', imports: [TuiChip, TuiDemo, TuiDocAppearance, TuiDocIcons], templateUrl: './index.html', changeDetection, }) export default class Example { protected readonly examples = [ 'Basic', 'Sizes and content', 'Interactive', 'Use cases', 'Auto color', 'Fade in complex designs', ]; protected readonly sizes: readonly TuiSizeXXS[] = ['xxs', 'xs', 's', 'm']; protected size = this.sizes[2]!; } ``` --- # components/ComboBox - **Package**: `KIT` - **Type**: components ComboBox is a form control for selecting a single value from a set of options. It is similar to Select but with a major difference – possibility to enter value manually . ### How to Use (Import) ```ts import {FormsModule} from '@angular/forms'; import {TuiTextfield} from '@taiga-ui/core'; import {TuiChevron, TuiComboBox} from '@taiga-ui/kit'; @Component({ imports: [ // ... FormsModule, TuiTextfield, TuiChevron, TuiComboBox, ], }) export class Example { items = ['Option 1', 'Option 2', 'Option 3']; value: string | null = null; } ``` ### How to Use (Template) ```html ``` ### Example ```html ``` ### API | Property | Type | Description | |----------|-----|----------| | [strict] | `boolean` | | | [matcher] | `TuiStringMatcher | null` | function that compares search text and datalist's items to define a match between them. Lowercase string comparison function by default. | | [content] | `PolymorpheusContent` | | ### Usage Examples #### Basic The main helper you’ll use with almost every ComboBox is the tuiFilterByInput pipe. It enables item filtering based on the user’s input as they type. **Template:** ```html ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiTextfield} from '@taiga-ui/core'; import { TuiChevron, TuiComboBox, TuiDataListWrapper, TuiFilterByInputPipe, } from '@taiga-ui/kit'; @Component({ standalone: true, imports: [ FormsModule, TuiChevron, TuiComboBox, TuiDataListWrapper, TuiFilterByInputPipe, TuiTextfield, ], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected readonly items = [ 'Darth Vader', 'Luke Skywalker', 'Princess Leia', 'Han Solo', 'Obi-Wan Kenobi', 'Yoda', ] as const; protected value: string | null = this.items[0]; } ``` #### Virtual scroll You can use ComboBox with virtual scrolling from @angular/cdk/scrolling . **Template:** ```html ``` **TypeScript:** ```ts import {ScrollingModule} from '@angular/cdk/scrolling'; import {AsyncPipe} from '@angular/common'; import {Component, inject} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiLet} from '@taiga-ui/cdk'; import {TuiDataList, TuiScrollable, TuiTextfield} from '@taiga-ui/core'; import { TUI_COUNTRIES, TuiChevron, TuiComboBox, TuiFilterByInputPipe, } from '@taiga-ui/kit'; import {map, type Observable} from 'rxjs'; @Component({ standalone: true, imports: [ AsyncPipe, FormsModule, ScrollingModule, TuiChevron, TuiComboBox, TuiDataList, TuiFilterByInputPipe, TuiLet, TuiScrollable, TuiTextfield, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly countries$: Observable = inject(TUI_COUNTRIES).pipe( map(Object.values), ); protected value = null; } ``` #### With DropdownMobile Use real mobile device or enable mobile emulation in DevTools to explore this example! Put tuiDropdownMobile on <tui-textfield /> to enable a full-screen dialog instead of the default dropdown on mobile devices. By default, the full-screen dialog hides all other content using visibility: hidden and shifts the textfield to the top of the page. Use --tui-dropdown-mobile-offset css-variable option to control how far the textfield is shifted. If needed, manually set visibility: visible on any hidden elements (e.g., a sticky header) to make them visible again. **Template:** ```html ``` **TypeScript:** ```ts import {AsyncPipe} from '@angular/common'; import {Component, inject, ViewEncapsulation} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDropdownMobile} from '@taiga-ui/addon-mobile'; import {TuiTextfield} from '@taiga-ui/core'; import { TUI_COUNTRIES, TuiChevron, TuiComboBox, TuiDataListWrapper, TuiFilterByInputPipe, } from '@taiga-ui/kit'; import {map, type Observable} from 'rxjs'; @Component({ standalone: true, imports: [ AsyncPipe, FormsModule, TuiChevron, TuiComboBox, TuiDataListWrapper, TuiDropdownMobile, TuiFilterByInputPipe, TuiTextfield, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation: ViewEncapsulation.None, changeDetection, }) export default class Example { protected readonly countries$: Observable = inject(TUI_COUNTRIES).pipe( map(Object.values), ); protected value: string | null = null; } ``` #### Override option component You can override default behavior and appearance of all options inside dropdown. Just provide your custom component by tuiAsOptionContent -utility. Double check if you really need this feature! For the most cases <tui-data-list-wrapper [itemContent]="..." /> can be enough for your task. Explore this example for more details. **Template:** ```html ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {FormControl, ReactiveFormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {tuiAsOptionContent, TuiTextfield} from '@taiga-ui/core'; import { TuiChevron, TuiComboBox, TuiDataListWrapper, TuiFilterByInputPipe, } from '@taiga-ui/kit'; import {Option} from './option'; @Component({ standalone: true, imports: [ ReactiveFormsModule, TuiChevron, TuiComboBox, TuiDataListWrapper, TuiFilterByInputPipe, TuiTextfield, ], templateUrl: './index.html', encapsulation, changeDetection, providers: [tuiAsOptionContent(Option)], }) export default class Example { protected readonly items = new Array(5) .fill(null) .map((_, index) => `Option ${index + 1}`); protected readonly control = new FormControl(this.items[2]!); } ``` #### Non-strict mode By default, strict mode is enabled. This means the input value must match one of the options from the data list. If the value doesn't match, the form control is not updated and the input is cleared on blur. In non-strict mode, the form control can contain any value — even if it doesn’t match any item in the data list. **Template:** ```html

Form control: {{ control.value | json }}

``` **TypeScript:** ```ts import {JsonPipe} from '@angular/common'; import {Component} from '@angular/core'; import {FormControl, ReactiveFormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiTextfield} from '@taiga-ui/core'; import {TuiChevron, TuiComboBox, TuiDataListWrapper} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [ JsonPipe, ReactiveFormsModule, TuiChevron, TuiComboBox, TuiDataListWrapper, TuiTextfield, ], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected readonly items = [ 'Medical Expenses', 'Education', 'Travel', 'Home Repair', 'Car', ]; protected control = new FormControl(null); } ``` #### Client-side filtering You can configure any filtering logic by passing a custom matcher function as an argument to the tuiFilterByInput pipe. **Template:** ```html ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {type TuiStringMatcher} from '@taiga-ui/cdk'; import {TuiTextfield} from '@taiga-ui/core'; import { TuiChevron, TuiComboBox, TuiDataListWrapper, TuiFilterByInputPipe, } from '@taiga-ui/kit'; const ROMAN_TO_LATIN: Record = { I: '1', II: '2', III: '3', IV: '4', V: '5', VI: '6', VII: '7', VIII: '8', }; @Component({ standalone: true, imports: [ FormsModule, TuiChevron, TuiComboBox, TuiDataListWrapper, TuiFilterByInputPipe, TuiTextfield, ], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected readonly items = [ 'Charles III', 'Elizabeth II', 'George VI', 'Edward VIII', 'George V', 'William IV', 'George IV', 'George III', ]; protected value: string | null = null; protected readonly matcher: TuiStringMatcher = (item, query) => { const romanNumeral = item.split(' ').at(-1)!; return ( query === ROMAN_TO_LATIN[romanNumeral] || item.toLowerCase().includes(query.toLowerCase()) ); }; } ``` #### Textfield customization Take full advantage of Textfield : add any number of Icons and Tooltips (with control over their order and color), adjust the size of the textbox, and more. Explore Textfield documentation page for more customization options. **Template:** ```html ``` **TypeScript:** ```ts import {NgIf} from '@angular/common'; import {Component} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiIcon, TuiTextfield} from '@taiga-ui/core'; import { TuiChevron, TuiComboBox, TuiDataListWrapper, TuiFilterByInputPipe, TuiTooltip, } from '@taiga-ui/kit'; @Component({ standalone: true, imports: [ FormsModule, NgIf, TuiChevron, TuiComboBox, TuiDataListWrapper, TuiFilterByInputPipe, TuiIcon, TuiTextfield, TuiTooltip, ], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected readonly cities = [ 'Night City', 'Raccoon City', 'City 17', 'Springfield', 'Bikini Bottom', 'Gotham', ]; protected value: string | null = null; } ``` #### Server-side filtering Pass null as argument to tui-data-list-wrapper[items] to show loader inside the dropdown. Additionally, you can put Loader inside textfield's box. Pass empty array to tui-data-list-wrapper[items] to show tui-data-list-wrapper[emptyContent] (it accepts PolymorpheusContent ). **Template:** ```html ``` **TypeScript:** ```ts import {AsyncPipe, NgIf} from '@angular/common'; import {Component, inject, signal} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiLet} from '@taiga-ui/cdk'; import {TuiLoader, TuiTextfield} from '@taiga-ui/core'; import {TuiChevron, TuiComboBox, TuiDataListWrapper} from '@taiga-ui/kit'; import {debounceTime, filter, of, Subject, switchMap, tap} from 'rxjs'; import {DatabaseServer} from './database'; @Component({ standalone: true, imports: [ AsyncPipe, FormsModule, NgIf, TuiChevron, TuiComboBox, TuiDataListWrapper, TuiLet, TuiLoader, TuiTextfield, ], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { private readonly api = inject(DatabaseServer); protected readonly showLoader = signal(false); // Click on cleaner / datalist item triggers (input) events too protected readonly search$ = new Subject(); protected readonly items$ = this.search$.pipe( debounceTime(0), // ensure form control is updated after last input filter(() => !this.value), // click on datalist item should not trigger new api request tap(() => this.showLoader.set(true)), debounceTime(300), switchMap((query) => (query.length >= 2 ? this.api.request$(query) : of(null))), tap(() => this.showLoader.set(false)), ); protected value: string | null = null; } ``` #### Items handlers Use tuiItemsHandlersProvider to override the default behavior of all ComboBox -s below the current DI scope. To customize a specific ComboBox , use the input properties [identityMatcher] / [stringify] / disabledItemHandler (inherited from Textfield ). **Template:** ```html ``` **TypeScript:** ```ts import {Component, signal} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {tuiItemsHandlersProvider, TuiTextfield} from '@taiga-ui/core'; import { TuiChevron, TuiComboBox, TuiDataListWrapper, TuiFilterByInputPipe, } from '@taiga-ui/kit'; interface Character { readonly id: number; readonly name: string; } @Component({ standalone: true, imports: [ FormsModule, TuiChevron, TuiComboBox, TuiDataListWrapper, TuiFilterByInputPipe, TuiTextfield, ], templateUrl: './index.html', encapsulation, changeDetection, providers: [ /** * You can also use input props of `Textfield` * (they will have more priority): * ```html * * ``` */ tuiItemsHandlersProvider({ stringify: signal((x: Character) => x.name), identityMatcher: signal((a: Character, b: Character) => a.id === b.id), disabledItemHandler: signal((x: Character) => x.name.includes('Trevor')), }), ], }) export default class Example { protected readonly users: Character[] = [ {id: 42, name: 'Tommy Vercetti'}, {id: 237, name: 'Carl Johnson'}, {id: 666, name: 'Niko Bellic'}, {id: 999, name: 'Trevor Philips'}, {id: 123, name: 'Michael De Santa'}, {id: 777, name: 'Franklin Clinton'}, ]; protected value: Character | null = {id: 42, name: 'Tommy Vercetti'}; // !== this.users[0] } ``` #### Customize content DataListWrapper lets you customize the appearance of options inside the dropdown by [itemContent] property. Also, Textfield has [content] property to customize appearance of selected option inside textbox. Both properties accept PolymorpheusContent – it empowers you with extremely large possibilities for customization. **Template:** ```html
{{ card.number.slice(-4) }} {{ card.name }}
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {type TuiPaymentSystem, TuiThumbnailCard} from '@taiga-ui/addon-commerce'; import {type TuiStringHandler, type TuiStringMatcher} from '@taiga-ui/cdk'; import {TuiTextfield} from '@taiga-ui/core'; import { TuiChevron, TuiComboBox, TuiDataListWrapper, TuiFilterByInputPipe, } from '@taiga-ui/kit'; interface Card { name: string; number: string; paymentSystem: TuiPaymentSystem; } @Component({ standalone: true, imports: [ FormsModule, TuiChevron, TuiComboBox, TuiDataListWrapper, TuiFilterByInputPipe, TuiTextfield, TuiThumbnailCard, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected cards: Card[] = [ {name: 'Bitcoin', number: '5555555555554444', paymentSystem: 'mastercard'}, {name: 'Salary', number: '4242424242424242', paymentSystem: 'visa'}, {name: 'Charity', number: '2201382000000013', paymentSystem: 'mir'}, {name: 'Subscriptions', number: '6200000000000005', paymentSystem: 'unionpay'}, ]; protected value: Card | null = null; protected readonly matcher: TuiStringMatcher = (item, value) => { return ( item.name.toLowerCase().includes(value.toLowerCase()) || item.number.includes(value) ); }; protected readonly stringify: TuiStringHandler = (x) => x.number; } ``` #### With DataList DataListWrapper is just a helper to solve most popular use cases. Use DataList for more complex cases when great flexibility is required. DataList documentation page for more customization options. **Template:** ```html
``` **TypeScript:** ```ts import {KeyValuePipe, NgFor, NgIf} from '@angular/common'; import {Component} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiDataList, TuiTextfield} from '@taiga-ui/core'; import {TuiChevron, TuiChip, TuiComboBox, TuiFilterByInputPipe} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [ FormsModule, KeyValuePipe, NgFor, NgIf, TuiChevron, TuiChip, TuiComboBox, TuiDataList, TuiFilterByInputPipe, TuiTextfield, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected filmDatabase = { Action: [ 'The Dark Knight', 'Inception', 'The Matrix', 'The Dark Knight Rises', 'Gladiator', ], Comedy: [ 'The Wolf of Wall Street', 'Back to the Future', 'Guardians of the Galaxy', 'The Truman Show', 'Deadpool', ], Drama: [ 'The Shawshank Redemption', 'The Godfather', "Schindler's List", '12 Angry Men', ], Horror: ['The Silence of the Lambs', 'Alien', 'Psycho', 'The Shining'], Romance: [ 'Forrest Gump', 'Titanic', 'Good Will Hunting', 'Eternal Sunshine of the Spotless Mind', 'Slumdog Millionaire', ], }; protected categories: string[] = Object.keys(this.filmDatabase); protected filters: Record = this.categories.reduce( (acc, category, i) => ({...acc, [category]: i % 2 === 0}), {}, ); protected selectedCategory = true; protected value: string | null = null; } ``` #### Choose form control output DataList exposes Option -directives – it provides you with an opportunity to decide which data type put inside its [value] . This example demonstrates how every option can be a complex object with any structure but form control contains a single id-property as number -type. **Template:** ```html

Form control: {{ control.value | json }}

``` **TypeScript:** ```ts import {JsonPipe, NgForOf} from '@angular/common'; import {Component} from '@angular/core'; import {FormControl, ReactiveFormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {type TuiStringHandler, type TuiStringMatcher} from '@taiga-ui/cdk'; import {TuiDataList, TuiTextfield} from '@taiga-ui/core'; import {TuiChevron, TuiComboBox} from '@taiga-ui/kit'; interface Python { readonly id: number; readonly name: string; } @Component({ standalone: true, imports: [ JsonPipe, NgForOf, ReactiveFormsModule, TuiChevron, TuiComboBox, TuiDataList, TuiTextfield, ], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected readonly control = new FormControl(777); protected readonly items: readonly Python[] = [ {id: 42, name: 'John Cleese'}, {id: 0, name: 'Eric Idle'}, {id: 666, name: 'Michael Palin'}, {id: 123, name: 'Terry Gilliam'}, {id: 777, name: 'Terry Jones'}, {id: 999, name: 'Graham Chapman'}, ]; protected readonly stringify: TuiStringHandler = (id) => this.items.find((item) => item.id === id)?.name ?? ''; protected readonly matcher: TuiStringMatcher = (id, query) => { const {name} = this.items.find((item) => item.id === id)!; return String(id) === query || name.toLowerCase() === query.toLowerCase(); }; } ``` ### TypeScript ```ts import {Component, computed, inject} from '@angular/core'; import {FormControl, ReactiveFormsModule} from '@angular/forms'; import {TuiDocControl} from '@demo/components/control'; import {TuiDocDropdown} from '@demo/components/dropdown'; import {TuiDocIcons} from '@demo/components/icons'; import {TuiDocItemsHandlers} from '@demo/components/items-handlers'; import {TuiDocTextfield} from '@demo/components/textfield'; import {changeDetection} from '@demo/emulate/change-detection'; import {DemoRoute} from '@demo/routes'; import {TuiDemo} from '@demo/utils'; import {type TuiRawLoaderContent} from '@taiga-ui/addon-doc'; import { TUI_IS_MOBILE, TUI_STRICT_MATCHER, type TuiContext, type TuiStringMatcher, } from '@taiga-ui/cdk'; import {TuiDropdown, TuiTextfield} from '@taiga-ui/core'; import { TUI_COUNTRIES, TuiChevron, TuiComboBox, TuiDataListWrapper, TuiFilterByInputPipe, } from '@taiga-ui/kit'; import {type PolymorpheusContent} from '@taiga-ui/polymorpheus'; import {map, type Observable} from 'rxjs'; interface Country { id: string; name: string; } @Component({ standalone: true, imports: [ ReactiveFormsModule, TuiChevron, TuiComboBox, TuiDataListWrapper, TuiDemo, TuiDocControl, TuiDocDropdown, TuiDocIcons, TuiDocItemsHandlers, TuiDocTextfield, TuiDropdown, TuiFilterByInputPipe, TuiTextfield, ], templateUrl: './index.html', changeDetection, }) export default class PageComponent { protected readonly routes = DemoRoute; protected readonly isMobile = inject(TUI_IS_MOBILE); protected readonly control = new FormControl(null); protected textfieldContent: PolymorpheusContent = ''; protected readonly countries$: Observable = inject(TUI_COUNTRIES).pipe( map((x) => Object.entries(x).map(([id, name]) => ({id, name}))), ); protected readonly matcherVariants: ReadonlyArray> = [ TUI_STRICT_MATCHER as TuiStringMatcher, (item: Country, search: string) => item.id === search, ]; protected matcher = this.matcherVariants[0]!; protected readonly textfieldContentVariants = computed(() => [ '', 'TOP SECRET', ({$implicit: x}: TuiContext) => x.name .split(' ') .map((x: string) => '*'.repeat(x.length)) .join(' '), ({$implicit: x}: TuiContext) => x?.name.includes('i') ? `->${x.name}<-` : x?.name, ]); protected strict = true; protected readonly databaseExample: TuiRawLoaderContent = import( './examples/5/database.ts?raw' ); protected readonly selectOptionExample: TuiRawLoaderContent = import( './examples/12/option.ts?raw' ); protected readonly handler = (item: Country): boolean => item.id.charCodeAt(1) % 3 === 0; } ``` --- # components/Compass - **Package**: `KIT` - **Type**: components ### How to Use (Import) ```ts import {Component} from '@angular/core'; import {TuiCompass} from '@taiga-ui/kit'; // ... @Component({ standalone: true, imports: [ // ... TuiCompass, ], }) export class Example {} ``` ### How to Use (Template) ```html ``` ### Example ```html ``` ### API | Property | Type | Description | |----------|-----|----------| | [degrees] | `number` | Pointer direction in degrees | | [style.color] | `string` | Custom color | ### Usage Examples #### Basic **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiCompass} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiCompass], template: '', encapsulation, changeDetection, }) export default class Example {} ``` #### Direction **TypeScript:** ```ts import {Component, ElementRef, ViewChild} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {EMPTY_CLIENT_RECT} from '@taiga-ui/cdk'; import {TuiCompass} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiCompass], template: '', encapsulation, changeDetection, host: { '(document:mousemove)': 'calculate($event)', }, }) export default class Example { @ViewChild(TuiCompass, {read: ElementRef}) private readonly compass?: ElementRef; protected degrees = 0; protected calculate(event: MouseEvent): void { const rect = this.compass?.nativeElement.getBoundingClientRect() ?? EMPTY_CLIENT_RECT; const x = Math.ceil(event.clientX - (rect.left + rect.width / 2)); const y = Math.ceil(event.clientY - (rect.top + rect.height / 2)); this.degrees = Math.atan2(y, x) * (180 / Math.PI) + 90; } } ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; import {TuiCompass} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiCompass, TuiDemo], templateUrl: './index.html', changeDetection, }) export default class Page { protected colorVariants = [ '#428bf9', 'rgb(234, 56, 24)', 'var(--tui-status-positive)', '', ]; protected color = this.colorVariants[0]!; protected degrees = 90; } ``` --- # components/Confirm - **Package**: `KIT` - **Type**: components Confirm is a ready to use Dialog to ask user to confirm an action See this example to learn how to use confirm to prevent data loss on forms inside other modals ### Example ```html ``` ### API | Property | Type | Description | |----------|-----|----------| | content | `PolymorpheusContent` | Content of the confirm | | appearance | `string` | Appearance of the confirming button | | no | `string` | Text on false button | | yes | `string` | Text on true button | ### Usage Examples #### Basic **Template:** ```html ``` **TypeScript:** ```ts import {Component, inject} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiResponsiveDialogService} from '@taiga-ui/addon-mobile'; import {TuiAlertService, TuiButton} from '@taiga-ui/core'; import {TUI_CONFIRM, type TuiConfirmData} from '@taiga-ui/kit'; import {switchMap} from 'rxjs'; @Component({ standalone: true, imports: [TuiButton], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { private readonly dialogs = inject(TuiResponsiveDialogService); private readonly alerts = inject(TuiAlertService); protected onClick(): void { const data: TuiConfirmData = { content: 'This is PolymorpheusContent so it can be template too!', yes: 'That is great!', no: 'Who cares?', }; this.dialogs .open(TUI_CONFIRM, { label: 'Do you like Taiga UI?', size: 's', data, }) .pipe(switchMap((response) => this.alerts.open(String(response)))) .subscribe(); } } ``` ### TypeScript ```ts import {Component, inject} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {DemoRoute} from '@demo/routes'; import {TuiDemo} from '@demo/utils'; import {TuiAlertService, TuiButton, TuiDialogService} from '@taiga-ui/core'; import {TUI_CONFIRM, type TuiConfirmData} from '@taiga-ui/kit'; import {switchMap} from 'rxjs'; @Component({ standalone: true, imports: [TuiButton, TuiDemo], templateUrl: './index.html', changeDetection, }) export default class Example implements TuiConfirmData { private readonly dialogs = inject(TuiDialogService); private readonly alerts = inject(TuiAlertService); protected readonly routes = DemoRoute; protected readonly examples = ['Basic']; protected readonly exampleService = import('./examples/import/service.md?raw'); public readonly appearances = ['primary', 'accent', 'secondary']; public appearance = this.appearances[0]!; public no = 'No'; public yes = 'Yes'; public readonly content = 'This is PolymorpheusContent, so it can be anything you like!'; protected onClick(): void { this.dialogs .open(TUI_CONFIRM, { label: 'Are you sure?', size: 's', data: this, }) .pipe(switchMap((response) => this.alerts.open(String(response)))) .subscribe(); } } ``` --- # components/Copy - **Package**: `KIT` - **Type**: components This component provides an easy way to copy text content to the clipboard. It displays the content normally and shows a copy button on hover, with visual feedback when content is copied. ### How to Use (Import) ```ts import {Component} from '@angular/core'; import {TuiCopy} from '@taiga-ui/kit'; // ... @Component({ imports: [ // ... TuiCopy, ], }) export class Example {} ``` ### How to Use (Template) ```html Here you can reproduce copy Taiga UI ``` ### Usage Examples #### Basic **Template:** ```html

Bank account 1234 42069237 88884321

Very very long text that is so long it will wrap to the next line

Very very long text that is so long it will overflow and get truncated ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiTitle} from '@taiga-ui/core'; import {TuiCopy} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiCopy, TuiTitle], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Sizes **Template:** ```html

{{ font }}

``` **TypeScript:** ```ts import {NgForOf} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiCopy} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [NgForOf, TuiCopy], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected readonly fonts = [ 'font-heading-1', 'font-heading-2', 'font-heading-3', 'font-heading-4', 'font-heading-5', 'font-heading-6', 'font-text-xl', 'font-text-l', 'font-text-m', 'font-text-s', 'font-text-xs', ]; } ``` #### InputCopy **Template:** ```html ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiIcon, TuiTextfield} from '@taiga-ui/core'; import {TuiCopy} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [FormsModule, TuiCopy, TuiIcon, TuiTextfield], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected value = ''; } ``` #### With CopyProcessor **Template:** ```html Taiga UI

When you copy, the result will have a space prepended and appended: " Taiga UI " .

``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiCopyProcessor} from '@taiga-ui/cdk'; import {TuiCopy} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiCopy, TuiCopyProcessor], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected readonly processor = (value: string): string => ` ${value} `; } ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; @Component({ standalone: true, imports: [TuiDemo], templateUrl: './index.html', changeDetection, }) export default class Example { protected readonly examples = ['Basic', 'Sizes', 'InputCopy', 'With CopyProcessor']; } ``` --- # components/DataList - **Package**: `CORE` - **Type**: components DataList allows to make lists or menus ### How to Use (Import) ```ts import {TuiDataList} from '@taiga-ui/core'; // ... @Component({ standalone: true, imports: [ // ... TuiDataList, ], // ... }) export class Example {} ``` ### How to Use (Template) ```html {{item.label}} ``` ### Example ```html ``` ### API | Property | Type | Description | |----------|-----|----------| | emptyContent | `PolymorpheusContent` | Content to display when there are no options inside | | size | `TuiSizeS | TuiSizeL` | Size of items | ### Usage Examples #### Links **Template:** ```html {{ item.label }} ``` **TypeScript:** ```ts import {NgForOf, NgIf} from '@angular/common'; import {Component} from '@angular/core'; import {RouterLink, RouterLinkActive} from '@angular/router'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiButton, TuiDataList, TuiDropdown, TuiIcon} from '@taiga-ui/core'; import {TuiChevron} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [ NgForOf, NgIf, RouterLink, RouterLinkActive, TuiButton, TuiChevron, TuiDataList, TuiDropdown, TuiIcon, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly groups = [ { label: 'Components', items: [ { label: 'Input', routerLink: '/components/input', }, { label: 'Select', routerLink: '/components/select', }, { label: 'DataList', routerLink: '/components/data-list', }, ], }, { label: 'Styles', items: [ { label: 'Icons', routerLink: '/icons', }, { label: 'Typography', routerLink: '/typography', }, ], }, { label: '', items: [ { label: 'Changelog', routerLink: '/changelog', }, ], }, ]; } ``` #### Submenu **Template:** ```html ``` **TypeScript:** ```ts import {NgForOf} from '@angular/common'; import {Component, inject} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiLet} from '@taiga-ui/cdk'; import { TuiButton, TuiDataList, TuiDialogService, TuiDropdown, type TuiSizeL, type TuiSizeS, } from '@taiga-ui/core'; import {TuiDataListDropdownManager} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [ NgForOf, TuiButton, TuiDataList, TuiDataListDropdownManager, TuiDropdown, TuiLet, ], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { private readonly dialogs = inject(TuiDialogService); protected dropdownOpen = false; protected size: TuiSizeL | TuiSizeS = 's'; protected readonly burgers = [ 'Classic', 'Cheeseburger', 'Royal Cheeseburger Quarterpounder', ]; protected readonly drinks = ['Cola', 'Tea', 'Coffee', 'Slurm']; protected open = false; protected selectOption(item: string): void { this.dropdownOpen = false; this.dialogs.open(`You selected ${item}`).subscribe(); } } ``` #### Form control **Template:** ```html

Multi select control

{{ value }}

Separate toggles

``` **TypeScript:** ```ts import {NgForOf} from '@angular/common'; import {Component} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiButton, TuiDataList, TuiDropdown} from '@taiga-ui/core'; import {TuiCheckbox, TuiChevron, TuiSwitch} from '@taiga-ui/kit'; import {TuiMultiSelectModule} from '@taiga-ui/legacy'; @Component({ standalone: true, imports: [ FormsModule, NgForOf, TuiButton, TuiCheckbox, TuiChevron, TuiDataList, TuiDropdown, TuiMultiSelectModule, TuiSwitch, ], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected first = false; protected second = true; protected control = false; protected label = false; protected value = []; protected readonly burgers = ['Hamburger', 'Cheeseburger']; protected readonly drinks = ['Cola', 'Tea', 'Coffee', 'Slurm']; } ``` #### Custom list **Template:** ```html Open-source budget ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import { type TuiContext, type TuiIdentityMatcher, type TuiStringHandler, } from '@taiga-ui/cdk'; import {TuiDataList} from '@taiga-ui/core'; import {TuiSelectModule} from '@taiga-ui/legacy'; import {CustomListComponent} from './custom-list'; const INCOME = { name: 'Income', items: [ 'Donations', 'Product placement', 'Sponsorship', 'Found on the street', 'Unexpected inheritance', 'Investments', 'Color copier', ], }; const EXPENSES = { name: 'Expenses', items: [ 'Energy drinks', 'Coffee', 'Ramen', 'Bills', 'Back medicine', 'Warhammer 40000 figurines', ], }; @Component({ standalone: true, imports: [CustomListComponent, FormsModule, TuiDataList, TuiSelectModule], templateUrl: './index.html', styles: [ ` .control { width: 320px; } `, ], encapsulation, changeDetection, }) export default class Example { protected value = []; protected readonly items = [INCOME, EXPENSES]; protected readonly identityMatcher: TuiIdentityMatcher = ( items1, items2, ) => items1.length === items2.length && items1.every((item) => items2.includes(item)); protected readonly valueContent: TuiStringHandler> = ({ $implicit, }) => { if (!$implicit.length) { return 'All'; } const selected = this.items.find(({items}) => this.identityMatcher($implicit, items), ); return selected ? `${selected.name} only` : `Selected: ${$implicit.length}`; }; } ``` #### Complex **Template:** ```html RUB Email
1 Rub = (X) Dollars 1 Rub = (Y) Euros
  • {{ moneyValue / dollar | tuiAmount: 'USD' | async }}
  • {{ moneyValue / euro | tuiAmount: 'EUR' | async }}
Range

Email: {{ emailValue }}

Chosen date: {{ dateValue }}

Range date: {{ rangeValue }}

Dol - {{ dollar }}, Eur - {{ euro }}

``` **TypeScript:** ```ts import {AsyncPipe} from '@angular/common'; import {Component} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAmountPipe} from '@taiga-ui/addon-commerce'; import {TuiDay, TuiDayRange} from '@taiga-ui/cdk'; import {TuiButton, TuiCalendar, TuiDataList, TuiDropdown, TuiGroup} from '@taiga-ui/core'; import {TuiDataListDropdownManager} from '@taiga-ui/kit'; import {TuiInputDateRangeModule, TuiInputModule} from '@taiga-ui/legacy'; @Component({ standalone: true, imports: [ AsyncPipe, FormsModule, TuiAmountPipe, TuiButton, TuiCalendar, TuiDataList, TuiDataListDropdownManager, TuiDropdown, TuiGroup, TuiInputDateRangeModule, TuiInputModule, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected dropdownOpen = false; protected dateValue: TuiDay = new TuiDay(2020, 0, 1); protected euro = 87; // 1 euro = 87 rub protected dollar = 75; // 1 dollar = 75 rub protected emailValue = 'mail@mail.ru'; protected moneyValue = 1000; protected rangeValue = new TuiDayRange( TuiDay.currentLocal(), TuiDay.currentLocal().append({year: 1}), ); protected onDayClick(day: TuiDay): void { this.dateValue = day; } } ``` #### Options with long text **Template:** ```html Enter 3 characters ``` **TypeScript:** ```ts import {AsyncPipe, NgForOf} from '@angular/common'; import {Component, inject} from '@angular/core'; import {FormControl, ReactiveFormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TUI_IS_MOBILE} from '@taiga-ui/cdk'; import {TuiButton, TuiDataList, TuiDropdown} from '@taiga-ui/core'; import {TuiChevron} from '@taiga-ui/kit'; import {TuiInputModule} from '@taiga-ui/legacy'; @Component({ standalone: true, imports: [ AsyncPipe, NgForOf, ReactiveFormsModule, TuiButton, TuiChevron, TuiDataList, TuiDropdown, TuiInputModule, ], templateUrl: './index.html', styles: [ ` .option { white-space: normal; } `, ], encapsulation, changeDetection, }) export default class Example { protected open = false; protected readonly groups = [ { label: 'Advantages of Taiga UI', items: [ '🧩 Modular and fully-treeshakable. We harnessed the power of Secondary Entry Points mechanism. You can import even just one entity from our library and be sure that there is no redundant code in your bundle.', '🧙 Agnostic. Our components are very flexible and are ready for any use case. But we take care of basic UX aspects to let you focus on your project features.', '🦋 Customizable. We use CSS custom properties for all our styling and provide easy methods to customize all UI components.', '🛠 Well engineered. We are not afraid to use DI to the max. All our components use OnPush, and the whole project is developed with strict TypeScript mode.', '📦 It is big! We have 130+ components, 100+ directives, dozens of tokens, utils and tools. And it is not over yet.', '🏗 Maintained! The library started as an internal product in our company. It is used by 50+ projects in production now and it is here to stay.', ], }, { label: 'Well-engineered Taiga UI components', items: ['Calendar', 'Dialog', 'ComboBox', 'Select'], }, ]; protected readonly isMobile = inject(TUI_IS_MOBILE); public control = new FormControl(''); } ``` ### TypeScript ```ts import {Component, inject} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; import {TUI_IS_E2E} from '@taiga-ui/cdk'; import {TuiDataList, type TuiSizeL, type TuiSizeS} from '@taiga-ui/core'; import {delay, of} from 'rxjs'; @Component({ standalone: true, imports: [TuiDataList, TuiDemo], templateUrl: './index.html', changeDetection, }) export default class Page { private readonly items = ['Foo', 'Bar', 'Baz']; protected readonly items$ = inject(TUI_IS_E2E) ? of(this.items) : of(this.items).pipe(delay(1e3)); protected readonly emptyContentVariants = ['Loading...', '']; protected emptyContent = this.emptyContentVariants[0]; protected readonly sizeVariants: ReadonlyArray = ['s', 'm', 'l']; protected size = this.sizeVariants[0]!; protected readonly example4 = { TypeScript: import('./examples/4/index.ts?raw'), HTML: import('./examples/4/index.html?raw'), 'custom-list/index.ts': import('./examples/4/custom-list/index.ts?raw'), 'custom-list/index.html': import('./examples/4/custom-list/index.html?raw'), }; } ``` --- # components/DataListWrapper - **Package**: `KIT` - **Type**: components DataListWrapper is an abstraction over DataList to simplify usage in common cases where precise control is not necessary. ### How to Use (Import) ```ts import {TuiDataListWrapper} from '@taiga-ui/kit'; // ... @Component({ standalone: true, imports: [ // ... TuiDataListWrapper, ], // ... }) export class Example {} ``` ### How to Use (Template) ```html Account ``` ### API | Property | Type | Description | |----------|-----|----------| | [items] | `readonly T[] | ReadonlyArray | null` | Items to select | | [itemContent] | `PolymorpheusContent>` | Content of an item | | [emptyContent] | `PolymorpheusContent` | Content to display when there are no options inside | | [disabledItemHandler] | `TuiBooleanHandler` | | | [size] | `TuiSizeL | TuiSizeXS` | Size of items | | [labels] | `readonly string[]` | Group label | | (itemClick) | `T` | Emits on click on item from datalist | ### Usage Examples #### Disables items that start with T **Template:** ```html Account ``` **TypeScript:** ```ts import {Component, inject} from '@angular/core'; import {FormControl, ReactiveFormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {type TuiBooleanHandler} from '@taiga-ui/cdk'; import {TuiDataListWrapper, TuiFilterByInputPipe} from '@taiga-ui/kit'; import {TuiInputModule} from '@taiga-ui/legacy'; @Component({ standalone: true, imports: [ ReactiveFormsModule, TuiDataListWrapper, TuiFilterByInputPipe, TuiInputModule, ], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected readonly control = new FormControl(''); protected readonly items = inject('Pythons' as any); protected readonly disabledItemHandler: TuiBooleanHandler = (v) => v.startsWith('T'); } ``` #### Custom item content **Template:** ```html ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {FormControl, ReactiveFormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import { TuiDataListWrapper, TuiFilterByInputPipe, TuiStringifyContentPipe, } from '@taiga-ui/kit'; import {TuiComboBoxModule, TuiTextfieldControllerModule} from '@taiga-ui/legacy'; @Component({ standalone: true, imports: [ ReactiveFormsModule, TuiComboBoxModule, TuiDataListWrapper, TuiFilterByInputPipe, TuiStringifyContentPipe, TuiTextfieldControllerModule, ], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected readonly control = new FormControl<{name: string; surname: string} | null>( null, ); protected readonly items = [ {name: 'John', surname: 'Cleese'}, {name: 'Eric', surname: 'Idle'}, {name: 'Graham', surname: 'Chapman'}, {name: 'Michael', surname: 'Palin'}, {name: 'Terry', surname: 'Gilliam'}, {name: 'Terry', surname: 'Jones'}, ]; protected readonly stringify = (item: {name: string; surname: string}): string => `${item.name} ${item.surname}`; } ``` #### Group by labels **Template:** ```html Menu ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {FormControl, ReactiveFormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiDataListWrapper} from '@taiga-ui/kit'; import {TuiInputModule} from '@taiga-ui/legacy'; @Component({ standalone: true, imports: [ReactiveFormsModule, TuiDataListWrapper, TuiInputModule], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected readonly control = new FormControl(''); protected readonly items = [ ['Caesar', 'Greek', 'Apple and Chicken'], ['Broccoli Cheddar', 'Chicken and Rice', 'Chicken Noodle'], ] as const; protected labels = ['Salad', 'Soup'] as const; } ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; @Component({ standalone: true, imports: [TuiDemo], templateUrl: './index.html', changeDetection, }) export default class Page { protected readonly examples = [ 'Disables items that start with T', 'Custom item content', 'Group by labels', ]; } ``` --- # components/Dialog - **Package**: `CORE` - **Type**: components Built-in implementation of Taiga UI modals If you want custom dialogs see this link on creating your own implementation Use TUI_DIALOGS_CLOSE token if you need to close dialog with from a stream. For example, this way you can close dialogs by logout ### Example ```html ``` ### API | Property | Type | Description | |----------|-----|----------| | [closeable] | `boolean` | | | [dismissible] | `boolean` | if you want prevent closing, for example, with a confirmation prompt. | | [data] | `number` | | | [header] | `PolymorpheusContent` | Content above a heading | | [label] | `string` | Heading of dialog | | [required] | `boolean` | (you can catch it with "catch" operator or onError handler) | | [size] | `TuiDialogSize` | Size | | [appearance] | `string` | Appearance of dialog | ### Usage Examples #### Dialog from string **Template:** ```html

``` **TypeScript:** ```ts import {Component, inject} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiButton, TuiDialogService} from '@taiga-ui/core'; @Component({ standalone: true, imports: [TuiButton], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { private readonly dialogs = inject(TuiDialogService); protected showDialog(): void { this.dialogs .open( '
This is a plain string dialog.
It supports basic HTML', {label: 'Heading', size: 's'}, ) .subscribe(); } protected showDialogWithCustomButton(): void { this.dialogs .open('Good, Anakin, Good!', { label: 'Star wars. Episode III', size: 's', data: {button: 'Do it!'}, }) .subscribe(); } } ``` #### Appearance **Template:** ```html ``` **TypeScript:** ```ts import {Component, inject, ViewEncapsulation} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiButton, TuiDialogService} from '@taiga-ui/core'; @Component({ standalone: true, imports: [TuiButton], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation: ViewEncapsulation.None, changeDetection, }) export default class Example { private readonly dialogs = inject(TuiDialogService); protected showDialog(): void { this.dialogs .open( 'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry`s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum', { label: 'What is Lorem Ipsum?', appearance: 'lorem-ipsum', }, ) .subscribe(); } } ``` #### Theme color **Template:** ```html ``` **TypeScript:** ```ts import {Component, inject} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiThemeColorService} from '@taiga-ui/cdk'; import {TuiButton, TuiDialogService} from '@taiga-ui/core'; @Component({ standalone: true, imports: [TuiButton], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { private readonly dialogs = inject(TuiDialogService); private readonly theme = inject(TuiThemeColorService); protected showDialog(): void { this.theme.color = '#ffdd2d'; this.dialogs .open( 'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry`s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum', {label: 'What is Lorem Ipsum?'}, ) .subscribe({ complete: () => { this.theme.color = '#ff7043'; }, }); } } ``` #### Component dialog **Template:** ```html ``` **TypeScript:** ```ts import {Component, inject, INJECTOR} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiButton, tuiDialog} from '@taiga-ui/core'; import {type Observable} from 'rxjs'; @Component({ standalone: true, imports: [TuiButton], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { private readonly injector = inject(INJECTOR); protected async showDialog(): Promise { const dialog = await this.lazyLoad(); dialog(237).subscribe({ next: (data) => { console.info(`Dialog emitted data = ${data}`); }, complete: () => { console.info('Dialog closed'); }, }); } private async lazyLoad(): Promise<(data: number) => Observable> { const {DialogExample} = await import('./dialog-example/dialog-example.component'); return tuiDialog(DialogExample, { injector: this.injector, dismissible: true, label: 'Heading', }); } } ``` #### Dialog from template **Template:** ```html

Your balance: {{ money | tuiAmount: 'RUB' | async }}

You can show a dialog with template

Your balance: {{ money | tuiAmount: 'RUB' | async }}

``` **TypeScript:** ```ts import {AsyncPipe, NgForOf} from '@angular/common'; import {Component, inject} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAmountPipe} from '@taiga-ui/addon-commerce'; import { TuiButton, TuiDataList, type TuiDialogContext, TuiDialogService, TuiDropdown, } from '@taiga-ui/core'; import {TuiChevron} from '@taiga-ui/kit'; import {type PolymorpheusContent} from '@taiga-ui/polymorpheus'; @Component({ standalone: true, imports: [ AsyncPipe, NgForOf, TuiAmountPipe, TuiButton, TuiChevron, TuiDataList, TuiDropdown, ], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { private readonly dialogs = inject(TuiDialogService); protected money = 1000; protected showDialog(content: PolymorpheusContent): void { this.dialogs.open(content).subscribe(); } protected withdraw(sum: number): void { this.money -= sum; } } ``` #### Mobile dialog **Template:** ```html

Long mobile dialog with filters

Card payment

Sushi

{{ 300 | tuiAmount: 'RUB' | async }}

Additional information

In user interface design for computer applications, a modal window is a graphical control element subordinate to an application's main window. A modal window creates a mode that disables the main window but keeps it visible, with the modal window as a child window in front of it. Users must interact with the modal window before they can return to the parent application. This avoids interrupting the workflow on the main window. Modal windows are sometimes called heavy windows or modal dialogs because they often display a dialog box.

Additional information

In user interface design for computer applications, a modal window is a graphical control element subordinate to an application's main window. A modal window creates a mode that disables the main window but keeps it visible, with the modal window as a child window in front of it. Users must interact with the modal window before they can return to the parent application. This avoids interrupting the workflow on the main window. Modal windows are sometimes called heavy windows or modal dialogs because they often display a dialog box.

``` **TypeScript:** ```ts import {AsyncPipe, NgIf} from '@angular/common'; import {Component, inject, type TemplateRef} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAmountPipe} from '@taiga-ui/addon-commerce'; import {TuiElasticSticky} from '@taiga-ui/addon-mobile'; import {tuiClamp} from '@taiga-ui/cdk'; import { TuiButton, TuiDialogService, TuiDropdownService, TuiNumberFormat, } from '@taiga-ui/core'; import {TuiAvatar} from '@taiga-ui/kit'; import {type PolymorpheusContent} from '@taiga-ui/polymorpheus'; @Component({ standalone: true, imports: [ AsyncPipe, NgIf, TuiAmountPipe, TuiAvatar, TuiButton, TuiElasticSticky, TuiNumberFormat, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { private readonly dialogs = inject(TuiDialogService); private readonly dropdowns = inject(TuiDropdownService); protected filters = false; protected onElastic(value: number, {style}: HTMLElement): void { const scale = tuiClamp(value, 0.7, 1); style.setProperty('transform', `scale(${scale})`); style.setProperty('width', `calc((100% + 3.5rem) / ${scale})`); } protected onFilterClick(): void { this.filters = true; this.dialogs.open('Dialog with filters').subscribe({ complete: () => { this.filters = false; }, }); } protected showDialog( content: PolymorpheusContent, button: TemplateRef>, ): void { const templateRef = this.dropdowns.addTemplate(button); this.dialogs.open(content).subscribe({ complete: () => { this.dropdowns.removeTemplate(templateRef); }, }); } } ``` #### Dialog with header **Template:** ```html Take a look
Cool
``` **TypeScript:** ```ts import {Component, inject} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import { TuiButton, type TuiDialogContext, TuiDialogService, type TuiDialogSize, } from '@taiga-ui/core'; import {type PolymorpheusContent} from '@taiga-ui/polymorpheus'; @Component({ standalone: true, imports: [TuiButton], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { private readonly dialogs = inject(TuiDialogService); protected onClick( content: PolymorpheusContent, header: PolymorpheusContent, size: TuiDialogSize, ): void { this.dialogs .open(content, { label: 'What a cool library set', header, size, }) .subscribe(); } } ``` #### Dialog with directive **Template:** ```html

This abstracts away service and subscription

Some value

``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {FormControl, FormGroup, ReactiveFormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAutoFocus} from '@taiga-ui/cdk'; import {TuiButton, TuiDialog, TuiHint} from '@taiga-ui/core'; import {TuiInputModule} from '@taiga-ui/legacy'; @Component({ standalone: true, imports: [ ReactiveFormsModule, TuiAutoFocus, TuiButton, TuiDialog, TuiHint, TuiInputModule, ], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected exampleForm = new FormGroup({ exampleControl: new FormControl(''), }); protected open = false; protected showDialog(): void { this.open = true; } } ``` #### Fullscreen mobile dialog with autofocus **Template:** ```html ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiButton, tuiDialog} from '@taiga-ui/core'; import {SearchDialogExample} from './search-example/search-dialog-example.component'; @Component({ standalone: true, imports: [TuiButton], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { private readonly dialog = tuiDialog(SearchDialogExample, { size: 'page', closeable: true, dismissible: true, }); protected showDialog(): void { this.dialog().subscribe(); } } ``` #### Confirmation **Template:** ```html Your name ``` **TypeScript:** ```ts import {Component, inject} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiResponsiveDialogService} from '@taiga-ui/addon-mobile'; import {TuiButton, TuiDialogService} from '@taiga-ui/core'; import {TuiConfirmService} from '@taiga-ui/kit'; import {TuiInputModule} from '@taiga-ui/legacy'; import {type PolymorpheusContent} from '@taiga-ui/polymorpheus'; @Component({ standalone: true, imports: [FormsModule, TuiButton, TuiInputModule], templateUrl: './index.html', encapsulation, changeDetection, providers: [ // Provide TUI_CONFIRM_DIALOG if you want to override default Confirm dialog TuiConfirmService, { provide: TuiDialogService, useExisting: TuiResponsiveDialogService, }, ], }) export default class Example { private readonly confirm = inject(TuiConfirmService); private readonly dialogs = inject(TuiDialogService); protected value = ''; protected onModelChange(value: string): void { this.value = value; this.confirm.markAsDirty(); } protected onClick(content: PolymorpheusContent): void { const closeable = this.confirm.withConfirm({ label: 'Are you sure?', data: { content: 'Your data will be lost', }, }); this.dialogs .open(content, {label: 'Form', closeable, dismissible: closeable}) .subscribe({ complete: () => { this.value = ''; this.confirm.markAsPristine(); }, }); } } ``` #### Pay **Template:** ```html
``` **TypeScript:** ```ts import {Component, DestroyRef, inject} from '@angular/core'; import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; import {FormControl, ReactiveFormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import { TuiButton, tuiDialog, TuiHint, TuiIcon, TuiIconPipe, TuiTextfield, } from '@taiga-ui/core'; import {TuiInputNumber, TuiTooltip} from '@taiga-ui/kit'; import {PayModal} from './pay-modal/pay-modal.component'; @Component({ standalone: true, imports: [ ReactiveFormsModule, TuiButton, TuiHint, TuiIcon, TuiIconPipe, TuiInputNumber, TuiTextfield, TuiTooltip, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { private readonly destroyRef = inject(DestroyRef); private readonly payModal = tuiDialog(PayModal, { size: 'auto', closeable: true, }); protected readonly amountControl = new FormControl(100, { nonNullable: true, }); protected payByCard(): void { this.payModal({ amount: this.amountControl.value, }) .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(); } } ``` ### TypeScript ```ts import {Component, inject, type TemplateRef} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {DemoRoute} from '@demo/routes'; import {TuiDemo} from '@demo/utils'; import { TuiAlertService, TuiButton, type TuiDialogContext, TuiDialogService, type TuiDialogSize, } from '@taiga-ui/core'; import {TuiAccordion} from '@taiga-ui/kit'; import {switchMap} from 'rxjs'; @Component({ standalone: true, imports: [TuiAccordion, TuiButton, TuiDemo], templateUrl: './index.html', styleUrls: ['./index.less'], changeDetection, }) export default class Page { private readonly alerts = inject(TuiAlertService); private readonly dialogs = inject(TuiDialogService); protected readonly routes = DemoRoute; protected readonly method = import('./method.md?raw'); protected readonly dialogsCloseToken = import( './examples/import/dialogs-close-token.md?raw' ); protected readonly example2 = { TypeScript: import('./examples/2/index.ts?raw'), HTML: import('./examples/2/index.html?raw'), 'dialog-example/dialog-example.component.ts': import( './examples/2/dialog-example/dialog-example.component.ts?raw' ), 'dialog-example/dialog-example.style.less': import( './examples/2/dialog-example/dialog-example.style.less?raw' ), 'dialog-example/dialog-example.template.html': import( './examples/2/dialog-example/dialog-example.template.html?raw' ), }; protected readonly example7 = { TypeScript: import('./examples/7/index.ts?raw'), HTML: import('./examples/7/index.html?raw'), 'search-example/search-dialog-example.component.ts': import( './examples/7/search-example/search-dialog-example.component.ts?raw' ), 'search-example/search-dialog-example.template.html': import( './examples/7/search-example/search-dialog-example.template.html?raw' ), 'search-example/search-dialog-example.component.less': import( './examples/7/search-example/search-dialog-example.component.less?raw' ), }; protected readonly example9 = { TypeScript: import('./examples/9/index.ts?raw'), HTML: import('./examples/9/index.html?raw'), LESS: import('./examples/9/index.less?raw'), 'helpers/mock-cards.ts': import('./examples/9/helpers/mock-cards.ts?raw'), 'helpers/models.ts': import('./examples/9/helpers/models.ts?raw'), 'helpers/pay.service.ts': import('./examples/9/helpers/pay.service.ts?raw'), 'helpers/validator.ts': import('./examples/9/helpers/validator.ts?raw'), 'pay-modal/pay-modal.component.ts': import( './examples/9/pay-modal/pay-modal.component.ts?raw' ), 'pay-modal/pay-modal.component.less': import( './examples/9/pay-modal/pay-modal.component.less?raw' ), 'pay-modal/pay-modal.component.html': import( './examples/9/pay-modal/pay-modal.component.html?raw' ), }; protected readonly exampleServiceUsage = import( './examples/import/service-usage.md?raw' ); protected readonly exampleCustomDialog = import( './examples/import/custom-dialog.md?raw' ); protected readonly exampleLazyDialog = import('./examples/import/lazy-dialog.md?raw'); protected data = 100; protected closeable = true; protected dismissible = true; protected required = false; protected readonly sizeVariants: readonly TuiDialogSize[] = [ 's', 'm', 'l', 'fullscreen', 'page', 'auto', ]; protected size: TuiDialogSize = this.sizeVariants[1]!; protected label = ''; protected appearance = ''; protected showDialog(content: TemplateRef>): void { const {data, label, required, closeable, dismissible, size, appearance} = this; this.dialogs .open(content, { data, label, required, closeable, dismissible, size, appearance, }) .pipe(switchMap((response) => this.alerts.open(String(response)))) .subscribe(); } } ``` ### LESS ```less .big { font-size: 3.125rem; } ``` --- # components/DialogExperimental - **Package**: `EXPERIMENTAL` - **Type**: components Customizable modal dialogs ### How to Use (Import) ```ts import {TuiButton} from '@taiga-ui/core'; import {TuiDialog} from '@taiga-ui/experimental'; // ... @Component({ standalone: true, imports: [ // ... TuiButton, TuiDialog, ], // ... }) export class Example {} ``` ### How to Use (Template) ```html

I am a title

I am some text

``` ### Example ```html ``` ### API | Property | Type | Description | |----------|-----|----------| | [appearance] | `string` | Appearance of dialog | | [closable] | `boolean` | | | [dismissible] | `boolean` | if you want prevent closing, for example, with a confirmation prompt. | | [data] | `string` | | | [label] | `string` | Heading of dialog | | [required] | `boolean` | (you can catch it with "catch" operator or onError handler) | | [size] | `TuiSizeS | TuiSizeL` | Size | ### Usage Examples #### String **Template:** ```html

``` **TypeScript:** ```ts import {Component, inject} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiButton} from '@taiga-ui/core'; import {TuiDialogService} from '@taiga-ui/experimental'; @Component({ standalone: true, imports: [TuiButton], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { private readonly dialogs = inject(TuiDialogService); protected default(): void { this.dialogs .open( 'This is a plain string dialog.
It supports basic HTML', {label: 'Heading', size: 's'}, ) .subscribe(); } protected custom(): void { this.dialogs .open('Good, Anakin, Good!', { label: 'Star wars. Episode III', size: 's', data: 'Do it!', }) .subscribe(); } } ``` #### Directive **Template:** ```html

Let us know

``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAutoFocus} from '@taiga-ui/cdk'; import {TuiButton, TuiTextfield, TuiTitle} from '@taiga-ui/core'; import {TuiDialog} from '@taiga-ui/experimental'; import {TuiForm, TuiHeader} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ TuiAutoFocus, TuiButton, TuiDialog, TuiForm, TuiHeader, TuiTextfield, TuiTitle, ], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected open = false; } ``` #### Component **Template:** ```html ``` **TypeScript:** ```ts import {Component, inject} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAlertService, TuiButton} from '@taiga-ui/core'; import {TuiDialogService} from '@taiga-ui/experimental'; import {PolymorpheusComponent} from '@taiga-ui/polymorpheus'; import {switchMap} from 'rxjs'; import {DialogComponent} from './component'; @Component({ standalone: true, imports: [TuiButton], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { private readonly alerts = inject(TuiAlertService); private readonly dialogs = inject(TuiDialogService); protected onClick(): void { this.dialogs .open(new PolymorpheusComponent(DialogComponent), { label: 'Edit info', size: 's', data: 'Alex Inkin', }) .pipe(switchMap((name) => this.alerts.open(name))) .subscribe(); } } ``` #### Confirmation **Template:** ```html ``` **TypeScript:** ```ts import {Component, inject} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAlertService, TuiButton} from '@taiga-ui/core'; import {TuiDialogService} from '@taiga-ui/experimental'; import {TUI_CONFIRM, type TuiConfirmData} from '@taiga-ui/kit'; import {switchMap} from 'rxjs'; @Component({ standalone: true, imports: [TuiButton], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { private readonly alerts = inject(TuiAlertService); private readonly dialogs = inject(TuiDialogService); protected onClick(): void { const data: TuiConfirmData = { content: 'This action cannot be undone', yes: 'Sure!', no: 'No, thanks', }; this.dialogs .open(TUI_CONFIRM, {size: 's', label: 'Are you sure?', data}) .pipe(switchMap((v) => this.alerts.open(v, {label: 'Response'}))) .subscribe(); } } ``` #### Closing **Template:** ```html

Hello!

Welcome to the website

``` **TypeScript:** ```ts import {Component, inject} from '@angular/core'; import {Router} from '@angular/router'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiAutoFocus} from '@taiga-ui/cdk'; import {TUI_DIALOGS_CLOSE, TuiButton, TuiTextfield, TuiTitle} from '@taiga-ui/core'; import {TuiDialog} from '@taiga-ui/experimental'; import {TuiHeader} from '@taiga-ui/layout'; import {merge} from 'rxjs'; import {AuthService} from './service'; @Component({ standalone: true, imports: [TuiAutoFocus, TuiButton, TuiDialog, TuiHeader, TuiTextfield, TuiTitle], templateUrl: './index.html', encapsulation, changeDetection, providers: [ // This has to be added to global providers, shown here for demonstration purposes only { provide: TUI_DIALOGS_CLOSE, useFactory: () => merge(inject(AuthService), inject(Router).events), }, ], }) export default class Example { protected readonly auth = inject(AuthService); protected open = false; } ``` #### Fullscreen **Template:** ```html

Fullscreen heading

This is shown fullscreen regardless of content height, you can use margin-top: auto to make sure footer is at the bottom of the page.

Title
Description
Secondary title
Another description
``` **TypeScript:** ```ts import {Component, ViewEncapsulation} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiRepeatTimes} from '@taiga-ui/cdk'; import {TuiButton, TuiTitle} from '@taiga-ui/core'; import {TuiDialog} from '@taiga-ui/experimental'; import {TuiAvatar, TuiFloatingContainer, TuiProgress} from '@taiga-ui/kit'; import {TuiAppBar, TuiCell, TuiHeader} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ TuiAppBar, TuiAvatar, TuiButton, TuiCell, TuiDialog, TuiFloatingContainer, TuiHeader, TuiProgress, TuiRepeatTimes, TuiTitle, ], templateUrl: './index.html', encapsulation: ViewEncapsulation.None, changeDetection, }) export default class Example { protected fullscreen = false; protected scrollable = false; } ``` #### Customization **Template:** ```html

Augmented design

Using both built-in "taiga" appearance and custom "compact" appearance to alter built-in styles

Custom design

Overriding default appearance completely and taking the styles of dialog fully upon oneself, leaving only behavior like focus trap and closable/dismissible interactions to Taiga UI

``` **TypeScript:** ```ts import {Component, ViewEncapsulation} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiButton, TuiTitle} from '@taiga-ui/core'; import {TuiDialog} from '@taiga-ui/experimental'; import {TuiHeader} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [TuiButton, TuiDialog, TuiHeader, TuiTitle], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation: ViewEncapsulation.None, changeDetection, }) export default class Example { protected augmented = false; protected custom = false; } ``` ### TypeScript ```ts import {Component, inject, type TemplateRef} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {DemoRoute} from '@demo/routes'; import {TuiDemo} from '@demo/utils'; import {TuiAutoFocus} from '@taiga-ui/cdk'; import { TuiAlertService, TuiButton, type TuiDialogContext, TuiTextfield, } from '@taiga-ui/core'; import {TUI_DIALOG_OPTIONS, TuiDialogService} from '@taiga-ui/experimental'; import {TuiForm} from '@taiga-ui/layout'; import {switchMap} from 'rxjs'; @Component({ standalone: true, imports: [TuiAutoFocus, TuiButton, TuiDemo, TuiForm, TuiTextfield], templateUrl: './index.html', changeDetection, }) export default class Page extends Array { private readonly alerts = inject(TuiAlertService); private readonly dialogs = inject(TuiDialogService); private readonly options = inject(TUI_DIALOG_OPTIONS); protected readonly routes = DemoRoute; protected readonly examples = [ 'String', 'Directive', 'Component', 'Confirmation', 'Closing', 'Fullscreen', 'Customization', ]; protected readonly [2] = { TypeScript: import('./examples/3/index.ts?raw'), HTML: import('./examples/3/index.html?raw'), 'component.ts': import('./examples/3/component.ts?raw'), }; protected readonly [4] = { TypeScript: import('./examples/5/index.ts?raw'), HTML: import('./examples/5/index.html?raw'), 'service.ts': import('./examples/5/service.ts?raw'), }; protected data = 'Data'; protected label = 'Label'; protected closable = this.options.closable; protected required = this.options.required; protected dismissible = this.options.dismissible; protected readonly appearances = ['taiga', 'fullscreen'] as const; protected appearance = this.options.appearance; protected readonly sizes = ['s', 'm', 'l'] as const; protected size = this.options.size; protected showDialog(content: TemplateRef>): void { const {data, label, required, closable, dismissible, size, appearance} = this; this.dialogs .open(content, { data, label, required, closable, dismissible, size, appearance, }) .pipe(switchMap((response) => this.alerts.open(response))) .subscribe(); } } ``` --- # components/Drawer - **Package**: `KIT` - **Type**: components ### How to Use (Import) ```ts import {TuiPopup} from '@taiga-ui/core'; import {TuiDrawer} from '@taiga-ui/kit'; // ... @Component({ standalone: true, imports: [ // ... TuiPopup, TuiDrawer, ], // ... }) export class Example {} ``` ### How to Use (Template) ```html

Header

Content
``` ### Example ```html

Header

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Cupiditate perspiciatis exercitationem nemo velit aliquam voluptates non porro, vel, nihil laudantium sapiente ex omnis corrupti assumenda voluptatibus, architecto sequi saepe consectetur ratione qui. Beatae, sapiente explicabo velit facere repudiandae veniam et soluta quia qui expedita voluptate accusamus dolor adipisci. Illo quia sint consequatur unde nulla fuga eum officiis, impedit dolorem? Vel itaque temporibus nihil quia? Provident earum aperiam autem veritatis hic doloremque unde nesciunt accusantium nisi corrupti.

Footer
``` ### API | Property | Type | Description | |----------|-----|----------| | [direction] | `TuiHorizontalDirection` | . | | [overlay] | `boolean` | Show overlay under the drawer. | | header | `string` | tag inside the drawer. | | footer | `string` | tag inside the drawer. | ### Usage Examples #### Full **Template:** ```html

Caption・caption Drawer title Label In publishing and graphic design, Lorem ipsum is a placeholder text commonly used.

Action 2

Content

``` **TypeScript:** ```ts import {Component, signal} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiRepeatTimes} from '@taiga-ui/cdk'; import {TuiButton, TuiLink, TuiPopup, TuiTitle} from '@taiga-ui/core'; import {TuiBadge, TuiDrawer, TuiTabs} from '@taiga-ui/kit'; import {TuiHeader, TuiNavigation} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ TuiBadge, TuiButton, TuiDrawer, TuiHeader, TuiLink, TuiNavigation, TuiPopup, TuiRepeatTimes, TuiTabs, TuiTitle, ], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected readonly open = signal(false); } ``` #### Modal **Template:** ```html

Sticky header

Content

``` **TypeScript:** ```ts import {Component, inject, signal} from '@angular/core'; import {FormControl, ReactiveFormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiRepeatTimes} from '@taiga-ui/cdk'; import { TuiButton, TuiDialogService, TuiPopup, TuiTextfield, TuiTitle, } from '@taiga-ui/core'; import {TUI_CONFIRM, TuiDrawer} from '@taiga-ui/kit'; import {TuiHeader} from '@taiga-ui/layout'; import {filter} from 'rxjs'; @Component({ standalone: true, imports: [ ReactiveFormsModule, TuiButton, TuiDrawer, TuiHeader, TuiPopup, TuiRepeatTimes, TuiTextfield, TuiTitle, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly dialogs = inject(TuiDialogService); protected readonly control = new FormControl('Some value'); protected readonly open = signal(false); public onClose(): void { if (this.control.pristine) { this.open.set(false); return; } this.dialogs .open(TUI_CONFIRM, { label: 'Cancel editing form?', size: 's', data: { content: 'You have unsaved changes that will be lost', }, }) .pipe(filter(Boolean)) .subscribe(() => { this.open.set(false); this.control.reset('Some value'); }); } } ``` ### TypeScript ```ts import {Component, signal} from '@angular/core'; import {ReactiveFormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; import { TuiButton, type TuiHorizontalDirection, TuiPopup, TuiTextfield, TuiTitle, } from '@taiga-ui/core'; import {TuiDrawer} from '@taiga-ui/kit'; import {TuiHeader} from '@taiga-ui/layout'; @Component({ standalone: true, imports: [ ReactiveFormsModule, TuiButton, TuiDemo, TuiDrawer, TuiHeader, TuiPopup, TuiTextfield, TuiTitle, ], templateUrl: './index.html', changeDetection, }) export default class Page { protected readonly examples = ['Full', 'Modal']; protected readonly directionVariants: readonly TuiHorizontalDirection[] = [ 'left', 'right', ]; protected open = signal(false); protected overlay = false; protected direction: TuiHorizontalDirection = 'right'; public onClose(): void { this.open.set(false); } } ``` --- # components/ElasticContainer - **Package**: `KIT` - **Type**: components A wrapper component that changes its height with transition, depending on the content ### How to Use (Import) ```ts import {TuiElasticContainer} from '@taiga-ui/kit'; // ... @Component({ standalone: true, imports: [ // ... TuiElasticContainer, ], // ... }) export class Example {} ``` ### How to Use (Template) ```html

Title

Your content here

``` ### Usage Examples #### Show more **Template:** ```html {{ current }} ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiLink} from '@taiga-ui/core'; import {TuiElasticContainer} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiElasticContainer, TuiLink], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected readonly more = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin iaculis ipsum in elit mattis consectetur. Maecenas venenatis ligula libero, lobortis rhoncus eros aliquam a. Vivamus blandit scelerisque urna, eu euismod ipsum ultricies non. Aenean fringilla tincidunt luctus. Phasellus eleifend a enim vel aliquet. Donec accumsan orci ac nunc suscipit posuere in a turpis. Fusce hendrerit in lectus eu egestas. Donec nisl ipsum, faucibus sit amet elit eu, vehicula hendrerit purus. Duis tempus pulvinar pharetra. In volutpat, odio dictum ornare iaculis, arcu turpis blandit quam, sit amet malesuada nisl enim nec tortor. In eleifend arcu diam, ut dignissim risus elementum nec. Interdum et malesuada fames ac ante ipsum primis in faucibus. Pellentesque pellentesque elit ac feugiat posuere. Aliquam diam ante, condimentum eget nisi nec, suscipit efficitur velit. Cras sed dolor eu tortor dapibus condimentum.'; protected readonly less = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin iaculis ipsum in elit mattis consectetur. Maecenas venenatis ligula libero, lobortis rhoncus eros aliquam a. Vivamus blandit scelerisque urna, eu euismod ipsum ultricies non. Aenean fringilla tincidunt luctus. Phasellus eleifend a enim vel aliquet. Donec accumsan orci ac nunc suscipit posuere in a turpis. Fusce hendrerit in lectus eu egestas.'; protected current = this.less; protected toggle(): void { this.current = this.current === this.less ? this.more : this.less; } } ``` #### contenteditable **Template:** ```html
Editable content
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiElasticContainer} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiElasticContainer], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example {} ``` #### Add and remove content **Template:** ```html
I'm content
``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiRepeatTimes} from '@taiga-ui/cdk'; import {TuiButton} from '@taiga-ui/core'; import {TuiElasticContainer} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [TuiButton, TuiElasticContainer, TuiRepeatTimes], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected content = 1; protected add(): void { this.content++; } protected remove(): void { this.content--; } } ``` #### With animations inside **Template:** ```html

Nested form

Some input
``` **TypeScript:** ```ts import {NgForOf} from '@angular/common'; import {Component} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {tuiArrayRemove} from '@taiga-ui/cdk'; import {TuiButton, TuiExpand} from '@taiga-ui/core'; import {TuiChevron, TuiElasticContainer} from '@taiga-ui/kit'; import {TuiInputModule} from '@taiga-ui/legacy'; @Component({ standalone: true, imports: [ FormsModule, NgForOf, TuiButton, TuiChevron, TuiElasticContainer, TuiExpand, TuiInputModule, ], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected items = [ { expanded: false, value: 'Test 1', }, { expanded: false, value: 'Test 2', }, ]; protected add(): void { this.items = this.items.concat({expanded: false, value: 'New value'}); } protected remove(index: number): void { this.items = tuiArrayRemove(this.items, index); } } ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; @Component({ standalone: true, imports: [TuiDemo], templateUrl: './index.html', changeDetection, }) export default class Page {} ``` --- # components/Error - **Package**: `CORE` - **Type**: components Error allows to show an error. If you work with a form, see tuiFieldError . The idea of tui-error is to show arbitrary messages styled as errors, with height or fade transition. ### How to Use (Import) ```ts import {TuiError} from '@taiga-ui/core'; // ... @Component({ standalone: true, imports: [ // ... TuiError, ], // ... }) export class Example {} ``` ### How to Use (Template) ```html ``` ### Example ```html ``` ### API | Property | Type | Description | |----------|-----|----------| | error | `TuiValidationError | string | null` | Active state for routerLinkActive , for example | ### Usage Examples #### Basic **Template:** ```html ``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiValidationError} from '@taiga-ui/cdk'; import {TuiError, TuiLabel} from '@taiga-ui/core'; import {TuiSwitch} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [FormsModule, TuiError, TuiLabel, TuiSwitch], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected enabled = false; protected error = new TuiValidationError('An error'); protected get computedError(): TuiValidationError | null { return this.enabled ? this.error : null; } } ``` ### TypeScript ```ts import {Component, type TemplateRef, ViewChild} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; import {TuiValidationError} from '@taiga-ui/cdk'; import {TuiError} from '@taiga-ui/core'; @Component({ standalone: true, imports: [TuiDemo, TuiError], templateUrl: './index.html', changeDetection, }) export default class Page { @ViewChild('errorContent') protected errorContent?: TemplateRef>; protected readonly errorVariants: readonly string[] = [ 'Error as string', 'Error as HTML content', ]; protected selectedError = this.errorVariants[0]!; protected get error(): TuiValidationError | string | null { if (this.selectedError === null) { return null; } if (this.selectedError === this.errorVariants[0]) { return this.selectedError; } return new TuiValidationError(this.errorContent || ''); } } ``` --- # components/Expand - **Package**: `EXPERIMENTAL` - **Type**: components ### How to Use (Import) ```ts import {TuiExpand} from '@taiga-ui/experimental'; // ... @Component({ standalone: true, imports: [ // ... TuiExpand, ], // ... }) export class Example {} ``` ### How to Use (Template) ```html Eager content ``` ### Usage Examples #### Lazy **Template:** ```html

Chapman: Mr Wentworth just told me to come in here and say that there was trouble at the mill, that's all - I didn't expect a kind of Spanish Inquisition.

NOBODY expects the Spanish Inquisition!

``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiItem} from '@taiga-ui/cdk'; import {TuiButton} from '@taiga-ui/core'; import {TuiExpand} from '@taiga-ui/experimental'; @Component({ standalone: true, imports: [TuiButton, TuiExpand, TuiItem], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected expanded = false; } ``` #### Eager **Template:** ```html

I am eagerly loaded but hidden

``` **TypeScript:** ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiRepeatTimes} from '@taiga-ui/cdk'; import {TuiButton} from '@taiga-ui/core'; import {TuiExpand} from '@taiga-ui/experimental'; @Component({ standalone: true, imports: [TuiButton, TuiExpand, TuiRepeatTimes], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected expanded = false; } ``` #### Async **Template:** ```html

You can use ElasticContainer to animate height changes

Just some more content

Making this section bigger than loader
``` **TypeScript:** ```ts import {AsyncPipe, NgIf} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TUI_FALSE_HANDLER, TuiItem} from '@taiga-ui/cdk'; import {TuiButton, TuiLoader} from '@taiga-ui/core'; import {TuiExpand} from '@taiga-ui/experimental'; import {TuiElasticContainer} from '@taiga-ui/kit'; import {map, startWith, timer} from 'rxjs'; @Component({ standalone: true, imports: [ AsyncPipe, NgIf, TuiButton, TuiElasticContainer, TuiExpand, TuiItem, TuiLoader, ], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected readonly loading$ = timer(2000).pipe( map(TUI_FALSE_HANDLER), startWith(true), ); protected expanded = false; } ``` #### Old syntax **Template:** ```html

Chapman: Mr Wentworth just told me to come in here and say that there was trouble at the mill, that's all - I didn't expect a kind of Spanish Inquisition.

NOBODY expects the Spanish Inquisition!

{{ page }}
``` **TypeScript:** ```ts import {NgForOf} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiButton, TuiExpand} from '@taiga-ui/core'; @Component({ standalone: true, imports: [NgForOf, TuiButton, TuiExpand], templateUrl: './index.html', encapsulation, changeDetection, }) export default class Example { protected expanded = false; protected subpages = ['page1', 'page2', 'page3']; protected toggle(): void { this.expanded = !this.expanded; } } ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; @Component({ standalone: true, imports: [TuiDemo], templateUrl: './index.html', styleUrls: ['./index.less'], changeDetection, }) export default class Page { protected readonly examples = ['Lazy', 'Eager', 'Async', 'Old syntax']; } ``` ### LESS ```less @import '@taiga-ui/core/styles/taiga-ui-local'; .tooltip { position: relative; &:hover .bubble { opacity: 1; } } .bubble { .transition(opacity); position: absolute; left: 3.125rem; bottom: 1.875rem; inline-size: 15.625rem; background: var(--tui-text-primary); color: var(--tui-background-base); border-radius: 0.25rem; padding: 0.625rem; opacity: 0; &::after { content: ''; position: absolute; left: 50%; bottom: -0.9375rem; border-block-start: 0.9375rem solid var(--tui-text-primary); border-inline-start: 0.625rem solid transparent; border-inline-end: 0.625rem solid transparent; transform: translate(-0.625rem, 0); } } ``` --- # components/Filter - **Package**: `KIT` - **Type**: components Components shows separated items that can be used to filter content on the page. There are also an option with badges. ### How to Use (Import) ```ts import {TuiFilter} from '@taiga-ui/kit'; // ... @Component({ standalone: true, imports: [ // ... TuiFilter, ], // ... }) export class Example {} ``` ### How to Use (Template) ```html
``` ### Example ```html ``` ### API | Property | Type | Description | |----------|-----|----------| | [badgeHandler] | `TuiHandler` | to get a number to show by default | | [content] | `PolymorpheusContent` | Template for custom content in filter | | [disabledItemHandler] | `TuiBooleanHandler` | | | [identityMatcher] | `TuiIdentityMatcher` | | | [items] | `T[]` | for view | | [size] | `TuiSizeS | TuiSizeL` | Size | | (toggledItem) | `T` | Toggled event of item | ### Usage Examples #### Basic **Template:** ```html
Form value: {{ form.value | json }}
``` **TypeScript:** ```ts import {JsonPipe} from '@angular/common'; import {Component} from '@angular/core'; import {FormControl, FormGroup, ReactiveFormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {type TuiBooleanHandler} from '@taiga-ui/cdk'; import {TuiFilter} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [JsonPipe, ReactiveFormsModule, TuiFilter], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly form = new FormGroup({ filters: new FormControl(['Food']), }); protected readonly items = [ 'News', 'Food', 'Clothes', 'Popular', 'Goods', 'Furniture', 'Tech', 'Building materials', ]; protected disabledItemHandler: TuiBooleanHandler = (item) => item.length < 7; } ``` #### With badges **Template:** ```html
{{ item.title }}
Form value: {{ form.value | json }}
``` **TypeScript:** ```ts import {JsonPipe} from '@angular/common'; import {Component} from '@angular/core'; import {FormControl, FormGroup, ReactiveFormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {type TuiHandler, type TuiIdentityMatcher} from '@taiga-ui/cdk'; import {TuiFilter} from '@taiga-ui/kit'; interface Operations { operations: readonly Operation[]; title: string; } interface Operation { amount: number; } const COMPLETED = { title: 'Done', operations: [ { amount: 100, }, { amount: 200, }, ], }; @Component({ standalone: true, imports: [JsonPipe, ReactiveFormsModule, TuiFilter], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly form = new FormGroup({ filters: new FormControl([ { title: 'Drafts', }, ]), }); protected items: readonly Operations[] = [ COMPLETED, { title: 'Drafts', operations: [ { amount: 100, }, { amount: 200, }, { amount: 100, }, { amount: 100, }, ], }, { title: 'For sign', operations: [], }, { title: 'Queue', operations: [ { amount: 100, }, { amount: 200, }, { amount: 100, }, { amount: 200, }, { amount: 100, }, { amount: 200, }, ], }, ]; protected identityMatcher: TuiIdentityMatcher = ( item1: Operations, item2: Operations, ) => item1.title === item2.title; protected badgeHandler: TuiHandler = (item) => item.operations.length; } ``` #### Custom **Template:** ```html
{{ item }}
Form value: {{ form.value | json }}
``` **TypeScript:** ```ts import {JsonPipe} from '@angular/common'; import {Component} from '@angular/core'; import {FormControl, FormGroup, ReactiveFormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiIcon} from '@taiga-ui/core'; import {TuiFilter} from '@taiga-ui/kit'; const getIcon: Record = { Calendar: '@tui.calendar', Favorite: '@tui.star', Messages: '@tui.message-square', FAQ: '@tui.circle-help', Settings: '@tui.settings', }; @Component({ standalone: true, imports: [JsonPipe, ReactiveFormsModule, TuiFilter, TuiIcon], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected items = ['Calendar', 'Favorite', 'Messages', 'FAQ', 'Settings']; protected form = new FormGroup({ filters: new FormControl([]), }); protected getItemIcon(title: string): string { return getIcon[title] ?? ''; } } ``` #### With all button **Template:** ```html
Choose a department:
``` **TypeScript:** ```ts import {AsyncPipe} from '@angular/common'; import {Component} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {TuiButton} from '@taiga-ui/core'; import {TuiFilter} from '@taiga-ui/kit'; import {BehaviorSubject, map} from 'rxjs'; const Department = { IT: 'IT', HR: 'HR', HeadOffice: 'Heads', Delivery: 'Delivery', Admin: 'Administrative', Business: 'Business lines', MB: 'Business technologies', Finance: 'Corporate Finance', Payment: 'Payment Systems', Operating: 'Operating service lines', Marketing: 'Media-marketing', Security: 'Security Service', } as const; @Component({ standalone: true, imports: [AsyncPipe, FormsModule, TuiButton, TuiFilter], templateUrl: './index.html', styleUrls: ['./index.less'], encapsulation, changeDetection, }) export default class Example { protected readonly items = Object.values(Department); protected readonly filters$ = new BehaviorSubject([]); protected readonly checked$ = this.filters$.pipe( map(({length}) => (length === this.items.length ? 'checked' : '')), ); protected readonly model$ = this.filters$.pipe( map((value) => (value.length === this.items.length ? [] : value)), ); protected onModelChange(model: readonly string[]): void { this.filters$.next(model); } protected toggleAll(): void { this.filters$.next( this.items.length === this.filters$.value.length ? [] : [...this.items], ); } } ``` ### TypeScript ```ts import {Component} from '@angular/core'; import {FormControl, ReactiveFormsModule} from '@angular/forms'; import {changeDetection} from '@demo/emulate/change-detection'; import {TuiDemo} from '@demo/utils'; import {TUI_FALSE_HANDLER, type TuiBooleanHandler, type TuiHandler} from '@taiga-ui/cdk'; import {type TuiSizeL, type TuiSizeS} from '@taiga-ui/core'; import {TuiFilter} from '@taiga-ui/kit'; class ItemWithBadge { constructor( public readonly text: string, public readonly badgeValue?: number, ) {} public toString(): string { return this.text; } public valueOf(): number | null { return this.badgeValue || null; } } @Component({ standalone: true, imports: [ReactiveFormsModule, TuiDemo, TuiFilter], templateUrl: './index.html', changeDetection, }) export default class Page { protected initialItems = ['Alex Inkin', 'Roman Sedov']; protected itemsVariants: Array> = [ ['Alex Inkin', 'Roman Sedov'], [ new ItemWithBadge('Focused Zone', 10), new ItemWithBadge('Dropdown', 100), new ItemWithBadge('Menu Items', 30), new ItemWithBadge('Accordion'), ], ]; protected badgeHandlerVariants: ReadonlyArray> = [ (item) => Number(item), (item) => String(item).length, ]; protected badgeHandler = this.badgeHandlerVariants[0]!; protected disabledItemHandlerVariants: ReadonlyArray< TuiBooleanHandler > = [ TUI_FALSE_HANDLER, (item) => item === 'Roman Sedov', (item) => (Number(item.valueOf()) || 0) >= 30, ]; protected disabledItemHandler = this.disabledItemHandlerVariants[0]!; protected items = this.itemsVariants[0]!; protected control = new FormControl(this.initialItems); protected readonly sizeVariants: ReadonlyArray = ['s', 'm', 'l']; protected size = this.sizeVariants[2]!; } ``` --- # components/FloatingContainer - **Package**: `KIT` - **Type**: components FloatingContainer is a special container for creating different animated sticky footers ### How to Use (Import) ```ts // ... import {tuiFloatingContainer, TuiButton} from '@taiga-ui/kit'; @Component({ standalone: true, imports: [ // ... tuiFloatingContainer, TuiButton, ], // ... }) export class Example {} ``` ### How to Use (Template) ```html ... Some content