-
Notifications
You must be signed in to change notification settings - Fork 273
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(ui5-illustrated-message): added new component (#3480)
The PR introduces new web component, called ui5-illustrated-message: - The component provides illustration and texts that add context to it. - The Component supports 4 main breakpoints: scene, dialog, spot and base and each of them provides different illustration. Note: In base breakpoint only title and subtitle of the component are displayed. Fixes: #3376 Closes: #3376
- Loading branch information
Showing
88 changed files
with
2,257 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import getSharedResource from "../getSharedResource.js"; | ||
|
||
const registry = getSharedResource("SVGIllustration.registry", new Map()); | ||
const ILLUSTRATION_NOT_FOUND = "ILLUSTRATION_NOT_FOUND"; | ||
|
||
const registerIllustration = (name, { dialogSvg, sceneSvg, spotSvg, title, subtitle } = {}) => { // eslint-disable-line | ||
registry.set(name, { | ||
dialogSvg, | ||
sceneSvg, | ||
spotSvg, | ||
title, | ||
subtitle, | ||
}); | ||
}; | ||
|
||
const getIllustrationDataSync = nameProp => { | ||
return registry.get(nameProp) || ILLUSTRATION_NOT_FOUND; | ||
}; | ||
|
||
export { | ||
getIllustrationDataSync, | ||
registerIllustration, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
<div class="ui5-illustrated-message-root"> | ||
<div class="ui5-illustrated-message-illustration"> | ||
{{{effectiveIllustration}}} | ||
</div> | ||
<ui5-title level="H2" class="ui5-illustrated-message-title" wrapping-type="Normal">{{effectiveTitleText}}</ui5-title> | ||
<div class="ui5-illustrated-message-subtitle">{{effectiveSubitleText}}</div> | ||
{{#if hasActions}} | ||
<div class="ui5-illustrated-message-actions"> | ||
<slot></slot> | ||
</div> | ||
{{/if}} | ||
</div> | ||
|
||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="ui5-illustrated-message-util"> | ||
<defs> | ||
<pattern id="sapIllus_PatternShadow" data-name="sapIllus_PatternShadow" width="3" height="5.5" | ||
patternUnits="userSpaceOnUse" viewBox="0 0 3 5.5"> | ||
<rect class="sapIllus_NoColor" style="fill:var(--sapIllus_NoColor)" width="3" height="5.5" /> | ||
<circle class="sapIllus_BrandColorPrimary" style="fill:var(--sapIllus_BrandColorPrimary)" cx="3" cy="5.5001" | ||
r="0.5" /> | ||
<circle class="sapIllus_BrandColorPrimary" style="fill:var(--sapIllus_BrandColorPrimary)" cy="5.5001" | ||
r="0.5" /> | ||
<circle class="sapIllus_BrandColorPrimary" style="fill:var(--sapIllus_BrandColorPrimary)" cx="1.5" | ||
cy="2.7501" r="0.5" /> | ||
<circle class="sapIllus_BrandColorPrimary" style="fill:var(--sapIllus_BrandColorPrimary)" cx="3" cy="0.0001" | ||
r="0.5" /> | ||
<circle class="sapIllus_BrandColorPrimary" style="fill:var(--sapIllus_BrandColorPrimary)" cy="0.0001" | ||
r="0.5" /> | ||
</pattern> | ||
<pattern id="sapIllus_PatternHighlight" data-name="sapIllus_PatternHighlight" width="3" height="5.5" | ||
patternTransform="translate(35.9059 309.6208)" patternUnits="userSpaceOnUse" viewBox="0 0 3 5.5"> | ||
<rect class="sapIllus_NoColor" style="fill:var(--sapIllus_NoColor)" width="3" height="5.5" /> | ||
<circle class="sapIllus_ObjectFillColor" style="fill:var(--sapIllus_ObjectFillColor)" cx="3.0001" | ||
cy="5.5001" r="0.5" /> | ||
<circle class="sapIllus_ObjectFillColor" style="fill:var(--sapIllus_ObjectFillColor)" cx="0.0001" | ||
cy="5.5001" r="0.5" /> | ||
<circle class="sapIllus_ObjectFillColor" style="fill:var(--sapIllus_ObjectFillColor)" cx="1.5001" | ||
cy="2.7501" r="0.5" /> | ||
<circle class="sapIllus_ObjectFillColor" style="fill:var(--sapIllus_ObjectFillColor)" cx="3.0001" | ||
cy="0.0001" r="0.5" /> | ||
<circle class="sapIllus_ObjectFillColor" style="fill:var(--sapIllus_ObjectFillColor)" cx="0.0001" | ||
cy="0.0001" r="0.5" /> | ||
</pattern> | ||
</defs> | ||
</svg> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,246 @@ | ||
import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js"; | ||
import ResizeHandler from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js"; | ||
import { getIllustrationDataSync } from "@ui5/webcomponents-base/dist/asset-registries/Illustrations.js"; | ||
|
||
import { getI18nBundle, fetchI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js"; | ||
import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js"; | ||
import IllustratedMessageTemplate from "./generated/templates/IllustratedMessageTemplate.lit.js"; | ||
import IllustrationMessageType from "./types/IllustrationMessageType.js"; | ||
|
||
// Styles | ||
import IllustratedMessageCss from "./generated/themes/IllustratedMessage.css.js"; | ||
|
||
const ILLUSTRATION_NOT_FOUND = "ILLUSTRATION_NOT_FOUND"; | ||
|
||
/** | ||
* @public | ||
*/ | ||
const metadata = { | ||
tag: "ui5-illustrated-message", | ||
managedSlots: true, | ||
properties: /** @lends sap.ui.webcomponents.fiori.IllustratedMessage.prototype */ { | ||
/** | ||
* Defines the title of the component. | ||
* <b>Note:</b> Using this property, the default title text of illustration will be overwritten. | ||
* @type {string} | ||
* @defaultvalue "" | ||
* @since 1.0.0-rc.15 | ||
* @public | ||
*/ | ||
titleText: { | ||
type: String, | ||
}, | ||
/** | ||
* Defines the subtitle of the component. | ||
* <b>Note:</b> Using this property, the default subtitle text of illustration will be overwritten. | ||
* @type {string} | ||
* @defaultvalue "" | ||
* @since 1.0.0-rc.15 | ||
* @public | ||
*/ | ||
subtitleText: { | ||
type: String, | ||
}, | ||
/** | ||
* Determinates what is the current media of the component based on its width. | ||
* @private | ||
*/ | ||
media: { | ||
type: String, | ||
}, | ||
/** | ||
* Determinates whether illustration is invalid. | ||
* @private | ||
*/ | ||
invalid: { | ||
type: Boolean, | ||
}, | ||
/** | ||
* Defines the illustration name that will be displayed in the component. | ||
* <br><br> | ||
* Available illustrations are: | ||
* <ul> | ||
* <li><code>BeforeSearch</code></li> | ||
* <li><code>NoActivities</code></li> | ||
* <li><code>NoData</code></li> | ||
* <li><code>NoEntries</code></li> | ||
* <li><code>NoMail</code></li> | ||
* <li><code>NoNotifications</code></li> | ||
* <li><code>NoSavedItems</code></li> | ||
* <li><code>NoSearchResults</code></li> | ||
* <li><code>NoTasks</code></li> | ||
* <li><code>UnableToLoad</code></li> | ||
* <li><code>UnableToUpload</code></li> | ||
* </ul> | ||
* <br><br> | ||
* <b>Note:</b> By default BeforeSearch illustration is loaded. When using illustration type | ||
* it have to be loaded separately (<code>import @ui5/webcomponents-fiori/dist/illustrations/BeforeSearch.js";</code>). | ||
* @type {IllustrationMessageType} | ||
* @defaultvalue "BeforeSearch" | ||
* @since 1.0.0-rc.15 | ||
* @public | ||
*/ | ||
name: { | ||
type: IllustrationMessageType, | ||
defaultValue: IllustrationMessageType.BeforeSearch, | ||
}, | ||
}, | ||
slots: /** @lends sap.ui.webcomponents.fiori.IllustratedMessage.prototype */ { | ||
/** | ||
* Defines the component actions. | ||
* @type {sap.ui.webcomponents.main.Button[]} | ||
* @slot actions | ||
* @public | ||
*/ | ||
"default": { | ||
propertyName: "actions", | ||
type: HTMLElement, | ||
}, | ||
}, | ||
events: /** @lends sap.ui.webcomponents.fiori.IllustratedMessage.prototype */ { | ||
// | ||
}, | ||
}; | ||
|
||
/** | ||
* @class | ||
* | ||
* <h3 class="comment-api-title">Overview</h3> | ||
* An <code>ui5-illustrated-message</code> recommended combination of a solution-oriented message, an engaging | ||
* illustration, and conversational tone to better communicate an empty or a success state than just show | ||
* a message alone. | ||
* | ||
* Each illistration has default internationalised title and subtitle texts. Also they can be managed with | ||
* <code>titleText</code> and <code>subtitleText</code> properties. | ||
* | ||
* <b>Note:</b> By default BeforeSearch illustration is loaded. | ||
* | ||
* <h3>Usage</h3> | ||
* <code>ui5-illustrated-message</code> is meant to be used inside container component, for example a <code>ui5-card</code>, | ||
* a <code>ui5-dialog</code> or a <code>ui5-page</code> | ||
* | ||
* For the <code>ui5-illustrated-message</code> | ||
* <h3>ES6 Module Import</h3> | ||
* | ||
* <code>import @ui5/webcomponents-fiori/dist/IllustratedMessage.js";</code> | ||
* | ||
* @constructor | ||
* @author SAP SE | ||
* @alias sap.ui.webcomponents.fiori.IllustratedMessage | ||
* @extends UI5Element | ||
* @tagname ui5-illustrated-message | ||
* @public | ||
* @since 1.0.0-rc.15 | ||
*/ | ||
class IllustratedMessage extends UI5Element { | ||
constructor() { | ||
super(); | ||
|
||
this.i18nBundle = getI18nBundle("@ui5/webcomponents-fiori"); | ||
this._handleResize = this.handleResize.bind(this); | ||
} | ||
|
||
static get metadata() { | ||
return metadata; | ||
} | ||
|
||
static get render() { | ||
return litRender; | ||
} | ||
|
||
static get styles() { | ||
return IllustratedMessageCss; | ||
} | ||
|
||
static get template() { | ||
return IllustratedMessageTemplate; | ||
} | ||
|
||
static async onDefine() { | ||
await fetchI18nBundle("@ui5/webcomponents-fiori"); | ||
} | ||
|
||
static get BREAKPOINTS() { | ||
return { | ||
DIALOG: 679, | ||
SPOT: 319, | ||
BASE: 259, | ||
}; | ||
} | ||
|
||
static get MEDIA() { | ||
return { | ||
BASE: "base", | ||
SPOT: "spot", | ||
DIALOG: "dialog", | ||
SCENE: "scene", | ||
}; | ||
} | ||
|
||
onBeforeRendering() { | ||
const illustrationData = getIllustrationDataSync(this.name); | ||
|
||
if (illustrationData === ILLUSTRATION_NOT_FOUND) { | ||
this.invalid = true; | ||
/* eslint-disable-next-line */ | ||
return console.warn(`Required illustration is not registered. You can either import the illustration as a module in order to use it e.g. "@ui5/webcomponents-fiori/dist/illustrations/${this.name}.js".`); | ||
} | ||
|
||
this.invalid = false; | ||
this.spotSvg = illustrationData.spotSvg; | ||
this.dialogSvg = illustrationData.dialogSvg; | ||
this.sceneSvg = illustrationData.sceneSvg; | ||
|
||
this.illustrationTitle = this.i18nBundle.getText(illustrationData.title); | ||
this.illustrationSubtitle = this.i18nBundle.getText(illustrationData.subtitle); | ||
} | ||
|
||
onEnterDOM() { | ||
ResizeHandler.register(this, this._handleResize); | ||
} | ||
|
||
onExitDOM() { | ||
ResizeHandler.deregister(this, this._handleResize); | ||
} | ||
|
||
handleResize() { | ||
if (this.offsetWidth <= IllustratedMessage.BREAKPOINTS.BASE) { | ||
this.media = IllustratedMessage.MEDIA.BASE; | ||
} else if (this.offsetWidth <= IllustratedMessage.BREAKPOINTS.SPOT) { | ||
this.media = IllustratedMessage.MEDIA.SPOT; | ||
} else if (this.offsetWidth <= IllustratedMessage.BREAKPOINTS.DIALOG) { | ||
this.media = IllustratedMessage.MEDIA.DIALOG; | ||
} else { | ||
this.media = IllustratedMessage.MEDIA.SCENE; | ||
} | ||
} | ||
|
||
get effectiveIllustration() { | ||
switch (this.media) { | ||
case IllustratedMessage.MEDIA.SPOT: | ||
return this.spotSvg; | ||
case IllustratedMessage.MEDIA.DIALOG: | ||
return this.dialogSvg; | ||
case IllustratedMessage.MEDIA.SCENE: | ||
return this.sceneSvg; | ||
default: | ||
return ""; | ||
} | ||
} | ||
|
||
get effectiveTitleText() { | ||
return this.titleText ? this.titleText : this.illustrationTitle; | ||
} | ||
|
||
get effectiveSubitleText() { | ||
return this.subtitleText ? this.subtitleText : this.illustrationSubtitle; | ||
} | ||
|
||
get hasActions() { | ||
return !!this.actions.length && this.media !== IllustratedMessage.MEDIA.BASE; | ||
} | ||
} | ||
|
||
IllustratedMessage.define(); | ||
|
||
export default IllustratedMessage; |
Oops, something went wrong.