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.55k stars 266 forks source link

SAP Enable Now: Support for data-help-id on targeted shadowDOM elements #1840

Closed codefactor closed 4 years ago

codefactor commented 4 years ago

Is your feature request related to a problem? Please describe. SuccessFactors integrates with the SAP Enable Now (see https://www.sap.com/products/enable-now/features.html), sometimes called Web Assistant or User Assistant. For the global header we have a set of data-help-id values that need to be maintained from one release to the next, and the web assistant will use that data-help-id to find the element on the page, and somehow target the ClientRect for this element.

You could imagine the following code (not really from WebAssistant):

function highlightById(helpid) {
  const el = document.querySelector(`[data-help-id="${helpid}"]`);
  const rect = el && el.getClientRects();
  rect && highlightRegion(rect); // not implemented here
}

Now consider the following HTML:

<ui5-tabcontainer>
  <ui5-tab data-help-id="helpTab" text="Help"></ui5-tab>
  <ui5-tab data-help-id="formsTab" text="Forms"></ui5-tab>
</ui5-tabcontainer>

In this case - the data-help-ids are identified on <ui5-tab> elements; however, those elements have no ClientRect, because the actual <li> tag that the <ui5-tabcontainer> renders is the shadowRoot is the "real tab" and this one is just a placeholder which contains the text as an attribute.

Note that this would work fine with the following HTML:

<ui5-button data-help-id="myButton">Hello World</ui5-button>

The above button would work as expected from the Web Assistant perspective.

This same issue plagues a few different Web Components, and in general we need some sort of strategy for an external process to identify ClientRects on the page given a unique identifier. We may have some opportunity to change how the Web Assistant looks up the ClientRect; however, it would be great if the code did not need to change (since that would require to involve other teams and makes things more complicated).

For example - most of the things in the header would also need to be targeted, such as the search button, menu button, profile button, etc.

Describe the solution you'd like The same code would work for the <ui5-tab> as it does for <ui5-button> at least the ClientRect would be returned correctly (if that's possible).

Describe alternatives you've considered Provide some other type of attribute on the <ui5-tab> which could be written to the shadowDOM's <li> as the data-help-id attribute, and then the Web Assistant could be changed to somehow "walk" the DOM and every shadowRoot on the page looking for a light/shadow DOM element with data-help-id

Here is another idea:

<ui5-shellbar>
  <ui5-help-id slot="menuButton" data-helpid="bizxHeaderModulePicker"></ui5-help-id>
</ui5-shellbar>

In the above example, the data-helpid="bizxHeaderModulePicker" is now present in the light DOM, but somehow the getClientRect is magically returning the rect of the menu button at the top left corner of the shellbar??

vladitasev commented 4 years ago

@codefactor,

I think this is a valid point, SAP Enable Now integration has been mentioned before, but never really worked on.

I see 2 solutions to the problem:

We'll try to integrate a test page with SAP Enable Now, and we can start from there.

codefactor commented 4 years ago

@vladitasev ,

I was looking into Help4.js, which you can go to SuccessMap to debug through -- they use Element#getBoundingClientRect() to determine an element's position.

How about we do the following:

  1. Important shadow DOM that is driven by attributes (e.g. show-co-pilot or show-product-switch) will get a new slot so something with the helpid can show up in the light dom, like this <ui5-help slot="coPilotHelp" data-help-id="bizxCoPilot"></ui5-help>, the new tag will not have any shadowRoot and by default is not visible at all
  2. Elements (like the new <ui5-help> or <ui5-tab>) which only make sense to be slotted into something else (like <ui5-shellbar> or <ui5-tabcontainer>) and do not take up space on their own because the parent they have slotted into has a corresponding shadowDOM element; let's call these special "proxy" elements.
  3. The "proxy" elements can override Element#getBoundingClientRect and maybe one or more other things - so if something else (like Help4.js from EnableNow) is trying to determine where this Proxy element is located on the screen, the position it receives will be the same as the corresponding shadow element instead.

I think this would be a pretty clean solution - and we can prove that it works well with EnableNow.

fifoosid commented 4 years ago

Hello @codefactor,

The following PR implements what might be really convenient for you. Please take a look at it and if possible test out if the getStableDomRef method works for your use case. Looking forward to discuss the solution.

codefactor commented 4 years ago

@fifoosid ,

Looks good so far - I made a comment in the PR - I think you are missing the ShellBarItem which is similar to the Tab. The strategy seems good to me.

fifoosid commented 4 years ago

You have a point, looks like I have missed that. It is now implemented as well.