feat(docs-infra): allow notification bar to show arbitrary content (#25020)
This change generalises the notification bar rendering to allow more complex content to be displayed. Now you must provide the full HTML of the notification message when using `<aio-notification>`. Also you can control whether clicking the content triggers the notification to close or not. This will support the new notification specified in "Other Items : 3" of [#24140](https://github.com/angular/angular/issues/24140#issuecomment-397480410) PR Close #25020
This commit is contained in:
parent
6a4d66d432
commit
e8d4211d5c
|
@ -7,14 +7,15 @@
|
|||
<mat-toolbar color="primary" class="app-toolbar no-print" [class.transitioning]="isTransitioning">
|
||||
<mat-toolbar-row class="notification-container">
|
||||
<aio-notification
|
||||
icon="insert_comment"
|
||||
iconLabel="Announcement"
|
||||
buttonText="Learn More"
|
||||
actionUrl="https://blog.angular.io/version-6-0-0-of-angular-now-available-cc56b0efa7a4"
|
||||
notificationId="angular-v6-announcement"
|
||||
expirationDate="2018-07-01"
|
||||
[dismissOnContentClick]="true"
|
||||
(dismissed)="notificationDismissed()">
|
||||
Version 6 of Angular Now Available!
|
||||
<a href="https://blog.angular.io/version-6-0-0-of-angular-now-available-cc56b0efa7a4">
|
||||
<mat-icon class="icon" svgIcon="insert_comment" aria-label="Announcement"></mat-icon>
|
||||
<span class="message">Version 6 of Angular Now Available!</span>
|
||||
<span class="action-button">Learn More</span>
|
||||
</a>
|
||||
</aio-notification>
|
||||
</mat-toolbar-row>
|
||||
<mat-toolbar-row>
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
<a href="{{actionUrl}}" class="content" (click)="dismiss()">
|
||||
<mat-icon class="icon" [svgIcon]="icon" [attr.aria-label]="iconLabel"></mat-icon>
|
||||
<span class="message"><ng-content></ng-content></span>
|
||||
<span class="action-button">{{buttonText}}</span>
|
||||
</a>
|
||||
<span class="content" (click)="contentClick()">
|
||||
<ng-content></ng-content>
|
||||
</span>
|
||||
|
||||
<button mat-icon-button class="close-button" aria-label="Close" (click)="dismiss()">
|
||||
<mat-icon svgIcon="close" aria-label="Dismiss notification"></mat-icon>
|
||||
|
|
|
@ -30,37 +30,49 @@ describe('NotificationComponent', () => {
|
|||
fixture.detectChanges();
|
||||
}
|
||||
|
||||
it('should display the message', () => {
|
||||
describe('content projection', () => {
|
||||
it('should display the message text', () => {
|
||||
configTestingModule();
|
||||
createComponent();
|
||||
expect(fixture.nativeElement.innerHTML).toContain('Help Angular by taking a <strong>1 minute survey</strong>!');
|
||||
expect(fixture.nativeElement.innerHTML).toContain('Version 6 of Angular Now Available!');
|
||||
});
|
||||
|
||||
it('should display an icon', () => {
|
||||
configTestingModule();
|
||||
createComponent();
|
||||
const iconElement = fixture.debugElement.query(By.css('.icon'));
|
||||
expect(iconElement.properties['svgIcon']).toEqual('insert_comment');
|
||||
expect(iconElement.attributes['aria-label']).toEqual('Survey');
|
||||
});
|
||||
|
||||
it('should display a button', () => {
|
||||
it('should render HTML elements', () => {
|
||||
configTestingModule();
|
||||
createComponent();
|
||||
const button = fixture.debugElement.query(By.css('.action-button'));
|
||||
expect(button.nativeElement.textContent).toEqual('Go to survey');
|
||||
expect(button.nativeElement.textContent).toEqual('Learn More');
|
||||
});
|
||||
|
||||
it('should call dismiss when the message link is clicked', () => {
|
||||
it('should process Angular directives', () => {
|
||||
configTestingModule();
|
||||
createComponent();
|
||||
const badSpans = fixture.debugElement.queryAll(By.css('.bad'));
|
||||
expect(badSpans.length).toEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('should call dismiss() when the message link is clicked, if dismissOnContentClick is true', () => {
|
||||
configTestingModule();
|
||||
createComponent();
|
||||
spyOn(component, 'dismiss');
|
||||
fixture.debugElement.query(By.css('a')).triggerEventHandler('click', null);
|
||||
fixture.detectChanges();
|
||||
component.dismissOnContentClick = true;
|
||||
const message: HTMLSpanElement = fixture.debugElement.query(By.css('.messageholder')).nativeElement;
|
||||
message.click();
|
||||
expect(component.dismiss).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call dismiss when the close button is clicked', () => {
|
||||
it('should not call dismiss() when the message link is clicked, if dismissOnContentClick is false', () => {
|
||||
configTestingModule();
|
||||
createComponent();
|
||||
spyOn(component, 'dismiss');
|
||||
component.dismissOnContentClick = false;
|
||||
const message: HTMLSpanElement = fixture.debugElement.query(By.css('.messageholder')).nativeElement;
|
||||
message.click();
|
||||
expect(component.dismiss).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call dismiss() when the close button is clicked', () => {
|
||||
configTestingModule();
|
||||
createComponent();
|
||||
spyOn(component, 'dismiss');
|
||||
|
@ -104,13 +116,15 @@ describe('NotificationComponent', () => {
|
|||
@Component({
|
||||
template: `
|
||||
<aio-notification
|
||||
icon="insert_comment"
|
||||
iconLabel="Survey"
|
||||
buttonText="Go to survey"
|
||||
actionUrl="https://bit.ly/angular-survey-2018"
|
||||
notificationId="survey-january-2018"
|
||||
expirationDate="2018-01-22">
|
||||
Help Angular by taking a <strong>1 minute survey</strong>!
|
||||
<span class="messageholder">
|
||||
<a href="https://blog.angular.io/version-6-0-0-of-angular-now-available-cc56b0efa7a4">
|
||||
<span *ngIf="false" class="bad">This should not appear</span>
|
||||
<span class="message">Version 6 of Angular Now Available!</span>
|
||||
<span class="action-button">Learn More</span>
|
||||
</a>
|
||||
</span>
|
||||
</aio-notification>`
|
||||
})
|
||||
class TestComponent {
|
||||
|
|
|
@ -22,10 +22,7 @@ const LOCAL_STORAGE_NAMESPACE = 'aio-notification/';
|
|||
export class NotificationComponent implements OnInit {
|
||||
private get localStorage() { return this.window.localStorage; }
|
||||
|
||||
@Input() icon: string;
|
||||
@Input() iconLabel: string;
|
||||
@Input() buttonText: string;
|
||||
@Input() actionUrl: string;
|
||||
@Input() dismissOnContentClick: boolean;
|
||||
@Input() notificationId: string;
|
||||
@Input() expirationDate: string;
|
||||
@Output() dismissed = new EventEmitter();
|
||||
|
@ -44,6 +41,12 @@ export class NotificationComponent implements OnInit {
|
|||
this.showNotification = previouslyHidden || expired ? 'hide' : 'show';
|
||||
}
|
||||
|
||||
contentClick() {
|
||||
if (this.dismissOnContentClick) {
|
||||
this.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
dismiss() {
|
||||
this.localStorage.setItem(LOCAL_STORAGE_NAMESPACE + this.notificationId, 'hide');
|
||||
this.showNotification = 'hide';
|
||||
|
|
|
@ -31,11 +31,14 @@ aio-notification {
|
|||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
max-width: calc(100% - #{$notificationHeight});
|
||||
text-transform: none;
|
||||
padding: 0;
|
||||
|
||||
> * {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin-right: 10px;
|
||||
@media (max-width: 464px) {
|
||||
|
@ -46,10 +49,10 @@ aio-notification {
|
|||
.message {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.action-button {
|
||||
margin-left: 10px;
|
||||
background: $brightred;
|
||||
border-radius: 15px;
|
||||
text-transform: uppercase;
|
||||
|
|
Loading…
Reference in New Issue