SAP / ui5-webcomponents

UI5 Web Components - the enterprise-flavored sugar on top of native APIs! Build SAP Fiori user interfaces with the technology of your choice.
https://sap.github.io/ui5-webcomponents/
Apache License 2.0
1.47k stars 254 forks source link

UI5WebComponents Enablement: Badge Concept #4624

Open ilhan007 opened 2 years ago

ilhan007 commented 2 years ago

Description

In UI5 Web Components it is necessary to enable the same badge functionality as in UI5 Controls - https://blogs.sap.com/2021/02/04/badge-support-in-ui5-controls/. Please carefully consider how the implentation will work in the enablement context.

Implementation

After discussions, we've come to a common agreement to implement badge support in each component using a slot - #5418, instead of a feature - #5469. Keep in mind that this is just a general guideline.

The slot may accept:

How to implement:

To implement badge support (e.g. for ui5-button):

  1. Define a badge slot:

packages/main/src/Button.js:

slots: /** @lends sap.ui.webcomponents.main.Button.prototype */ {
    /**
     * Defines the optional badge that will be used.
     * <b>Note:</b> While the slot allows for custom badges, to achieve the
     * Fiori design, please use <code>ui5-badge</code> with a text node inside.
     *
     * @type 
     * @slot
     * @public
     * @since 1.7.0
     */
    badge: {
        type: HTMLElement,
    },
}
  1. Same as above, for the Handlebars template:

packages/main/src/Button.hbs:

<button>
...
    <slot name="badge"></slot>
...
</button>
  1. Use the ::slotted([slot="badge"]) selector to apply styles:

packages/main/src/themes/Button.css:

::slotted([slot="badge"]) {
        padding: 5%;
    min-width: 1rem;
    background: var(--sapContent_BadgeBackground);
    border-color: var(--sapContent_BadgeBackground);
    color: var(--sapContent_BadgeTextColor);
    padding: .25rem;
    border-radius: 1rem;
    justify-content: center;
    font-size: var(--sapFontSmallSize);
    margin-inline-start: 0.25rem;
}

Example usage:

In UI5 Web Components:

<!-- With ui5-badge -->
<ui5-button>
    Press
    <ui5-badge slot="badge">
        <ui5-icon slot="icon" name="accelerated"></ui5-icon>
    </ui5-badge>
</ui5-button>

<!-- With a custom element -->
<ui5-button>
    Press
    <span slot="badge" class="my-custom-badge">5</span>
</ui5-button>

In UI5 Enablement:

<main:Avatar initials="AB">
    <badge>
        <Badge>
            <icon>
                <Icon name="accept" slot="icon" />
            </icon>
        </Badge>
    </Badge>
</main:Avatar>

Implemented components:

slin-sap commented 1 month ago

This planed approach doesn't seem to be optimal to me. This applies to Badge in UI5 webc 1.0 and the renamed Tag in 2.0.

Using badge as a slot, the parents of badge need to be adjusted to support positioning badge. This needs to be done for all the controls that need to support badge one by one.

It is better to implement badge as a container using a structure like this:

<badge-root>
    <slot><slot>
    <badge-div></badge-div>
</badge-root>

The div that hold the badge rendering<badge-div> is the 2nd child so that it has higher z-index over slot. You only need to update the badge implementation, and any other webcomponent can have the badge attached to it without any modifications.

You can take a look at popular UI frameworks and they use badge as container:

Material UI: https://mui.com/material-ui/react-badge/ Ant Design: https://ant.design/components/badge

slin-sap commented 1 month ago

@niyap Thanks for reviewing the issues I created. Since this issue already exists, I didn't created a new one and instead I commented my request above. Could you also review this request?

ilhan007 commented 1 month ago

Hello there and really sorry for the delay in our answer...

If I understood the suggestion, it is to wrap a given web component like this:

<Badge badgeContent={4} color="secondary">
  <MailIcon color="action" />
</Badge>

The problem that we have seen with that, because I think we discussed it also, is that we have cases like with the tabs and tab container, where the component with a badge is slotted/aggregated into other component

<TabContainer>
    <Badge badgeContent={4} color="secondary">
        <Tab><Tab/>
    </Badge>
</TabContainer>

And the TabContainer expects tabs and this leads to other complications.

So I would even be more in favour for built-in functionality as there are only 3/4 components with badging design (of course we can think how to generally provide it, but then we have to think for the case with the tabs I mentioned) like: ui5-tab badge={} ui5-button badge={}

However I think you are talking about the topic from component development aspect not just using the button, tab, etc that are supposed to have badging. Is it the case that you want to create a ui5 web component that should have badge, and you find difficult the part we describe: use the slotted selector to place/style the badge? In this aspect we can think about some reuse of styles, but I think that the badges across components are not like at the same place, maybe the layering is the same - the badge is always on top of the component that is associated with.

Did I get more or less the topic you are bringing, or I am going into different direction

Br ilhan

slin-sap commented 1 month ago

Hi @ilhan007

Thanks a lot for the detailed explanation. Now I understand the original design choice better.

I would still suggest using badge as a container and workaround for tab case. Please see below:

  1. For the built-in UI5 webcomponents, it maybe true that there is only 3 or 4 components require badge. But implementing badge as a container would allow any customize web components to integrate with badge easily. This prompts reuse of UI5 badge web component.

So I would even be more in favour for built-in functionality as there are only 3/4 components with badging design

  1. Tab can be modified to support badge. I can see the Tab webcomponent now accepts "text" and "icon" properties. It should be possible to support an additional that allow customized content in the tab.
<ui5-tabcontainer>
    <ui5-tab icon="menu" text="Tab 1">
        <ui5-tab-content slot="tab-content">
           <ui5-badge>...</ui5-badge>
        </ui5-tab-content>
        <ui5-label>Quibusdam, veniam! Architecto debitis iusto ad et, asperiores quisquam perferendis reprehenderit ipsa voluptate minus minima, perspiciatis cum. Totam harum necessitatibus numquam voluptatum.</ui5-label>
    </ui5-tab>
</ui5-tabcontainer>    
  1. So far we don't have design that require place badge at different locations. But it is not uncommon to have such design. Such support is also easier if badge is implemented as a container, since the placement support only needs to be handled within badge.

E.g. Teletrik badge placement design spec Google Material badge alignment design spec

Overall, I think implementing badge as container would gives benefits: