Skip to content

Commit

Permalink
feat(kit): Toggle allow configuring default options (#635)
Browse files Browse the repository at this point in the history
Co-authored-by: Dima Karimov <[email protected]>
  • Loading branch information
2 people authored and splincode committed Sep 21, 2021
1 parent bf146ff commit 46b7ca8
Show file tree
Hide file tree
Showing 13 changed files with 295 additions and 24 deletions.
11 changes: 11 additions & 0 deletions projects/demo/src/modules/components/toggle/examples/2/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<form [formGroup]="testForm">
<div>
<tui-toggle formControlName="testValue1"></tui-toggle>
<tui-toggle
class="tui-space_left-1"
formControlName="testValue2"
size="l"
>
</tui-toggle>
</div>
</form>
41 changes: 41 additions & 0 deletions projects/demo/src/modules/components/toggle/examples/2/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import {Component} from '@angular/core';
import {FormControl, FormGroup} from '@angular/forms';
import {
ToggleOptions,
TUI_TOGGLE_DEFAULT_OPTIONS,
TUI_TOGGLE_OPTIONS,
} from '@taiga-ui/kit';
import {changeDetection} from '../../../../../change-detection-strategy';
import {encapsulation} from '../../../../../view-encapsulation';

const options: Partial<ToggleOptions> = {
icons: {
toggleOff: ({$implicit}) =>
$implicit === 'm' ? 'tuiIconChevronRight' : 'tuiIconChevronRightLarge',
toggleOn: ({$implicit}) =>
$implicit === 'm' ? 'tuiIconChevronLeft' : 'tuiIconChevronLeftLarge',
},
showIcons: true,
};

@Component({
selector: 'tui-toggle-example-2',
templateUrl: './index.html',
changeDetection,
encapsulation,
providers: [
{
provide: TUI_TOGGLE_OPTIONS,
useValue: {
...TUI_TOGGLE_DEFAULT_OPTIONS,
...options,
},
},
],
})
export class TuiToggleExample2 {
testForm = new FormGroup({
testValue1: new FormControl(true),
testValue2: new FormControl(false),
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {
ToggleOptions,
TUI_TOGGLE_DEFAULT_OPTIONS,
TUI_TOGGLE_OPTIONS,
} from '@taiga-ui/kit';

...
const options: Partial<ToggleOptions> = {
icons: {
toggleOff: ({$implicit}) =>
$implicit === 'm' ? 'tuiIconChevronRight' : 'tuiIconChevronRightLarge',
toggleOn: ({$implicit}) =>
$implicit === 'm' ? 'tuiIconChevronLeft' : 'tuiIconChevronLeftLarge',
},
};

@NgModule({
providers: [{
provide: TUI_TOGGLE_OPTIONS,
useValue: {
...TUI_TOGGLE_DEFAULT_OPTIONS,
...options,
}
}],
...
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import {default as example1Html} from '!!raw-loader!./examples/1/index.html';
import {default as example1Ts} from '!!raw-loader!./examples/1/index.ts';
import {default as example2Html} from '!!raw-loader!./examples/2/index.html';
import {default as example2Ts} from '!!raw-loader!./examples/2/index.ts';

import {default as exampleDeclareForm} from '!!raw-loader!./examples/import/declare-form.txt';
import {default as exampleDefineOptions} from '!!raw-loader!./examples/import/define-options.txt';
import {default as exampleImportModule} from '!!raw-loader!./examples/import/import-module.txt';
import {default as exampleInsertTemplate} from '!!raw-loader!./examples/import/insert-template.txt';

Expand All @@ -28,12 +31,18 @@ export class ExampleTuiToggleComponent extends AbstractExampleTuiInteractive {
readonly exampleDeclareForm = exampleDeclareForm;
readonly exampleImportModule = exampleImportModule;
readonly exampleInsertTemplate = exampleInsertTemplate;
readonly exampleDefineOptions = exampleDefineOptions;

readonly example1: FrontEndExample = {
TypeScript: example1Ts,
HTML: example1Html,
};

readonly example2: FrontEndExample = {
TypeScript: example2Ts,
HTML: example2Html,
};

showIcons = false;

showLoader = false;
Expand Down
3 changes: 2 additions & 1 deletion projects/demo/src/modules/components/toggle/toggle.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {generateRoutes, TuiAddonDocModule} from '@taiga-ui/addon-doc';
import {TuiToggleModule} from '@taiga-ui/kit';
import {InheritedDocumentationModule} from '../abstract/inherited-documentation/inherited-documentation.module';
import {TuiToggleExample1} from './examples/1';
import {TuiToggleExample2} from './examples/2';
import {ExampleTuiToggleComponent} from './toggle.component';

@NgModule({
Expand All @@ -18,7 +19,7 @@ import {ExampleTuiToggleComponent} from './toggle.component';
CommonModule,
RouterModule.forChild(generateRoutes(ExampleTuiToggleComponent)),
],
declarations: [ExampleTuiToggleComponent, TuiToggleExample1],
declarations: [ExampleTuiToggleComponent, TuiToggleExample1, TuiToggleExample2],
exports: [ExampleTuiToggleComponent],
})
export class ExampleTuiToggleModule {}
22 changes: 22 additions & 0 deletions projects/demo/src/modules/components/toggle/toggle.template.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@
>
<tui-toggle-example-1></tui-toggle-example-1>
</tui-doc-example>

<tui-doc-example
id="options"
i18n-heading
heading="options"
[content]="example2"
>
<tui-toggle-example-2></tui-toggle-example-2>
</tui-doc-example>
</ng-template>

<ng-template pageTab>
Expand Down Expand Up @@ -112,6 +121,19 @@
[code]="exampleInsertTemplate"
></tui-doc-code>
</li>

<li>
<p i18n>
Optionally use the
<code>TUI_TOGGLE_OPTIONS</code> injection token to override
the default options for the component.
</p>

<tui-doc-code
filename="myComponent.module.ts"
[code]="exampleDefineOptions"
></tui-doc-code>
</li>
</ol>
</ng-template>
</tui-doc-page>
1 change: 1 addition & 0 deletions projects/kit/components/toggle/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './toggle-options';
export * from './toggle.component';
export * from './toggle.module';
96 changes: 96 additions & 0 deletions projects/kit/components/toggle/test/toggle.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {ComponentFixture, TestBed} from '@angular/core/testing';
import {FormControl, ReactiveFormsModule} from '@angular/forms';
import {PageObject} from '@taiga-ui/testing';
import {configureTestSuite} from 'ng-bullet';
import {TUI_TOGGLE_DEFAULT_OPTIONS, TUI_TOGGLE_OPTIONS} from '../toggle-options';
import {TuiToggleModule} from '../toggle.module';

describe('Toggle', () => {
Expand Down Expand Up @@ -207,3 +208,98 @@ describe('Toggle', () => {
}
}
});

describe('Toggle with TUI_TOGGLE_OPTIONS', () => {
@Component({
template: `
<tui-toggle [formControl]="control" [showLoader]="showLoader"> </tui-toggle>
`,
})
class TestComponent {
control = new FormControl();
showLoader = false;
}

let fixture: ComponentFixture<TestComponent>;
let testComponent: TestComponent;
let pageObject: PageObject<TestComponent>;
const testContext = {
get prefix() {
return 'tui-toggle__';
},
};

configureTestSuite(() => {
TestBed.configureTestingModule({
imports: [ReactiveFormsModule, TuiToggleModule],
declarations: [TestComponent],
providers: [
{
provide: TUI_TOGGLE_OPTIONS,
useValue: {
...TUI_TOGGLE_DEFAULT_OPTIONS,
showIcons: true,
},
},
],
});
});

beforeEach(() => {
fixture = TestBed.createComponent(TestComponent);
pageObject = new PageObject(fixture);
testComponent = fixture.componentInstance;
});

describe('Icons', () => {
describe('showIcons === true', () => {
it('Icons are shown when toggle is "disabled"', () => {
testComponent.control.setValue(false);
fixture.detectChanges();

// If icons are enabled, then both are added to the DOM at once -
// implementation feature for smooth animation
isIconVisible(`${testContext.prefix}check-icon`);
isIconVisible(`${testContext.prefix}cancel-icon`);
});

it('Icons are shown when toggle is "on"', () => {
testComponent.control.setValue(true);
fixture.detectChanges();

isIconVisible(`${testContext.prefix}check-icon`);
isIconVisible(`${testContext.prefix}cancel-icon`);
});
});
});

describe('Loader', () => {
describe('showLoader === false', () => {
beforeEach(() => {
testComponent.showLoader = false;
});

it('Icons are shown when toggle is "disabled"', () => {
testComponent.control.setValue(false);
fixture.detectChanges();

isIconVisible(`${testContext.prefix}check-icon`);
isIconVisible(`${testContext.prefix}cancel-icon`);
});

it('Icons are shown when toggle is "on"', () => {
testComponent.control.setValue(true);
fixture.detectChanges();

isIconVisible(`${testContext.prefix}check-icon`);
isIconVisible(`${testContext.prefix}cancel-icon`);
});
});
});

function isIconVisible(tuiIconAutomationId: string) {
const icon = pageObject.getByAutomationId(tuiIconAutomationId);

expect(icon).not.toBeNull();
}
});
36 changes: 36 additions & 0 deletions projects/kit/components/toggle/toggle-options.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import {InjectionToken} from '@angular/core';
import {TuiContextWithImplicit} from '@taiga-ui/cdk';
import {TuiSizeL} from '@taiga-ui/core';
import {PolymorpheusContent} from '@tinkoff/ng-polymorpheus';

export interface ToggleOptions {
readonly icons: Readonly<{
toggleOff: PolymorpheusContent<TuiContextWithImplicit<TuiSizeL>>;
toggleOn: PolymorpheusContent<TuiContextWithImplicit<TuiSizeL>>;
}>;
readonly singleColor: boolean;
readonly showIcons: boolean;
readonly size: TuiSizeL;
}

/** Default values for the toggle options. */
export const TUI_TOGGLE_DEFAULT_OPTIONS: ToggleOptions = {
icons: {
toggleOff({$implicit}: TuiContextWithImplicit<TuiSizeL>): string {
return $implicit === 'm' ? 'tuiIconToggleOff' : 'tuiIconToggleOffLarge';
},
toggleOn({$implicit}: TuiContextWithImplicit<TuiSizeL>): string {
return $implicit === 'm' ? 'tuiIconToggleOn' : 'tuiIconToggleOnLarge';
},
},
singleColor: false,
showIcons: false,
size: 'm',
};

export const TUI_TOGGLE_OPTIONS = new InjectionToken<ToggleOptions>(
'Default parameters for toggle component',
{
factory: () => TUI_TOGGLE_DEFAULT_OPTIONS,
},
);
27 changes: 16 additions & 11 deletions projects/kit/components/toggle/toggle.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
AbstractTuiControl,
isNativeFocused,
TUI_FOCUSABLE_ITEM_ACCESSOR,
TuiContextWithImplicit,
tuiDefaultProp,
TuiFocusableElementAccessor,
TuiNativeFocusableElement,
Expand All @@ -27,6 +28,8 @@ import {
TuiSizeL,
TuiSizeXS,
} from '@taiga-ui/core';
import {PolymorpheusContent} from '@tinkoff/ng-polymorpheus';
import {ToggleOptions, TUI_TOGGLE_OPTIONS} from './toggle-options';

@Component({
selector: 'tui-toggle',
Expand All @@ -45,11 +48,11 @@ export class TuiToggleComponent
implements TuiFocusableElementAccessor {
@Input()
@tuiDefaultProp()
singleColor = false;
singleColor = this.options.singleColor;

@Input()
@tuiDefaultProp()
showIcons = false;
showIcons = this.options.showIcons;

@Input()
@tuiDefaultProp()
Expand All @@ -58,7 +61,7 @@ export class TuiToggleComponent
@Input()
@HostBinding('attr.data-tui-host-size')
@tuiDefaultProp()
size: TuiSizeL = 'm';
size: TuiSizeL = this.options.size;

@ViewChild('focusableElement')
private readonly focusableElement?: ElementRef<TuiNativeFocusableElement>;
Expand All @@ -72,10 +75,20 @@ export class TuiToggleComponent
@Optional()
@Inject(TuiModeDirective)
private readonly modeDirective: TuiModeDirective | null,
@Inject(TUI_TOGGLE_OPTIONS)
public readonly options: ToggleOptions,
) {
super(control, changeDetectorRef);
}

get iconOn(): PolymorpheusContent<TuiContextWithImplicit<TuiSizeL>> {
return this.options.icons.toggleOn;
}

get iconOff(): PolymorpheusContent<TuiContextWithImplicit<TuiSizeL>> {
return this.options.icons.toggleOff;
}

get nativeFocusableElement(): TuiNativeFocusableElement | null {
return this.focusableElement ? this.focusableElement.nativeElement : null;
}
Expand All @@ -99,14 +112,6 @@ export class TuiToggleComponent
return this.value;
}

get iconOn(): string {
return this.sizeM ? 'tuiIconToggleOn' : 'tuiIconToggleOnLarge';
}

get iconOff(): string {
return this.sizeM ? 'tuiIconToggleOff' : 'tuiIconToggleOffLarge';
}

get loaderSize(): TuiSizeXS {
return this.sizeM ? 'xs' : 's';
}
Expand Down
Loading

0 comments on commit 46b7ca8

Please sign in to comment.