diff --git a/projects/addon-table/components/table/directives/table.directive.ts b/projects/addon-table/components/table/directives/table.directive.ts index 497fee90d1e2..9b543b803128 100644 --- a/projects/addon-table/components/table/directives/table.directive.ts +++ b/projects/addon-table/components/table/directives/table.directive.ts @@ -1,16 +1,19 @@ import { AfterViewInit, + ChangeDetectionStrategy, ChangeDetectorRef, + Component, Directive, EventEmitter, HostBinding, Inject, Input, Output, + ViewEncapsulation, } from '@angular/core'; import {IntersectionObserverService} from '@ng-web-apis/intersection-observer'; import {TuiComparator} from '@taiga-ui/addon-table/types'; -import {AbstractTuiController} from '@taiga-ui/cdk'; +import {AbstractTuiController, TuiDirectiveStylesService} from '@taiga-ui/cdk'; import {TUI_MODE, TuiBrightness} from '@taiga-ui/core'; import {Observable} from 'rxjs'; @@ -18,6 +21,17 @@ import {TUI_STUCK} from '../providers/stuck.provider'; import {TUI_TABLE_PROVIDERS} from '../providers/table.providers'; import {TUI_TABLE_OPTIONS, TuiTableOptions} from '../table.options'; +@Component({ + template: '', + styleUrls: ['./table.style.less'], + encapsulation: ViewEncapsulation.None, + changeDetection: ChangeDetectionStrategy.OnPush, + host: { + class: 'tui-table', + }, +}) +class TuiTableStylesComponent {} + @Directive({ selector: 'table[tuiTable]', providers: TUI_TABLE_PROVIDERS, @@ -54,8 +68,10 @@ export class TuiTableDirective>> @Inject(TUI_STUCK) readonly stuck$: Observable, @Inject(TUI_TABLE_OPTIONS) private readonly options: TuiTableOptions, @Inject(ChangeDetectorRef) private readonly cdr: ChangeDetectorRef, + @Inject(TuiDirectiveStylesService) directiveStyles: TuiDirectiveStylesService, ) { super(); + directiveStyles.addComponent(TuiTableStylesComponent); } @Input() diff --git a/projects/addon-table/components/table/directives/table.style.less b/projects/addon-table/components/table/directives/table.style.less new file mode 100644 index 000000000000..84cdbd2d3c8f --- /dev/null +++ b/projects/addon-table/components/table/directives/table.style.less @@ -0,0 +1,23 @@ +table[tuiTable] { + [tuiCell] { + padding: 0; + } + + [tuiTitle] { + white-space: nowrap; + + tui-icon { + font-size: 1rem; + } + } + + [tuiSubtitle] { + color: var(--tui-text-02); + } + + [tuiTh] [tuiCell], + [tuiTh] [tuiTitle] { + font: inherit; + color: inherit; + } +} diff --git a/projects/addon-table/components/table/td/td.component.ts b/projects/addon-table/components/table/td/td.component.ts index 6c1c3c33936e..ef0271cf9472 100644 --- a/projects/addon-table/components/table/td/td.component.ts +++ b/projects/addon-table/components/table/td/td.component.ts @@ -1,10 +1,5 @@ -import { - ChangeDetectionStrategy, - Component, - ContentChild, - HostBinding, -} from '@angular/core'; -import {NgControl} from '@angular/forms'; +import {ChangeDetectionStrategy, Component, ContentChild} from '@angular/core'; +import {AbstractTuiControl} from '@taiga-ui/cdk'; @Component({ selector: 'th[tuiTd], td[tuiTd]', @@ -13,9 +8,11 @@ import {NgControl} from '@angular/forms'; `, styleUrls: ['./td.style.less'], changeDetection: ChangeDetectionStrategy.OnPush, + host: { + '[class._editable]': 'legacy', + }, }) export class TuiTdComponent { - @HostBinding('class._editable') - @ContentChild(NgControl) - readonly control: unknown; + @ContentChild(AbstractTuiControl) + protected readonly legacy: unknown; } diff --git a/projects/addon-table/components/table/td/td.style.less b/projects/addon-table/components/table/td/td.style.less index 7f2b367e2c54..25e6e5e9f4c7 100644 --- a/projects/addon-table/components/table/td/td.style.less +++ b/projects/addon-table/components/table/td/td.style.less @@ -2,20 +2,22 @@ :host { position: relative; - height: var(--tui-height-m); - font: var(--tui-font-text-s); text-align: left; - padding: 0 0.75rem; background: var(--tui-base-01); border: 1px solid var(--tui-base-04); border-top: none; box-sizing: border-box; // Create new viewport for fixed positioning filter: opacity(1); + .safari-only({ transform: translate3d(0, 0, 0); }); + &._editable { + padding: 0 !important; + } + &:first-child { left: 0; } @@ -71,13 +73,19 @@ :host-context(table[data-size='l']) { font: var(--tui-font-text-m); height: var(--tui-height-l); - // Don't affect vertical padding for easier override - padding-left: 1rem; - padding-right: 1rem; + padding: 1rem; +} - &._editable { - padding: 0; - } +:host-context(table[data-size='m']) { + height: var(--tui-height-m); + font: var(--tui-font-text-s); + padding: 0.75rem; +} + +:host-context(table[data-size='s']) { + height: var(--tui-height-s); + font: var(--tui-font-text-s); + padding: 0.25rem 0.5rem; } :host(td) { diff --git a/projects/addon-table/components/table/th/th.style.less b/projects/addon-table/components/table/th/th.style.less index 0e32c2b92c58..48f5c8e2267d 100644 --- a/projects/addon-table/components/table/th/th.style.less +++ b/projects/addon-table/components/table/th/th.style.less @@ -17,6 +17,7 @@ border: 1px solid var(--tui-base-04); // Create new viewport for fixed positioning filter: opacity(1); + .safari-only({ transform: translate3d(0, 0, 0); }); @@ -64,6 +65,13 @@ padding: 0 1rem; } +:host-context(table[data-size='s']) { + height: var(--tui-height-s); + font: var(--tui-font-text-s); + font-weight: bold; + padding: 0 0.5rem; +} + :host-context(thead[tuiThead]) { position: sticky; } diff --git a/projects/demo/src/modules/tables/table/examples/2/index.html b/projects/demo/src/modules/tables/table/examples/2/index.html index ad8c24309fb5..247c139dc43c 100644 --- a/projects/demo/src/modules/tables/table/examples/2/index.html +++ b/projects/demo/src/modules/tables/table/examples/2/index.html @@ -1,100 +1,162 @@ +
+ + + {{ value === 's' ? 'Small' : value === 'm' ? 'Medium' : 'Large' }} + +
+ - - - - + + + + - + + - - - + + - - - - + + diff --git a/projects/demo/src/modules/tables/table/examples/2/index.less b/projects/demo/src/modules/tables/table/examples/2/index.less index f4a340214e69..276bbcd15317 100644 --- a/projects/demo/src/modules/tables/table/examples/2/index.less +++ b/projects/demo/src/modules/tables/table/examples/2/index.less @@ -1,50 +1,15 @@ -@import '@taiga-ui/core/styles/taiga-ui-local'; - -td, -th { - white-space: nowrap; - border-color: transparent; - border-right-color: var(--tui-base-04); - - &:last-child { - border-right-color: transparent; - } -} - -tbody { - border-color: transparent; -} - -tr:nth-child(even) td { - background: var(--tui-base-02); +[tuiTh], +[tuiTd] { + border-inline-start: none; + border-inline-end: none; } -.alive, -.deceased { - display: flex; - align-items: center; - text-transform: capitalize; - - &:before { - content: ''; - width: 0.5rem; - height: 0.5rem; - border-radius: 100%; - margin-right: 0.5rem; - background: var(--tui-base-04); - } +[tuiTable][data-size='s'] [tuiTitle] { + flex-direction: row; + gap: 0.375rem; } -.alive:before { - background: var(--tui-success-fill); -} - -.remove { - .transition(opacity); - opacity: 0; - - tr:hover &, - tr:focus-within & { - opacity: 1; - } +[tuiTd] > tui-items-with-more { + gap: 0.25rem; + max-width: 110px; } diff --git a/projects/demo/src/modules/tables/table/examples/2/index.ts b/projects/demo/src/modules/tables/table/examples/2/index.ts index 4ecc4605d9c1..a09c27491931 100644 --- a/projects/demo/src/modules/tables/table/examples/2/index.ts +++ b/projects/demo/src/modules/tables/table/examples/2/index.ts @@ -1,14 +1,6 @@ import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; -import {BehaviorSubject} from 'rxjs'; - -interface User { - readonly email: string; - readonly name: string; - readonly status: 'alive' | 'deceased'; - readonly tags: readonly string[]; -} @Component({ selector: 'tui-table-example-2', @@ -18,50 +10,89 @@ interface User { changeDetection, }) export class TuiTableExample2 { - readonly columns = ['name', 'email', 'status', 'tags', 'actions']; + readonly sizes = ['l', 'm', 's'] as const; - readonly users$ = new BehaviorSubject([ - { - name: 'Michael Palin', - email: 'm.palin@montypython.com', - status: 'alive', - tags: ['Funny'], - }, - { - name: 'Eric Idle', - email: 'e.idle@montypython.com', - status: 'alive', - tags: ['Funny', 'Music'], - }, - { - name: 'John Cleese', - email: 'j.cleese@montypython.com', - status: 'alive', - tags: ['Funny', 'Tall', 'Actor'], - }, + size = this.sizes[0]; + + readonly data = [ { - name: 'Terry Jones', - email: '', - status: 'deceased', - tags: ['Funny', 'Director'], + checkbox: { + title: 'Data point 1', + subtitle: 'The first element', + }, + title: { + icon: 'tuiIconFile', + title: 'This is title', + chip: 'Chip', + subtitle: 'More information ・ Data', + }, + cell: { + name: 'John Cleese', + email: 'silly@walk.uk', + }, + status: { + value: 'Success', + color: 'var(--tui-success-fill)', + }, + items: ['Some', 'items', 'displayed', 'here', 'and', 'can', 'overflow'], + progress: 78, + selected: false, }, { - name: 'Terry Gilliam', - email: 't.gilliam@montypython.com', - status: 'alive', - tags: ['Funny', 'Director'], + checkbox: { + title: 'Some title', + subtitle: 'Some more text', + }, + title: { + icon: 'tuiIconHeart', + title: 'More info', + chip: 'Chips can be here', + }, + cell: { + name: 'Eric Idle', + email: 'cool@dude.com', + }, + status: { + value: 'Failure', + color: 'var(--tui-error-fill)', + }, + items: ['One', 'Item'], + progress: 91, + selected: false, }, { - name: 'Graham Chapman', - email: '', - status: 'deceased', - tags: ['Funny', 'King Arthur'], + checkbox: { + title: 'And now', + subtitle: 'Completely different', + }, + title: { + icon: 'tuiIconStar', + title: 'Wow', + }, + cell: { + name: 'Michael Palin', + email: 'its@man.com', + }, + status: { + value: 'Pending', + color: 'var(--tui-warning-fill)', + }, + items: [], + progress: 32, + selected: false, }, - ]); + ]; - remove(item: User): void { - const users = this.users$.getValue().filter(user => user !== item); + get checked(): boolean | null { + const every = this.data.every(({selected}) => selected); + const some = this.data.some(({selected}) => selected); + + return every || (some && null); + } - this.users$.next(users); + onCheck(checked: boolean): void { + this.data.forEach(item => { + item.selected = checked; + }); } } diff --git a/projects/demo/src/modules/tables/table/table.module.ts b/projects/demo/src/modules/tables/table/table.module.ts index aaf17861d195..e116011c00f1 100644 --- a/projects/demo/src/modules/tables/table/table.module.ts +++ b/projects/demo/src/modules/tables/table/table.module.ts @@ -14,6 +14,7 @@ import {TuiLetModule, TuiValidatorModule} from '@taiga-ui/cdk'; import { TuiButtonModule, TuiDataListModule, + TuiDropdownModule, TuiFormatNumberPipeModule, TuiHostedDropdownModule, TuiLinkModule, @@ -23,14 +24,29 @@ import { TuiSvgModule, TuiTextfieldControllerModule, } from '@taiga-ui/core'; +import { + TuiAppearanceModule, + TuiAutoColorModule, + TuiAvatarModule, + TuiCellModule, + TuiCheckboxModule, + TuiIconModule, + TuiInitialsModule, + TuiStatusModule, + TuiTitleModule, +} from '@taiga-ui/experimental'; import { TuiAccordionModule, TuiArrowModule, + TuiBadgeModule, TuiDataListWrapperModule, TuiInputCountModule, TuiInputDateModule, TuiInputModule, TuiInputNumberModule, + TuiItemsWithMoreModule, + TuiProgressModule, + TuiRadioListModule, TuiSelectModule, TuiTagModule, TuiTextareaModule, @@ -51,6 +67,11 @@ import {ExampleTuiTableComponent} from './table.component'; ReactiveFormsModule, ScrollingModule, IntersectionObserverModule, + TuiRadioListModule, + TuiAvatarModule, + TuiDropdownModule, + TuiBadgeModule, + TuiItemsWithMoreModule, TuiNotificationModule, TuiScrollbarModule, TuiTableModule, @@ -76,6 +97,15 @@ import {ExampleTuiTableComponent} from './table.component'; TuiHostedDropdownModule, TuiArrowModule, TuiReorderModule, + TuiCellModule, + TuiIconModule, + TuiInitialsModule, + TuiAutoColorModule, + TuiProgressModule, + TuiCheckboxModule, + TuiTitleModule, + TuiStatusModule, + TuiAppearanceModule, TuiAddonDocModule, RouterModule.forChild(tuiGenerateRoutes(ExampleTuiTableComponent)), ], diff --git a/projects/demo/used-icons.ts b/projects/demo/used-icons.ts index 5f7cfcff85af..7a6abb976d7f 100644 --- a/projects/demo/used-icons.ts +++ b/projects/demo/used-icons.ts @@ -161,4 +161,5 @@ export const TUI_USED_ICONS = [ 'tuiIconAmazonPay', 'tuiIconAndroidPay', 'tuiIconPaperclipLarge', + 'tuiIconFile', ] as const;
- Name - - E-mail - - Status +
+
+ + Checkbox +
TitleCellStatus - Tags + Items ProgressActions
- {{ index + 1 }}. {{ item.name }} +
+
+ + + {{ item.checkbox.title }} + {{ item.checkbox.subtitle }} + +
- - {{ item.email }} - + +
+ + + + {{ item.title.title }} + + + + + + {{ item.title.subtitle }} + + + +
-
{{ item.status }}
+
+
+ + + {{ item.cell.name }} + {{ item.cell.email }} + +
- + + {{ item.status.value }} - + + + + + + + + + + + + + {{ item.progress }}ms + + + + + +