Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] go-toast maxHeight & icon overrides #819

Merged
merged 3 commits into from
Aug 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 40 additions & 36 deletions projects/go-lib/src/lib/components/go-toast/go-toast.component.html
Original file line number Diff line number Diff line change
@@ -1,47 +1,51 @@
<div class="go-toast" [ngClass]="{'go-toast--dark': theme === 'dark'}">
<div class="go-toast-strip" [ngClass]="statusClass"></div>
<div class="go-toast-strip" [ngClass]="_status"></div>
<div class="go-toast-status">
<go-icon
class="go-toast-status__icon"
[ngClass]="statusClass"
[icon]="icon">
[ngClass]="_status"
[icon]="_icon">
</go-icon>
</div>
<div
class="go-toast-content"
[ngClass]="{ 'go-toast-content--no-title': !header }">
<h4
class="go-heading-4 go-toast-content__title"
*ngIf="header || headerContent">
<ng-container *ngIf="headerContent; else headerContentElse">
<ng-container *ngTemplateOutlet="headerContent"></ng-container>
class="go-toast__container"
[ngClass]="{ 'go-toast__container--max-height': enableMaxHeight }">
<div
class="go-toast-content"
[ngClass]="{ 'go-toast-content--no-title': !header }">
<h4
class="go-heading-4 go-toast-content__title"
*ngIf="header || headerContent">
<ng-container *ngIf="headerContent; else headerContentElse">
<ng-container *ngTemplateOutlet="headerContent"></ng-container>
</ng-container>
<ng-template #headerContentElse>
{{ header }}
</ng-template>
</h4>

<ng-container *ngIf="messageContent; else messageContentElse">
grahamhency marked this conversation as resolved.
Show resolved Hide resolved
<p class="go-toast-content__message">
<ng-container *ngTemplateOutlet="messageContent"></ng-container>
</p>
</ng-container>
<ng-template #headerContentElse>
{{ header }}
<ng-template #messageContentElse>
<p
class="go-toast-content__message"
[innerHTML]="message">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel that the naming here may be a little confusing just because message is a string but messageContent is a template ref. I feel like messageContentTemplate (or something like that) would be a little more explicit just from the standpoint of reading the html.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a fair point and a good suggestion. In this instance, none of this is actually new code. I am just restructuring the HTML to accommodate the CSS changes. Ideally, I'd like to refrain from making unrelated code changes so I think I'll leave it as is here.

</p>
</ng-template>
</h4>

<ng-container *ngIf="messageContent; else messageContentElse">
<p class="go-toast-content__message">
<ng-container *ngTemplateOutlet="messageContent"></ng-container>
</p>
</ng-container>
<ng-template #messageContentElse>
<p
class="go-toast-content__message"
[innerHTML]="message">
</p>
</ng-template>
</div>
<div
class="go-toast-dismiss"
*ngIf="dismissable">
<go-icon-button
buttonIcon="close"
(handleClick)="dismiss()">
</go-icon-button>
</div>
<div class="go-toast__actions" *ngIf="showToastActions">
<ng-content select="[go-toast-action]"></ng-content>
</div>
<div
class="go-toast-dismiss"
*ngIf="dismissable">
<go-icon-button
buttonIcon="close"
(handleClick)="dismiss()">
</go-icon-button>
</div>
<div class="go-toast__actions" *ngIf="showToastActions">
<ng-content select="[go-toast-action]"></ng-content>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
@import '../../../../styles/variables';
@import '../../../../styles/mixins';

$toast-padding: 1.25rem;

.go-toast {
background: $theme-light-bg;
border-radius: $global-radius;
Expand All @@ -10,10 +12,22 @@

&__actions {
align-items: center;
align-self: flex-start;
display: flex;
flex: 1;
justify-content: flex-end;
padding: .875rem 1.25rem;
padding: $toast-padding;
}

&__container {
align-items: baseline;
display: flex;
flex: 1 1 auto;

&--max-height {
max-height: 9rem;
overflow-y: auto;
}
}

&--dark {
Expand Down Expand Up @@ -69,7 +83,7 @@
flex: 1;
flex-direction: column;
justify-content: center;
padding: 1rem 1.25rem 1rem 0;
padding: $toast-padding $toast-padding $toast-padding 0;

&__title {
margin-bottom: .25rem;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,31 +28,40 @@ describe('GoToastComponent', () => {
expect(component).toBeTruthy();
});

describe('ngOnInit', () => {
it('sets a default statusClass if no type is passed in', () => {
describe('_status', () => {
it('returns a default status if no type is passed in', () => {
fixture.detectChanges();

expect(component.statusClass).toEqual('go-toast-status--neutral');
expect(component._status).toEqual('go-toast-status--neutral');
});

it('sets a statusClass if type is passed in', () => {
it('returns a type status if type is passed in', () => {
component.type = 'positive';
fixture.detectChanges();

expect(component.statusClass).toEqual('go-toast-status--positive');
expect(component._status).toEqual('go-toast-status--positive');
});
});

it('sets a default icon if no type is passed in', () => {
describe('_icon', () => {
it('returns a default icon if no type is passed in', () => {
fixture.detectChanges();

expect(component.icon).toEqual('notifications_none');
expect(component._icon).toEqual('notifications_none');
});

it('should set an icon if type is passed in', () => {
it('returns an icon if type is passed in', () => {
component.type = 'positive';
fixture.detectChanges();

expect(component.icon).toEqual('done');
expect(component._icon).toEqual('done');
});

it('returns an icon if icon is passed in', () => {
component.icon = 'pets';
fixture.detectChanges();

expect(component._icon).toEqual('pets');
});
});

Expand Down
46 changes: 20 additions & 26 deletions projects/go-lib/src/lib/components/go-toast/go-toast.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
ContentChild,
EventEmitter,
Input,
OnInit,
Output,
TemplateRef
} from '@angular/core';
Expand All @@ -13,17 +12,17 @@ import {
templateUrl: './go-toast.component.html',
styleUrls: ['./go-toast.component.scss']
})
export class GoToastComponent implements OnInit {
statusClass: string = 'go-toast-status--neutral';
icon: string = 'notifications_none';
export class GoToastComponent {
duration: number;

@Input() dismissable: boolean = false;
@Input() enableMaxHeight: boolean = true;
@Input() header: string;
@Input() icon: string;
@Input() message: string;
@Input() type: string;
@Input() showToastActions: boolean = false;
@Input() theme: 'light' | 'dark' = 'light';
@Input() type: string;

@Output() handleDismiss: EventEmitter<void> = new EventEmitter();

Expand All @@ -39,18 +38,22 @@ export class GoToastComponent implements OnInit {
*/
@ContentChild('messageContent') messageContent: TemplateRef<any>;

ngOnInit(): void {
this.statusClass = this.getStatus();
this.icon = this.getIcon();
}

public dismiss(): void {
this.handleDismiss.emit();
get _icon(): string {
if (this.icon) {
return this.icon;
} else {
switch (this.type) {
case 'positive':
return 'done';
case 'negative':
return 'priority_high';
default:
return 'notifications_none';
}
}
}

//#region Private Methods

private getStatus(): string {
get _status(): string {
switch (this.type) {
case 'positive':
return 'go-toast-status--positive';
Expand All @@ -61,16 +64,7 @@ export class GoToastComponent implements OnInit {
}
}

private getIcon(): string {
switch (this.type) {
case 'positive':
return 'done';
case 'negative':
return 'priority_high';
default:
return 'notifications_none';
}
dismiss(): void {
this.handleDismiss.emit();
}

//#endregion
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ <h4 class="go-heading-4">dismissable</h4>
</p>
</div>

<div class="go-column go-column--100">
<h4 class="go-heading-4">enableMaxHeight</h4>
<p class="go-body-copy go-body-copy--no-margin">
By default this is true, but if set to false will allow the toast to expand to the size of its content.
</p>
</div>

<div class="go-column go-column--100">
<h4 class="go-heading-4">header</h4>
<p class="go-body-copy go-body-copy--no-margin">
Expand All @@ -46,6 +53,16 @@ <h4 class="go-heading-4">header</h4>
</p>
</div>

<div class="go-column go-column--100">
<h4 class="go-heading-4">icon</h4>
<p class="go-body-copy go-body-copy--no-margin">
Changes the icon that is displayed within the toast. This is set automatically for each type, but if a value
is passed for this binding it will override all of those type icons. See the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I see this is for the docs so I'm not sure it really matters, would it be a good idea to store text like this in a variable somewhere and use {{ interpolation }}?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case, because it's just documentation and the value will never change I think it's fine to just have plain text here. Using interpolation on text that doesn't change is an extra thing that Angular will need to keep track of that it doesn't need to. Good thinking though!

<a class="go-link" href="https://material.io/tools/icons/">Material Design System Icons</a>
page for available icons.
</p>
</div>

<div class="go-column go-column--100">
<h4 class="go-heading-4">message</h4>
<p class="go-body-copy go-body-copy--no-margin">
Expand Down Expand Up @@ -249,7 +266,7 @@ <h4 class="go-heading-4">component.html</h4>
<go-card class="go-column go-column--100" id="toast-theme">
<ng-container go-card-header>
<h2 class="go-heading-2 go-heading--no-wrap">Theme</h2>
<go-copy cardId="theme-template" goCopyCardLink></go-copy>
<go-copy cardId="toast-theme" goCopyCardLink></go-copy>
</ng-container>
<ng-container go-card-content>
<div class="go-column go-column--100">
Expand All @@ -270,6 +287,76 @@ <h4 class="go-heading-4">component.html</h4>
header="Success!"
message="The thing you did saved successfully."
type="positive">
</go-toast>
</go-toast>

<go-card class="go-column go-column--100" id="toast-icon">
<ng-container go-card-header>
<h2 class="go-heading-2 go-heading--no-wrap">Icon Example</h2>
<go-copy cardId="toast-icon" goCopyCardLink></go-copy>
</ng-container>
<ng-container go-card-content>
<div class="go-column go-column--100">
<p class="go-body-copy go-body-copy--no-margin">
An icon may be specified with the <code class="code-block--inline">@Input icon: string;</code>
binding. If a value is passed to this binding, it will override all of the default icons for each type.
</p>
</div>
<h4 class="go-heading-4">component.html</h4>
<code [highlight]="toast_icon_template_html"></code>
</ng-container>
</go-card>

<go-toast
class="go-column go-column--100"
icon="pets"
header="Icon Chaos!"
message="This shows an example where the icon has been set to something unique from the Material Icons library.">
</go-toast>

<go-card class="go-column go-column--100" id="max-height">
<ng-container go-card-header>
<h2 class="go-heading-2 go-heading--no-wrap">Max Height Example</h2>
<go-copy cardId="max-height" goCopyCardLink></go-copy>
</ng-container>
<div class="go-container" go-card-content>
<div class="go-column go-column--100">
By default, the toasts have a max height that allows for vertical overflow scrolling. See below:
</div>
<div class="go-column go-column--50">
<h4 class="go-heading-4 go-heading--underlined">View</h4>
<go-toast header="Something you should know...">
<ng-template #messageContent>
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?
</ng-template>
</go-toast>
</div>
<div class="go-column go-column--50">
<h4 class="go-heading-4 go-heading--underlined">Code</h4>
<code
[highlight]="toast_maxHeight_html"
class="code-block--no-bottom-margin">
</code>
</div>

<div class="go-column go-column--100">
To disable the max height restriction on toasts, you can pass in a binding:
</div>
<div class="go-column go-column--50">
<h4 class="go-heading-4 go-heading--underlined">View</h4>
<go-toast header="Show me everything!" [enableMaxHeight]="false">
<ng-template #messageContent>
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?
</ng-template>
</go-toast>
</div>
<div class="go-column go-column--50">
<h4 class="go-heading-4 go-heading--underlined">Code</h4>
<code
[highlight]="toast_maxHeight_enable_html"
class="code-block--no-bottom-margin">
</code>
</div>
</div>
</go-card>

</section>
Loading