Skip to content

Commit

Permalink
feat(circle-toggle): expert appearance (#332)
Browse files Browse the repository at this point in the history
  • Loading branch information
yd-allianz authored and GitHub Enterprise committed Jul 19, 2021
1 parent 20e357e commit 3f7909f
Show file tree
Hide file tree
Showing 12 changed files with 232 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { CircleToggleStandaloneExampleComponent } from './circle-toggle-standalo
import { CircleToggleTemplateDrivenExampleComponent } from './circle-toggle-template-driven/circle-toggle-template-driven-example';
import { CircleToggleTextExampleComponent } from './circle-toggle-text/circle-toggle-text-example';
import { ExamplesSharedModule } from '../examples-shared.module';
import { CircleToggleGroupExpertExampleComponent } from './circle-toggle-group-expert/circle-toggle-group-expert-example';

const EXAMPLES = [
CircleToggleGroupExampleComponent,
Expand All @@ -21,7 +22,8 @@ const EXAMPLES = [
CircleToggleSimpleBindingExampleComponent,
CircleToggleStandaloneExampleComponent,
CircleToggleTemplateDrivenExampleComponent,
CircleToggleTextExampleComponent
CircleToggleTextExampleComponent,
CircleToggleGroupExpertExampleComponent
];

@NgModule({
Expand All @@ -44,6 +46,7 @@ export class CircleExamplesModule {
'circle-toggle-standalone': CircleToggleStandaloneExampleComponent,
'circle-toggle-template-driven': CircleToggleTemplateDrivenExampleComponent,
'circle-toggle-text': CircleToggleTextExampleComponent,
'circle-toggle-group-expert': CircleToggleGroupExpertExampleComponent
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<nx-circle-toggle-group class="nx-margin-bottom-m" appearance="expert">
<nx-circle-toggle *ngFor="let item of sampleValues" [value]="item.value" [icon]="item.icon"
[hint]="item.hint" [label]="item.label" [checked]="item.selected">
</nx-circle-toggle>
</nx-circle-toggle-group>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Component } from '@angular/core';

/**
* @title Circle toggle group expert default example
*/
@Component({
selector: 'circle-toggle-group-expert-example',
templateUrl: './circle-toggle-group-expert-example.html',
styleUrls: ['./circle-toggle-group-expert-example.css'],
})
export class CircleToggleGroupExpertExampleComponent {
sampleValues = [{value: 'A', icon: 'product-heart', hint: 'Hint A', label: 'Label A', selected: false},
{value: 'B', icon: 'product-car', hint: 'Hint B', label: 'Label B', selected: true},
{value: 'C', icon: 'product-plane', hint: 'Hint C', label: 'Label C', selected: false},
];
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,11 @@
flex-direction: row;
}
}

:host(.is-expert) {
justify-content: flex-start;

::ng-deep .nx-toggle-circle {
margin-right: nx-spacer(xl);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ describe('NxToggleButtonGroup', () => {
DisabledCircleToggleGroupComponent,
CircleToggleOnPushComponent,
EmptyToggleOnPushComponent,
CircleToggleGroupWithDivComponent
CircleToggleGroupWithDivComponent,
ExpertCircleToggleGroupComponent
],
imports: [
NxCircleToggleModule, FormsModule, ReactiveFormsModule
Expand Down Expand Up @@ -195,6 +196,19 @@ describe('NxToggleButtonGroup', () => {
});
});

describe('appearance', () => {
it('has default appearance', () => {
createTestComponent(SimpleCircleToggleGroupComponent);
expect(toggleComponent.appearance).toBe('default');
});

it('has expert appearance', () => {
createTestComponent(ExpertCircleToggleGroupComponent);
expect(toggleComponent.appearance).toBe('expert');
expect(toggleNativeElement.classList.contains('is-expert')).toBe(true);
});
});

describe('a11y', () => {
it('has no accessibility violations', async () => {
createTestComponent(SimpleCircleToggleGroupComponent);
Expand All @@ -209,6 +223,7 @@ abstract class ButtonToggleGroupTest {
buttonToggleGroup: NxCircleToggleGroupComponent;
modelValue: string;
valueBinding = 'B';
appearance = 'default';
}

@Component({
Expand Down Expand Up @@ -319,3 +334,14 @@ class DisabledCircleToggleGroupComponent extends ButtonToggleGroupTest {}
`
})
class CircleToggleGroupWithDivComponent extends ButtonToggleGroupTest {}

@Component({
template: `
<nx-circle-toggle-group appearance="expert">
<nx-circle-toggle value="A" icon="product-heart" hint="info1" label="text1"></nx-circle-toggle>
<nx-circle-toggle value="B" icon="product-bed" hint="info2" label="text2"></nx-circle-toggle>
<nx-circle-toggle value="C" icon="product-bed" hint="info3" label="text3"></nx-circle-toggle>
</nx-circle-toggle-group>
`
})
class ExpertCircleToggleGroupComponent extends ButtonToggleGroupTest {}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ import {
AfterViewInit,
ChangeDetectorRef,
OnDestroy,
ChangeDetectionStrategy
ChangeDetectionStrategy,
Optional,
Inject,
HostBinding,
InjectionToken
} from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { coerceBooleanProperty, BooleanInput } from '@angular/cdk/coercion';
Expand All @@ -19,6 +23,25 @@ import { merge, Subject } from 'rxjs';
import { ToggleButton } from '../circle-toggle/toggle-button';
import { ToggleChangeEvent } from '../circle-toggle/circle-toggle.component';

/**
* Appearance options for the circle toggle group component.
*/
export type NxCircleToggleGroupAppearance = 'default' | 'expert';

/**
* Represents the default options for the circle toggle group.
* It can be configured using the `CIRCLE_TOGGLE_GROUP_DEFAULT_OPTIONS` injection token.
*/
export interface CircleToggleGroupDefaultOptions {
/**
* Sets the default appearance. (optional)
*/
appearance?: NxCircleToggleGroupAppearance;
}

export const CIRCLE_TOGGLE_GROUP_DEFAULT_OPTIONS =
new InjectionToken<CircleToggleGroupDefaultOptions>('CIRCLE_TOGGLE_GROUP_DEFAULT_OPTIONS');

let nextId = 0;

@Component({
Expand Down Expand Up @@ -46,10 +69,6 @@ let nextId = 0;
})
export class NxCircleToggleGroupComponent implements ControlValueAccessor, AfterViewInit, OnDestroy {

@ContentChildren(ToggleButton, { descendants: true }) private _buttons: QueryList<ToggleButton>;

private _id = `nx-circle-toggle-group-${nextId++}`;

/**
* Id of the circle toggle group.
*
Expand All @@ -62,13 +81,6 @@ export class NxCircleToggleGroupComponent implements ControlValueAccessor, After
get id(): string {
return this._id;
}
private _destroyed: Subject<void> = new Subject();

/** An event emitted when the selection changes. Outputs the value of the currently selected button. */
@Output()
valueChange: EventEmitter<any> = new EventEmitter();

private _name: string = `toggle-group-${nextId++}`;

/** Name that is used for accessibility. */
@Input()
Expand All @@ -81,8 +93,6 @@ export class NxCircleToggleGroupComponent implements ControlValueAccessor, After
return this._name;
}

private _disabled: boolean;

/** Whether the circle toggle group is disabled. */
@Input()
set disabled(value: boolean) {
Expand All @@ -98,8 +108,6 @@ export class NxCircleToggleGroupComponent implements ControlValueAccessor, After
get disabled(): boolean {
return this._disabled;
}

_negative: boolean = false;
/** Whether the circle toggle group uses the negative styling. */
@Input()
set negative(value: boolean) {
Expand All @@ -114,8 +122,6 @@ export class NxCircleToggleGroupComponent implements ControlValueAccessor, After
get negative(): boolean {
return this._negative;
}

private _value;
/** The value of the selected circle toggle in the circle toggle group. */
@Input()
set value(value: string) {
Expand All @@ -125,8 +131,6 @@ export class NxCircleToggleGroupComponent implements ControlValueAccessor, After
get value(): string {
return this._value;
}

private _responsive: boolean = true;
/** Whether the circle toggle group has a responsive behavior. */
@Input()
set responsive(value: boolean) {
Expand All @@ -138,14 +142,67 @@ export class NxCircleToggleGroupComponent implements ControlValueAccessor, After
}

get responsive(): boolean {
return this._responsive;
if (this.appearance === 'expert') {
return false;
} else {
return this._responsive;
}
}

@HostBinding('class.is-expert')
get _isExpert() {
return this.appearance === 'expert';
}

constructor(private _changeDetectorRef: ChangeDetectorRef,
@Optional() @Inject(CIRCLE_TOGGLE_GROUP_DEFAULT_OPTIONS) defaultOptions: CircleToggleGroupDefaultOptions) {
if (defaultOptions && defaultOptions.appearance) {
this.appearance = defaultOptions.appearance;
}
}

/** @docs-private */
get selectedButton(): ToggleButton {
return this.buttons ? this.buttons.find(button => button.checked) : null;
}

/** @docs-private */
get buttons() {
return this._buttons;
}

static ngAcceptInputType_disabled: BooleanInput;
static ngAcceptInputType_negative: BooleanInput;
static ngAcceptInputType_responsive: BooleanInput;

@ContentChildren(ToggleButton, { descendants: true }) private _buttons: QueryList<ToggleButton>;

private _id = `nx-circle-toggle-group-${nextId++}`;
private _destroyed: Subject<void> = new Subject();

/** An event emitted when the selection changes. Outputs the value of the currently selected button. */
@Output()
valueChange: EventEmitter<any> = new EventEmitter();

private _name: string = `toggle-group-${nextId++}`;

private _disabled: boolean;

_negative: boolean = false;

private _value;

private _responsive: boolean = true;

/**
* Sets the appearance of the circle toggle group. Default: 'default'
*/
@Input()
appearance: NxCircleToggleGroupAppearance = 'default';

private onChangeCallback = (value: string) => { };
private onTouchedCallback = () => { };

constructor(private _changeDetectorRef: ChangeDetectorRef) { }

writeValue(value: any) {
if (this.value !== value) {
this._value = value;
Expand Down Expand Up @@ -220,18 +277,4 @@ export class NxCircleToggleGroupComponent implements ControlValueAccessor, After
setDisabledState?(isDisabled: boolean): void {
this.disabled = isDisabled;
}

/** @docs-private */
get selectedButton(): ToggleButton {
return this.buttons ? this.buttons.find(button => button.checked) : null;
}

/** @docs-private */
get buttons() {
return this._buttons;
}

static ngAcceptInputType_disabled: BooleanInput;
static ngAcceptInputType_negative: BooleanInput;
static ngAcceptInputType_responsive: BooleanInput;
}
12 changes: 12 additions & 0 deletions projects/ng-aquila/src/circle-toggle/circle-toggle.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,18 @@ Please note that if no label is provided, on mobile the circleText will be displ

<!-- example(circle-toggle-negative) -->

<div class="docs-expert-container">

#### Expert: Appearance

With `appearance="expert"` you can change the styling of the card to expert.

Please note that this is an **Expert option**. This means that it is only intended for internal applications and not for applications that are client facing.

<!-- example(circle-toggle-group-expert)-->

</div>

### Simple binding

<!-- example(circle-toggle-simple-binding) -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ $check-icon-size: nx-spacer(2m);
border-radius: 50%;
border-width: $check-icon-border-size;
border-style: solid;
@include var(border-color, circle-toggle-border-color);
border-color: var(--circle-toggle-border-color);
display: flex;
align-items: center;
justify-content: center;
Expand Down Expand Up @@ -172,6 +172,56 @@ $check-icon-size: nx-spacer(2m);
}
}

:host-context(.is-expert) {
.nx-toggle-circle__icon-wrapper {
height: nx-spacer(xl);
width: nx-spacer(xl);

.nx-toggle-circle__icon nx-icon {
font-size: nx-font-size(l);
}
}

.nx-toggle-circle__label-text {
@include type-style(circle-toggle-label-mobile);
}

.is-label-bold {
font-weight: nx-font-weight(regular);
}

.nx-toggle-circle__content-text {
@include type-style(circle-toggle-content-text-mobile);
}

.nx-toggle-circle__label-hint {
@include type-style(circle-toggle-hint-mobile);

.nx-toggle-circle__icon-wrapper {
width: nx-spacer(xl);
height: nx-spacer(xl);
}

.nx-toggle-circle__icon nx-icon {
font-size: nx-spacer(2m);
}

.nx-toggle-circle__check-icon {
right: calc(50% - #{nx-spacer(3m)});

[dir="rtl"] & {
left: calc(50% - #{nx-spacer(3m)});
right: auto;
}
}

.nx-toggle-circle__icon-image {
width: nx-spacer(xl);
height: nx-spacer(xl);
}
}
}

:host(.is-flipped) {
.nx-toggle-circle__icon-wrapper {
@include var(background-color, circle-toggle-selected-background-color);
Expand Down
3 changes: 3 additions & 0 deletions projects/ng-aquila/src/config/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ When imported, this module sets the injection tokens for a bunch of components.
- **Formfield:** `[appearance]` is set to `"outline"` and `nxFloatLabel` to `"always"` (see [here](./documentation/formfield/overview#expert%253A-appearance)).
- **Label:** The size is set to `"small"` (see [here](./documentation/base/overview#label)).
- **TabGroup** and **TabNavBar**: `[appearance]` is set to `"expert"` for both of the components (see [here](./documentation/tabs/overview#expert%253A-appearance)).
- **SelectableCard**: `[appearance]` is set to `"expert"` (see [here](./documentation/card/overview#expert%253A-appearance)).
- **SmallStage**: `[appearance]` is set to `"expert"` (see [here](./documentation/small-stage/overview#expert-specifics)).
- **CircleToggle**: `[appearance]` is set to `"expert"` and `[responsive]` to `"false"` for the CircleToggleGroup component (see [here](./documentation/circle-toggle/overview#expert%253A-appearance)).

If you use this module, you don't need to set these configurations explicitly for every component in your template anymore. This means instead of using the expert properties for the component `<nx-formfield nxFloatLabel="always" appearance="outline">` you only need to write `<nx-formfield>...</nx-formfield>` and `nxFloatLabel`, `appearance` are set for you automatically.

Expand Down
Loading

0 comments on commit 3f7909f

Please sign in to comment.