move notification default layout to src/core

This commit is contained in:
Jacob Overgaard
2023-03-13 13:51:27 +01:00
parent 95e035617d
commit d506a627e4
11 changed files with 59 additions and 44 deletions

View File

@@ -1 +0,0 @@
export * from './notification-layout-default.element';

View File

@@ -1,29 +0,0 @@
import { html, LitElement } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import { ifDefined } from 'lit/directives/if-defined.js';
import { UUITextStyles } from '@umbraco-ui/uui-css';
import type { UmbNotificationHandler } from '../..';
export interface UmbNotificationDefaultData {
message: string;
headline?: string;
}
@customElement('umb-notification-layout-default')
export class UmbNotificationLayoutDefaultElement extends LitElement {
static styles = [UUITextStyles];
@property({ attribute: false })
notificationHandler!: UmbNotificationHandler;
@property({ type: Object })
data!: UmbNotificationDefaultData;
render() {
return html`
<uui-toast-notification-layout id="layout" headline="${ifDefined(this.data.headline)}" class="uui-text">
<div id="message">${this.data.message}</div>
</uui-toast-notification-layout>
`;
}
}

View File

@@ -1,22 +0,0 @@
import { Meta, Story } from '@storybook/web-components';
import { html } from 'lit';
import { UmbNotificationLayoutDefaultElement, UmbNotificationDefaultData } from '.';
export default {
title: 'API/Notifications/Layouts/Default',
component: 'umb-notification-layout-default',
id: 'notification-layout-default',
} as Meta;
const data: UmbNotificationDefaultData = {
headline: 'Headline',
message: 'This is a default notification',
};
const Template: Story<UmbNotificationLayoutDefaultElement> = () => html`
<uui-toast-notification .open=${true}>
<umb-notification-layout-default .data=${data}></umb-notification-layout-default>
</uui-toast-notification>
`;
export const Default = Template.bind({});

View File

@@ -1,56 +0,0 @@
import { fixture, expect, html } from '@open-wc/testing';
import { UUIToastNotificationLayoutElement } from '@umbraco-ui/uui';
import { UmbNotificationHandler } from '../..';
import type { UmbNotificationLayoutDefaultElement, UmbNotificationDefaultData } from '.';
import '.';
describe('UmbNotificationLayoutDefault', () => {
let element: UmbNotificationLayoutDefaultElement;
const data: UmbNotificationDefaultData = {
headline: 'Notification Headline',
message: 'Notification message',
};
const options = { elementName: 'umb-notification-layout-default', data };
let notificationHandler: UmbNotificationHandler;
beforeEach(async () => {
notificationHandler = new UmbNotificationHandler(options);
element = await fixture(
html`<umb-notification-layout-default
.notificationHandler=${notificationHandler}
.data=${options.data}></umb-notification-layout-default>`
);
});
describe('Public API', () => {
describe('properties', () => {
it('has a notificationHandler property', () => {
expect(element).to.have.property('notificationHandler');
});
it('has a data property', () => {
expect(element).to.have.property('data');
});
});
});
describe('Data options', () => {
describe('Headline', () => {
it('sets headline on uui notification layout', () => {
const uuiNotificationLayout: UUIToastNotificationLayoutElement | null =
element.renderRoot.querySelector('#layout');
expect(uuiNotificationLayout?.getAttribute('headline')).to.equal('Notification Headline');
});
});
describe('message', () => {
it('renders the message', () => {
const messageElement: HTMLElement | null = element.renderRoot.querySelector('#message');
expect(messageElement?.innerText).to.equal('Notification message');
});
});
});
});

View File

@@ -3,14 +3,13 @@ import { validate as uuidValidate } from 'uuid';
import { UmbNotificationHandler } from './notification-handler';
import type { UmbNotificationDefaultData } from './layouts/default';
import type { UmbNotificationOptions } from './notification.context';
describe('UmbNotificationHandler', () => {
let notificationHandler: UmbNotificationHandler;
beforeEach(async () => {
const options: UmbNotificationOptions<UmbNotificationDefaultData> = {};
const options: UmbNotificationOptions = {};
notificationHandler = new UmbNotificationHandler(options);
});
@@ -72,7 +71,7 @@ describe('UmbNotificationHandler', () => {
let layoutElement: any;
beforeEach(async () => {
const options: UmbNotificationOptions<UmbNotificationDefaultData> = {
const options: UmbNotificationOptions = {
color: 'positive',
data: {
message: 'Notification default layout message',
@@ -100,7 +99,7 @@ describe('UmbNotificationHandler', () => {
let layoutElement: any;
beforeEach(async () => {
const options: UmbNotificationOptions<UmbNotificationDefaultData> = {
const options: UmbNotificationOptions = {
elementName: 'umb-notification-test-element',
color: 'positive',
data: {

View File

@@ -1,8 +1,6 @@
import { UUIToastNotificationElement } from '@umbraco-ui/uui';
import { v4 as uuidv4 } from 'uuid';
import type { UmbNotificationOptions, UmbNotificationColor, UmbNotificationDefaultData } from '.';
import './layouts/default';
import type { UmbNotificationOptions, UmbNotificationColor, UmbNotificationDefaultData } from './notification.context';
/**
* @export

View File

@@ -1,177 +0,0 @@
import { Meta } from '@storybook/blocks';
<Meta title="API/Notifications/Intro" />
# Notifications
Notifications appear in the bottom right corner of the Backoffice. There are two types of notifications: "Peek" and "Stay".
**Peek notifications**
Goes away automatically and should be used as feedback on user actions.
**Stay notifications**
Stays on the screen until dismissed by the user or custom code. Stay notification should be used when you need user feedback or want to control when the notification disappears.
## Basic usage
### Consume UmbNotificationContext from an element
The UmbNotification context can be used to open notifications.
```ts
import { html, LitElement } from 'lit';
import { UmbLitElement } from '@umbraco-cms/element';
import type { UmbNotificationContext, UMB_NOTIFICATION_CONTEXT_ALIAS } from '@umbraco-cms/notification';
class MyElement extends UmbLitElement {
private _notificationContext?: UmbNotificationContext;
constructor() {
super();
this.consumeContext(UMB_NOTIFICATION_CONTEXT_ALIAS, (instance) => {
this._notificationContext = notificationContext;
// notificationContext is now ready to be used
});
}
}
```
### Open a notification
A notification is opened by calling one of the helper methods on the UmbNotificationContext. The methods will return an instance of UmbNotificationHandler.
```ts
import { html, LitElement } from 'lit';
import { state } from 'lit/decorators.js';
import { UmbLitElement } from '@umbraco-cms/element';
import type {
UmbNotificationContext,
UmbNotificationDefaultData,
UMB_NOTIFICATION_CONTEXT_ALIAS,
} from '@umbraco-cms/notification';
class MyElement extends UmbLitElement {
private _notificationContext?: UmbNotificationContext;
constructor() {
super();
this.consumeContext(UMB_NOTIFICATION_CONTEXT_ALIAS, (notificationContext) => {
this._notificationContext = notificationContext;
// notificationContext is now ready to be used
});
}
private _handleClick() {
const data: UmbNotificationDefaultData = { headline: 'Look at this', message: 'Something good happened' };
const notificationHandler = this._notificationContext?.peek('positive', { data });
notificationHandler.onClose().then(() => {
// if you need any logic when the notification is closed you can run it here
});
}
render() {
return html`<button @click="${this._handleClick}">Open Notification</button>`;
}
}
```
## Advanced usage: creating custom layouts
The default layout will cover most cases, but there might be situations where we want a more complex layout. You can create a new Custom Element to use as the layout.
### Custom layout element
```ts
import { html, LitElement } from 'lit';
import { property } from 'lit/decorators.js';
import { UUITextStyles } from '@umbraco-ui/uui-css';
import type { UmbNotificationHandler } from '@umbraco-cms/notification';
export interface UmbNotificationCustomData {
headline: string;
user: {
name: string;
};
}
export class UmbNotificationLayoutCustom extends LitElement {
static styles = [UUITextStyles];
@property({ attribute: false })
public notificationHandler: UmbNotificationHandler;
@property({ type: Object })
public data: UmbNotificationCustomData;
private _handleConfirm() {
this.notificationHandler.close(true);
}
render() {
return html`
<uui-toast-notification-layout headline="${this.data.headline}" class="uui-text">
${this.data.user.name}
<uui-button slot="actions" @click="${this._handleConfirm}" label="Confirm">Confirm</uui-button>
</uui-toast-notification-layout>
`;
}
}
```
### Open notification with custom layout
```ts
import { html, LitElement } from 'lit';
import { UmbContextInjectMixin } from '@umbraco-cms/context-api';
import type {
UmbNotificationContext,
UmbNotificationOptions,
UMB_NOTIFICATION_CONTEXT_ALIAS,
} from '@umbraco-cms/notification';
import type { UmbNotificationCustomData } from './custom-notification-layout';
class MyElement extends LitElement {
private _notificationContext?: UmbNotificationContext;
constructor() {
super();
this.consumeContext(UMB_NOTIFICATION_CONTEXT_ALIAS, (instance) => {
this._notificationContext = instance;
// notificationContext is now ready to be used
});
}
private _handleClick() {
const options: UmbNotificationOptions<UmbNotificationCustomData> = {
elementName: 'umb-notification-layout-custom',
data: {
headline: 'Attention',
user: { name: 'Peter Parker' },
},
};
const notificationHandler = this._notificationContext?.stay('default', options);
notificationHandler.onClose().then((result) => {
if (result) {
console.log('He agreed!');
}
});
}
render() {
return html`<button @click="${this._handleClick}">Open Notification</button>`;
}
}
```
## Best practices
- Keep messages in notifications short and friendly.
- Only use headlines when you need extra attention to the notification
- If a custom notification layout is only used in one module keep the files layout files local to that module.
- If a custom notification will be used across the project. Create it as a layout in the notification folder and add a helper method to the UmbNotificationContext.

View File

@@ -1,38 +0,0 @@
import '../layouts/default';
import { Meta, Story } from '@storybook/web-components';
import { html } from 'lit';
import { UmbNotificationContext } from '..';
export default {
title: 'API/Notifications/Overview',
component: 'ucp-notification-layout-default',
decorators: [
(story) =>
html`<umb-context-provider key="UmbNotificationContext" .value=${new UmbNotificationContext()}>
${story()}
</umb-context-provider>`,
],
} as Meta;
const Template: Story = () => html`<story-notification-default-example></story-notification-default-example>`;
export const Default = Template.bind({});
Default.parameters = {
docs: {
source: {
language: 'js',
code: `
const options: UmbNotificationOptions<UmbNotificationDefaultData> = {
data: {
headline: 'Headline',
message: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit'
}
};
this._notificationContext?.peek('positive', options);
`,
},
},
};

View File

@@ -1,56 +0,0 @@
import { html } from 'lit';
import { customElement } from 'lit/decorators.js';
import { UmbNotificationDefaultData } from '../layouts/default';
import {
UmbNotificationColor,
UmbNotificationOptions,
UmbNotificationContext,
UMB_NOTIFICATION_CONTEXT_TOKEN,
} from '..';
import { UmbLitElement } from '@umbraco-cms/element';
@customElement('story-notification-default-example')
export class StoryNotificationDefaultExampleElement extends UmbLitElement {
private _notificationContext?: UmbNotificationContext;
connectedCallback(): void {
super.connectedCallback();
this.consumeContext(UMB_NOTIFICATION_CONTEXT_TOKEN, (instance) => {
this._notificationContext = instance;
});
}
private _handleNotification = (color: UmbNotificationColor) => {
const options: UmbNotificationOptions<UmbNotificationDefaultData> = {
data: {
headline: 'Headline',
message: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
},
};
this._notificationContext?.peek(color, options);
};
render() {
return html`
<uui-button @click="${() => this._handleNotification('default')}" label="Default"></uui-button>
<uui-button
@click="${() => this._handleNotification('positive')}"
label="Positive"
look="primary"
color="positive"></uui-button>
<uui-button
@click="${() => this._handleNotification('warning')}"
label="Warning"
look="primary"
color="warning"></uui-button>
<uui-button
@click="${() => this._handleNotification('danger')}"
label="Danger"
look="primary"
color="danger"></uui-button>
<umb-backoffice-notification-container></umb-backoffice-notification-container>
`;
}
}