From 03c4be31ed825d0217b2c5afb87f1e2d527690b2 Mon Sep 17 00:00:00 2001 From: Maksim Ivanov Date: Mon, 12 Feb 2024 16:39:34 +0300 Subject: [PATCH] feat(experimental): add `tuiButtonGroup` (#6686) --- projects/demo/src/modules/app/app.routes.ts | 9 +++ projects/demo/src/modules/app/pages.ts | 6 ++ .../button-group/button-group.component.ts | 31 +++++++++ .../button-group/button-group.module.ts | 33 +++++++++ .../button-group/button-group.template.html | 59 ++++++++++++++++ .../button-group/examples/1/index.html | 44 ++++++++++++ .../button-group/examples/1/index.less | 12 ++++ .../button-group/examples/1/index.ts | 12 ++++ .../button-group/examples/2/index.html | 44 ++++++++++++ .../button-group/examples/2/index.less | 12 ++++ .../button-group/examples/2/index.ts | 12 ++++ .../button-group/examples/3/index.html | 44 ++++++++++++ .../button-group/examples/3/index.less | 24 +++++++ .../button-group/examples/3/index.ts | 12 ++++ .../examples/import/import-module.md | 14 ++++ .../examples/import/insert-template.md | 11 +++ projects/demo/used-icons.ts | 1 + .../button-group/button-group.component.ts | 12 ++++ .../button-group/button-group.directive.ts | 15 ++++ .../button-group/button-group.module.ts | 10 +++ .../button-group/button-group.style.less | 68 +++++++++++++++++++ .../directives/button-group/index.ts | 3 + .../directives/button-group/ng-package.json | 5 ++ projects/experimental/directives/index.ts | 1 + 24 files changed, 494 insertions(+) create mode 100644 projects/demo/src/modules/experimental/button-group/button-group.component.ts create mode 100644 projects/demo/src/modules/experimental/button-group/button-group.module.ts create mode 100644 projects/demo/src/modules/experimental/button-group/button-group.template.html create mode 100644 projects/demo/src/modules/experimental/button-group/examples/1/index.html create mode 100644 projects/demo/src/modules/experimental/button-group/examples/1/index.less create mode 100644 projects/demo/src/modules/experimental/button-group/examples/1/index.ts create mode 100644 projects/demo/src/modules/experimental/button-group/examples/2/index.html create mode 100644 projects/demo/src/modules/experimental/button-group/examples/2/index.less create mode 100644 projects/demo/src/modules/experimental/button-group/examples/2/index.ts create mode 100644 projects/demo/src/modules/experimental/button-group/examples/3/index.html create mode 100644 projects/demo/src/modules/experimental/button-group/examples/3/index.less create mode 100644 projects/demo/src/modules/experimental/button-group/examples/3/index.ts create mode 100644 projects/demo/src/modules/experimental/button-group/examples/import/import-module.md create mode 100644 projects/demo/src/modules/experimental/button-group/examples/import/insert-template.md create mode 100644 projects/experimental/directives/button-group/button-group.component.ts create mode 100644 projects/experimental/directives/button-group/button-group.directive.ts create mode 100644 projects/experimental/directives/button-group/button-group.module.ts create mode 100644 projects/experimental/directives/button-group/button-group.style.less create mode 100644 projects/experimental/directives/button-group/index.ts create mode 100644 projects/experimental/directives/button-group/ng-package.json diff --git a/projects/demo/src/modules/app/app.routes.ts b/projects/demo/src/modules/app/app.routes.ts index c9857721a74e..92f927d4f858 100644 --- a/projects/demo/src/modules/app/app.routes.ts +++ b/projects/demo/src/modules/app/app.routes.ts @@ -361,6 +361,15 @@ export const ROUTES: Routes = [ title: 'ButtonClose', }, }, + { + path: 'experimental/button-group', + loadChildren: async () => + (await import('../experimental/button-group/button-group.module')) + .ExampleTuiButtonGroupModule, + data: { + title: 'ButtonGroup', + }, + }, { path: 'experimental/cell', loadChildren: async () => diff --git a/projects/demo/src/modules/app/pages.ts b/projects/demo/src/modules/app/pages.ts index 0d6fd8f86cd9..766ec73c11f1 100644 --- a/projects/demo/src/modules/app/pages.ts +++ b/projects/demo/src/modules/app/pages.ts @@ -916,6 +916,12 @@ export const pages: TuiDocPages = [ keywords: 'кнопка, button, close, закрыть', route: '/experimental/button-close', }, + { + section: 'Experimental', + title: 'ButtonGroup', + keywords: 'кнопка, button, group, группа', + route: '/experimental/button-group', + }, ], }, { diff --git a/projects/demo/src/modules/experimental/button-group/button-group.component.ts b/projects/demo/src/modules/experimental/button-group/button-group.component.ts new file mode 100644 index 000000000000..45b46f5f3d2a --- /dev/null +++ b/projects/demo/src/modules/experimental/button-group/button-group.component.ts @@ -0,0 +1,31 @@ +import {Component} from '@angular/core'; +import {changeDetection} from '@demo/emulate/change-detection'; +import {TuiDocExample, TuiRawLoaderContent} from '@taiga-ui/addon-doc'; + +@Component({ + selector: 'example-button-group-card', + templateUrl: './button-group.template.html', + changeDetection, +}) +export class ExampleTuiButtonGroupComponent { + readonly exampleModule: TuiRawLoaderContent = import( + './examples/import/import-module.md?raw' + ); + + readonly exampleHtml: TuiRawLoaderContent = import( + './examples/import/insert-template.md?raw' + ); + + readonly example1: TuiDocExample = { + HTML: import('./examples/1/index.html?raw'), + }; + + readonly example2: TuiDocExample = { + HTML: import('./examples/2/index.html?raw'), + }; + + readonly example3: TuiDocExample = { + HTML: import('./examples/3/index.html?raw'), + LESS: import('./examples/3/index.less?raw'), + }; +} diff --git a/projects/demo/src/modules/experimental/button-group/button-group.module.ts b/projects/demo/src/modules/experimental/button-group/button-group.module.ts new file mode 100644 index 000000000000..f7d3e8fcf544 --- /dev/null +++ b/projects/demo/src/modules/experimental/button-group/button-group.module.ts @@ -0,0 +1,33 @@ +import {CommonModule} from '@angular/common'; +import {NgModule} from '@angular/core'; +import {tuiGetDocModules} from '@taiga-ui/addon-doc'; +import {TuiNotificationModule} from '@taiga-ui/core'; +import { + TuiButtonGroupModule, + TuiIconModule, + TuiSurfaceModule, +} from '@taiga-ui/experimental'; + +import {ExampleTuiButtonGroupComponent} from './button-group.component'; +import {TuiButtonGroupExample1} from './examples/1'; +import {TuiButtonGroupExample2} from './examples/2'; +import {TuiButtonGroupExample3} from './examples/3'; + +@NgModule({ + imports: [ + CommonModule, + TuiIconModule, + TuiSurfaceModule, + TuiNotificationModule, + TuiButtonGroupModule, + tuiGetDocModules(ExampleTuiButtonGroupComponent), + ], + declarations: [ + ExampleTuiButtonGroupComponent, + TuiButtonGroupExample1, + TuiButtonGroupExample2, + TuiButtonGroupExample3, + ], + exports: [ExampleTuiButtonGroupComponent], +}) +export class ExampleTuiButtonGroupModule {} diff --git a/projects/demo/src/modules/experimental/button-group/button-group.template.html b/projects/demo/src/modules/experimental/button-group/button-group.template.html new file mode 100644 index 000000000000..0e89a2f09802 --- /dev/null +++ b/projects/demo/src/modules/experimental/button-group/button-group.template.html @@ -0,0 +1,59 @@ + + + + This code is + experimental + and is a subject to change. Expect final solution to be shipped in the next major version + + + + + + + + + + + + + + + + +
    +
  1. +

    Import module:

    + + +
  2. + +
  3. +

    Add to the template:

    + + +
  4. +
+
+
diff --git a/projects/demo/src/modules/experimental/button-group/examples/1/index.html b/projects/demo/src/modules/experimental/button-group/examples/1/index.html new file mode 100644 index 000000000000..a62f550370fd --- /dev/null +++ b/projects/demo/src/modules/experimental/button-group/examples/1/index.html @@ -0,0 +1,44 @@ +
+ + + + + +
+ +
+ + + +
+ +
+ +
diff --git a/projects/demo/src/modules/experimental/button-group/examples/1/index.less b/projects/demo/src/modules/experimental/button-group/examples/1/index.less new file mode 100644 index 000000000000..1aae53ea422f --- /dev/null +++ b/projects/demo/src/modules/experimental/button-group/examples/1/index.less @@ -0,0 +1,12 @@ +@import '@taiga-ui/core/styles/taiga-ui-local'; + +:host { + display: flex; + flex-direction: column; + gap: 1rem; + width: 21.5625rem; + + @media @tui-mobile { + width: 100%; + } +} diff --git a/projects/demo/src/modules/experimental/button-group/examples/1/index.ts b/projects/demo/src/modules/experimental/button-group/examples/1/index.ts new file mode 100644 index 000000000000..3cefd7843236 --- /dev/null +++ b/projects/demo/src/modules/experimental/button-group/examples/1/index.ts @@ -0,0 +1,12 @@ +import {Component} from '@angular/core'; +import {changeDetection} from '@demo/emulate/change-detection'; +import {encapsulation} from '@demo/emulate/encapsulation'; + +@Component({ + selector: 'tui-button-group-example-1', + templateUrl: './index.html', + styleUrls: ['./index.less'], + encapsulation, + changeDetection, +}) +export class TuiButtonGroupExample1 {} diff --git a/projects/demo/src/modules/experimental/button-group/examples/2/index.html b/projects/demo/src/modules/experimental/button-group/examples/2/index.html new file mode 100644 index 000000000000..1e97a3cb5d3e --- /dev/null +++ b/projects/demo/src/modules/experimental/button-group/examples/2/index.html @@ -0,0 +1,44 @@ +
+ + + + + +
+ +
+ + + +
+ +
+ +
diff --git a/projects/demo/src/modules/experimental/button-group/examples/2/index.less b/projects/demo/src/modules/experimental/button-group/examples/2/index.less new file mode 100644 index 000000000000..1aae53ea422f --- /dev/null +++ b/projects/demo/src/modules/experimental/button-group/examples/2/index.less @@ -0,0 +1,12 @@ +@import '@taiga-ui/core/styles/taiga-ui-local'; + +:host { + display: flex; + flex-direction: column; + gap: 1rem; + width: 21.5625rem; + + @media @tui-mobile { + width: 100%; + } +} diff --git a/projects/demo/src/modules/experimental/button-group/examples/2/index.ts b/projects/demo/src/modules/experimental/button-group/examples/2/index.ts new file mode 100644 index 000000000000..8decc0e110e8 --- /dev/null +++ b/projects/demo/src/modules/experimental/button-group/examples/2/index.ts @@ -0,0 +1,12 @@ +import {Component} from '@angular/core'; +import {changeDetection} from '@demo/emulate/change-detection'; +import {encapsulation} from '@demo/emulate/encapsulation'; + +@Component({ + selector: 'tui-button-group-example-2', + templateUrl: './index.html', + styleUrls: ['./index.less'], + encapsulation, + changeDetection, +}) +export class TuiButtonGroupExample2 {} diff --git a/projects/demo/src/modules/experimental/button-group/examples/3/index.html b/projects/demo/src/modules/experimental/button-group/examples/3/index.html new file mode 100644 index 000000000000..5ceece8e95cd --- /dev/null +++ b/projects/demo/src/modules/experimental/button-group/examples/3/index.html @@ -0,0 +1,44 @@ +
+ + + + + +
+ +
+ + + +
+ +
+ +
diff --git a/projects/demo/src/modules/experimental/button-group/examples/3/index.less b/projects/demo/src/modules/experimental/button-group/examples/3/index.less new file mode 100644 index 000000000000..78a3cab2a94e --- /dev/null +++ b/projects/demo/src/modules/experimental/button-group/examples/3/index.less @@ -0,0 +1,24 @@ +@import '@taiga-ui/core/styles/taiga-ui-local'; + +:host { + display: flex; + flex-direction: column; + gap: 1rem; + width: 21.5625rem; + + @media @tui-mobile { + width: 100%; + } +} + +[tuiSurface][data-surface='dark'] { + background: linear-gradient(334.83deg, #7d8ca0 0%, #647382 100%); + + button { + color: #fff; + + &:active { + --tui-clear: var(--tui-clear-inverse); + } + } +} diff --git a/projects/demo/src/modules/experimental/button-group/examples/3/index.ts b/projects/demo/src/modules/experimental/button-group/examples/3/index.ts new file mode 100644 index 000000000000..052c8d9a8791 --- /dev/null +++ b/projects/demo/src/modules/experimental/button-group/examples/3/index.ts @@ -0,0 +1,12 @@ +import {Component} from '@angular/core'; +import {changeDetection} from '@demo/emulate/change-detection'; +import {encapsulation} from '@demo/emulate/encapsulation'; + +@Component({ + selector: 'tui-button-group-example-3', + templateUrl: './index.html', + styleUrls: ['./index.less'], + encapsulation, + changeDetection, +}) +export class TuiButtonGroupExample3 {} diff --git a/projects/demo/src/modules/experimental/button-group/examples/import/import-module.md b/projects/demo/src/modules/experimental/button-group/examples/import/import-module.md new file mode 100644 index 000000000000..99e96d5f8c09 --- /dev/null +++ b/projects/demo/src/modules/experimental/button-group/examples/import/import-module.md @@ -0,0 +1,14 @@ +```ts +import {NgModule} from '@angular/core'; +import {TuiButtonGroupModule} from '@taiga-ui/experimental'; +// ... + +@NgModule({ + imports: [ + // ... + TuiButtonModule, + TuiButtonGroupModule, + ], +}) +export class MyModule {} +``` diff --git a/projects/demo/src/modules/experimental/button-group/examples/import/insert-template.md b/projects/demo/src/modules/experimental/button-group/examples/import/insert-template.md new file mode 100644 index 000000000000..167985df77d9 --- /dev/null +++ b/projects/demo/src/modules/experimental/button-group/examples/import/insert-template.md @@ -0,0 +1,11 @@ +```html +
+ +
+``` diff --git a/projects/demo/used-icons.ts b/projects/demo/used-icons.ts index 99021f8b7594..8ccf0a2845c8 100644 --- a/projects/demo/used-icons.ts +++ b/projects/demo/used-icons.ts @@ -101,6 +101,7 @@ export const TUI_USED_ICONS = [ 'tuiIconLock', 'tuiIconUsers', 'tuiIconClock', + 'tuiIconArrowRightCircleLarge', 'tuiIconPlusSquareLarge', 'tuiIconTarget', 'tuiIconGooglePay', diff --git a/projects/experimental/directives/button-group/button-group.component.ts b/projects/experimental/directives/button-group/button-group.component.ts new file mode 100644 index 000000000000..d1385ce579b1 --- /dev/null +++ b/projects/experimental/directives/button-group/button-group.component.ts @@ -0,0 +1,12 @@ +import {ChangeDetectionStrategy, Component, ViewEncapsulation} from '@angular/core'; + +@Component({ + template: '', + styleUrls: ['./button-group.style.less'], + encapsulation: ViewEncapsulation.None, + changeDetection: ChangeDetectionStrategy.OnPush, + host: { + class: 'tui-button-group-styles', + }, +}) +export class TuiButtonGroupComponent {} diff --git a/projects/experimental/directives/button-group/button-group.directive.ts b/projects/experimental/directives/button-group/button-group.directive.ts new file mode 100644 index 000000000000..a9df64a25d55 --- /dev/null +++ b/projects/experimental/directives/button-group/button-group.directive.ts @@ -0,0 +1,15 @@ +import {Directive, Inject} from '@angular/core'; +import {TuiDirectiveStylesService} from '@taiga-ui/cdk'; + +import {TuiButtonGroupComponent} from './button-group.component'; + +@Directive({ + selector: '[tuiButtonGroup]', +}) +export class TuiButtonGroupDirective { + constructor( + @Inject(TuiDirectiveStylesService) directiveStyles: TuiDirectiveStylesService, + ) { + directiveStyles.addComponent(TuiButtonGroupComponent); + } +} diff --git a/projects/experimental/directives/button-group/button-group.module.ts b/projects/experimental/directives/button-group/button-group.module.ts new file mode 100644 index 000000000000..b06322d26f43 --- /dev/null +++ b/projects/experimental/directives/button-group/button-group.module.ts @@ -0,0 +1,10 @@ +import {NgModule} from '@angular/core'; + +import {TuiButtonGroupComponent} from './button-group.component'; +import {TuiButtonGroupDirective} from './button-group.directive'; + +@NgModule({ + declarations: [TuiButtonGroupDirective, TuiButtonGroupComponent], + exports: [TuiButtonGroupDirective], +}) +export class TuiButtonGroupModule {} diff --git a/projects/experimental/directives/button-group/button-group.style.less b/projects/experimental/directives/button-group/button-group.style.less new file mode 100644 index 000000000000..9d8ad9b9604b --- /dev/null +++ b/projects/experimental/directives/button-group/button-group.style.less @@ -0,0 +1,68 @@ +@import '@taiga-ui/core/styles/taiga-ui-local'; + +[tuiButtonGroup] { + display: flex; + border-radius: var(--tui-radius-xl); + justify-content: center; + overflow: hidden; + + > button, + > a { + .transition(background); + position: relative; + display: flex; + border: none; + outline: none; + background: transparent; + align-items: center; + flex: 1; + flex-direction: column; + padding: 1.125rem 0.25rem; + gap: 0.5rem; + font-size: var(--tui-font-text-s); + max-width: calc(50% - 1.75rem); + cursor: pointer; + color: var(--tui-link); + text-align: center; + + &:active { + background: var(--tui-clear); + } + + &:before, + &:after { + position: absolute; + top: 0; + background: inherit; + width: 1.75rem; + height: 100%; + } + + &:first-child::before { + content: ''; + left: -1.75rem; + } + + &:last-child::after { + content: ''; + right: -1.75rem; + } + + tui-icon { + font-size: 1.75rem; + } + } + + &:has(button:only-child) { + border-radius: var(--tui-radius-l); + } + + > button:only-child, + > a:only-child { + width: 100%; + flex-direction: row; + font: var(--tui-font-text-l); + max-width: 100%; + justify-content: center; + } +} diff --git a/projects/experimental/directives/button-group/index.ts b/projects/experimental/directives/button-group/index.ts new file mode 100644 index 000000000000..0c4cf1d35827 --- /dev/null +++ b/projects/experimental/directives/button-group/index.ts @@ -0,0 +1,3 @@ +export * from './button-group.component'; +export * from './button-group.directive'; +export * from './button-group.module'; diff --git a/projects/experimental/directives/button-group/ng-package.json b/projects/experimental/directives/button-group/ng-package.json new file mode 100644 index 000000000000..bebf62dcb5e5 --- /dev/null +++ b/projects/experimental/directives/button-group/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "index.ts" + } +} diff --git a/projects/experimental/directives/index.ts b/projects/experimental/directives/index.ts index 78a556d9b6c2..7d2856ccfe8b 100644 --- a/projects/experimental/directives/index.ts +++ b/projects/experimental/directives/index.ts @@ -1,5 +1,6 @@ export * from '@taiga-ui/experimental/directives/appearance'; export * from '@taiga-ui/experimental/directives/button-close'; +export * from '@taiga-ui/experimental/directives/button-group'; export * from '@taiga-ui/experimental/directives/button-vertical'; export * from '@taiga-ui/experimental/directives/card'; export * from '@taiga-ui/experimental/directives/cell';