Skip to content

Commit

Permalink
feat(ui5-badge): add different design types (#7564)
Browse files Browse the repository at this point in the history
* feat(ui5-badge): add different design types
  • Loading branch information
TeodorTaushanov committed Jan 9, 2024
1 parent 782350e commit e5895f7
Show file tree
Hide file tree
Showing 16 changed files with 1,578 additions and 121 deletions.
31 changes: 26 additions & 5 deletions packages/main/src/Badge.hbs
Original file line number Diff line number Diff line change
@@ -1,9 +1,30 @@
<div class="ui5-badge-root">
<slot name="icon"></slot>
{{#if interactive}}
<button class="ui5-badge-root"
title="{{_title}}"
aria-roledescription="{{_roleDescription}}"
aria-description="{{_valueState}}"
@onclick={{_onclick}}
>
{{> content}}
</button>
{{else}}
<div class="ui5-badge-root"
title="{{_title}}">
{{> content}}
</div>
{{/if}}

{{#*inline "content"}}
<slot name="icon"></slot>
{{#if this._semanticIconName}}
<ui5-icon class="ui5-badge-semantic-icon" name="{{_semanticIconName}}"></ui5-icon>
{{/if}}
<span class="ui5-hidden-text">{{badgeDescription}}</span>
{{#if hasText}}
<label class="ui5-badge-text"><bdi><slot></slot></bdi></label>
<span class="ui5-badge-text"><bdi><slot></slot></bdi></span>
{{/if}}
{{/inline}}




<span class="ui5-hidden-text">{{badgeDescription}}</span>
</div>
167 changes: 158 additions & 9 deletions packages/main/src/Badge.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,32 @@
import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js";
import event from "@ui5/webcomponents-base/dist/decorators/event.js";
import property from "@ui5/webcomponents-base/dist/decorators/property.js";
import slot from "@ui5/webcomponents-base/dist/decorators/slot.js";
import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
import { getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js";
import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js";
import willShowContent from "@ui5/webcomponents-base/dist/util/willShowContent.js";

import Icon from "./Icon.js";
import "@ui5/webcomponents-icons/dist/sys-help-2.js";
import "@ui5/webcomponents-icons/dist/sys-enter-2.js";
import "@ui5/webcomponents-icons/dist/error.js";
import "@ui5/webcomponents-icons/dist/alert.js";
import "@ui5/webcomponents-icons/dist/information.js";
import WrappingType from "./types/WrappingType.js";
import BadgeDesign from "./types/BadgeDesign.js";
// Template
import BadgeTemplate from "./generated/templates/BadgeTemplate.lit.js";

import { BADGE_DESCRIPTION } from "./generated/i18n/i18n-defaults.js";
import {
BADGE_DESCRIPTION_BADGE,
BADGE_DESCRIPTION_TAG,
BADGE_ROLE_DESCRIPTION,
BADGE_ERROR,
BADGE_WARNING,
BADGE_SUCCESS,
BADGE_INFORMATION,
} from "./generated/i18n/i18n-defaults.js";

// Styles
import badgeCss from "./generated/themes/Badge.css.js";
Expand All @@ -19,14 +35,15 @@ import badgeCss from "./generated/themes/Badge.css.js";
* @class
* <h3 class="comment-api-title">Overview</h3>
*
* The <code>ui5-badge</code> is a small non-interactive component which contains text information and color chosen from a list of predefined color schemes.
* It serves the purpose to attract the user attention to some piece of information (state, quantity, condition, etc.).
* The <code>ui5-badge</code> is a component which serves
* the purpose to attract the user attention to some piece
* of information (state, quantity, condition, etc.).
* It can contain icon and text information, and its design can be chosen from specific design types.
*
* <h3>Usage Guidelines</h3>
* <ul>
* <li>If the text is longer than the width of the component, it doesn’t wrap, it shows ellipsis.</li>
* <li>When truncated, the full text is not visible, therefore, it’s recommended to make more space for longer texts to be fully displayed.</li>
* <li>Colors are not semantic and have no visual representation in High Contrast Black (sap_belize_hcb) theme.</li>
* <li>If the text is longer than the width of the component, it can wrap, or it can show ellipsis, depending on the <code>wrappingType</code> property.</li>
* <li>Colors can be semantic or not semantic.</li>
* </ul>
*
* <h3>ES6 Module Import</h3>
Expand All @@ -47,8 +64,31 @@ import badgeCss from "./generated/themes/Badge.css.js";
renderer: litRender,
template: BadgeTemplate,
styles: badgeCss,
dependencies: [
Icon,
],
})

/**
* Fired when the user clicks on an interactive badge.
* <b>Note:</b> The event will be fired if the <code>interactive</code> property is <code>true</code>
* @event sap.ui.webc.main.Badge#click
* @public
* @since 1.20
*/
@event("click")
class Badge extends UI5Element {
/**
* Defines the design type of the component.
* @type {string}
* @name sap.ui.webc.main.Badge.prototype.design
* @defaultvalue "Set3"
* @public
* @since 1.20
*/
@property({ defaultValue: BadgeDesign.Set3 })
design!: `${BadgeDesign}`;

/**
* Defines the color scheme of the component.
* There are 10 predefined schemes.
Expand All @@ -63,6 +103,44 @@ class Badge extends UI5Element {
@property({ defaultValue: "1" })
colorScheme!: string;

/**
* Defines if the default state icon is shown.
* @type {boolean}
* @name sap.ui.webc.main.Badge.prototype.hideStateIcon
* @defaultValue false
* @public
* @since 1.20
*/
@property({ type: Boolean })
hideStateIcon!: boolean;

/**
* Defines if the component is interactive (focusable and pressable).
* <br><b>Note:</b> The badge cannot be <code>interactive</code>
* when <code>design</code> property is <code>BadgeDesign.Set3</code>
* @type {boolean}
* @name sap.ui.webc.main.Badge.prototype.interactive
* @defaultValue false
* @public
* @since 1.20
*/
@property({ type: Boolean })
interactive!: boolean;

/**
* Defines how the text of a component will be displayed when there is not enough space.
* <br><b>Note:</b> For option "Normal" the text will wrap and the
* words will not be broken based on hyphenation.
*
* @name sap.ui.webc.main.Badge.prototype.wrappingType
* @type {sap.ui.webc.main.types.WrappingType}
* @defaultvalue "None"
* @public
* @since 1.20
*/
@property({ type: WrappingType, defaultValue: WrappingType.None })
wrappingType!: `${WrappingType}`;

/**
* Defines if the badge has an icon.
* @private
Expand All @@ -77,6 +155,13 @@ class Badge extends UI5Element {
@property({ type: Boolean })
_iconOnly!: boolean;

/**
* Defines if the badge has "Tag" design type.
* @private
*/
@property({ type: Boolean })
_isTagDesign!: boolean;

/**
* Defines the text of the component.
* <br><b>Note:</b> Although this slot accepts HTML Elements, it is strongly recommended that you only use text in order to preserve the intended design.
Expand Down Expand Up @@ -107,8 +192,28 @@ class Badge extends UI5Element {
}

onBeforeRendering() {
this._hasIcon = this.hasIcon;
this._hasIcon = this.hasIcon || !!this._semanticIconName;
this._iconOnly = this.iconOnly;
this._isTagDesign = this.design !== BadgeDesign.Set3;
}

get _roleDescription() {
return Badge.i18nBundle.getText(BADGE_ROLE_DESCRIPTION);
}

get _valueState() {
switch (this.design) {
case BadgeDesign.Positive:
return Badge.i18nBundle.getText(BADGE_SUCCESS);
case BadgeDesign.Negative:
return Badge.i18nBundle.getText(BADGE_ERROR);
case BadgeDesign.Critical:
return Badge.i18nBundle.getText(BADGE_WARNING);
case BadgeDesign.Information:
return Badge.i18nBundle.getText(BADGE_INFORMATION);
}

return undefined;
}

get hasText() {
Expand All @@ -123,8 +228,52 @@ class Badge extends UI5Element {
return this.hasIcon && !this.hasText;
}

get _title() {
return this.title || undefined;
}

get badgeDescription() {
return Badge.i18nBundle.getText(BADGE_DESCRIPTION);
if (this.interactive) {
return undefined;
}

if (this.design === BadgeDesign.Set3) {
return Badge.i18nBundle.getText(BADGE_DESCRIPTION_BADGE);
}

const valueState = this._valueState;
let description = Badge.i18nBundle.getText(BADGE_DESCRIPTION_TAG);

if (valueState) {
description = `${description} ${valueState}`;
}

return description;
}

get _semanticIconName() {
if (this.hideStateIcon || this.hasIcon) {
return null;
}

switch (this.design) {
case BadgeDesign.Neutral:
return "sys-help-2";
case BadgeDesign.Positive:
return "sys-enter-2";
case BadgeDesign.Negative:
return "error";
case BadgeDesign.Critical:
return "alert";
case BadgeDesign.Information:
return "information";
default:
return null;
}
}

_onclick() {
this.fireEvent("click");
}
}

Expand Down
20 changes: 19 additions & 1 deletion packages/main/src/i18n/messagebundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,25 @@ AVATAR_GROUP_ARIA_LABEL_GROUP=Conjoined avatars.
AVATAR_GROUP_MOVE=Press ARROW keys to move.

#XACT: ARIA announcement for the badge
BADGE_DESCRIPTION=Badge
BADGE_DESCRIPTION_BADGE=Badge

#XACT: ARIA announcement for the badge with "Tag" design
BADGE_DESCRIPTION_TAG=Tag

#XACT: ARIA announcement for the roledescription attribute
BADGE_ROLE_DESCRIPTION=Tag button

#XACT: ARIA announcement for the "Error" state
BADGE_ERROR=Error

#XACT: ARIA announcement for the "Warning" state
BADGE_WARNING=Warning

#XACT: ARIA announcement for the "Success" state
BADGE_SUCCESS=Success

#XACT: ARIA announcement for the "Information" state
BADGE_INFORMATION=Information

#XACT: position (current and max. value) of a Breadcrumb item which should be announced by screenreaders
BREADCRUMB_ITEM_POS={0} of {1}
Expand Down
Loading

0 comments on commit e5895f7

Please sign in to comment.