Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ui5-input to show "quickcard" ui5-popover pointing to an item #1768

Closed
codefactor opened this issue Jun 10, 2020 · 9 comments · Fixed by #1784
Closed

ui5-input to show "quickcard" ui5-popover pointing to an item #1768

codefactor opened this issue Jun 10, 2020 · 9 comments · Fixed by #1784
Assignees
Labels

Comments

@codefactor
Copy link
Contributor

codefactor commented Jun 10, 2020

Is your feature request related to a problem? Please describe.
The requirement is that when the user does a search on the ui5-shellbar, and then he does either of the following:

  1. Hovers his mouse onto one search result item for a length of time
  2. Selects the search result item with the arrow keys for a length of time

He is then indicating that he wants more information on this search result item - and we should show a <ui5-popover> that points to the search result item with more information. If he subsequently types the special keystroke Ctrl + Shift + 1 this will focus onto the Quick Card and allow him to navigate through the quick card (meanwhile the input loses focus, and the search results will disappear). Pressing Escape key will then close the Quick Card and focus back onto the Search Input -- it is questionable if at this point the user must retype his search or not, but in an ideal world it would open back to the previous search state as before he typed Ctrl + Shift + 1

However, there are several issues with our attempt to solve this with out of the box web components:

  1. Any events we attach to the <ui5-li> tags that are part of the <ui5-input>, such as onmouseover for example, do not make it into the static area clone of the <ui5-li> and so we do not get any mouse event callbacks using this approach
  2. We are not sure how to get a callback when the user has selected an item using the arrow key without pressing enter to select it.

Describe the solution you'd like
Can we get events for things like:

  1. User mouse over/out on an item
  2. User selects an item with keyboard (but not select yet)
  3. User presses a key such as Ctrl + Shift + 1

Describe alternatives you've considered
None yet

Additional context
image

The above shows the legacy quickcard, likely the new one will look a little different. The quick card is only aligned with the search item, the new one will be a popover with a pointer.

@ilhan007 ilhan007 self-assigned this Jun 12, 2020
ilhan007 added a commit that referenced this issue Jun 12, 2020
Add "suggestion-item-preview" event to notify when the user navigates to a suggestion item via the ARROW keys,
before he/she performs final selection.

Related to: #1768
vladitasev pushed a commit that referenced this issue Jun 12, 2020
Add "suggestion-item-preview" event to notify when the user navigates to a suggestion item via the ARROW keys,
before he/she performs final selection.

Related to: #1768
ilhan007 added a commit that referenced this issue Jun 15, 2020
The user can now bind for mouseover and mouseout events on the ui5-suggestion-item elements and perform some other action. For example: opening another popover, pointing to particular suggestion, when hovered.

FIXES: #1768
ilhan007 added a commit that referenced this issue Jun 15, 2020
The user can now bind for mouseover and mouseout events on the ui5-suggestion-item elements and perform some other action. For example: opening another popover, pointing to particular suggestion, when hovered.

FIXES: #1768
@ilhan007 ilhan007 reopened this Jun 16, 2020
@ilhan007
Copy link
Member

ilhan007 commented Jun 17, 2020

1. User mouse over/out on an item

To handle user mouseover an mouseout, you have to listen for the mouseover and mouseout events as follows:

suggestion.addEventListener("mouseover", function (event) {
	const targetRef = event.detail.targetRef; // the item rendered in the popover - ui5-li
        const item = event.target or event.detail.item // the logical item - ui5-suggestion-item
});

And, to open a popover, pointing to particular suggestion you can use the code below. Pay attention to the event details.
Note: The event.detail.targetRef is the rendered item in the popover you need as an opener of the quickview popover.
Note: Provide second parameter to "openBy" to prevent the quickview popover of applying focus immediately after opening, otherwise the suggestion would close:

suggestion.addEventListener("mouseover", function (event) {
	const targetRef = event.detail.targetRef;
     	quickViewCard.openBy(targetRef, true);
});

@ilhan007
Copy link
Member

ilhan007 commented Jun 17, 2020

2. User selects an item with keyboard (but not select yet)

To handle user navigation through the items you should listen for the suggestion-item-preview event as follows:

<ui5-input id="inputPreview" show-suggestions>
	<ui5-suggestion-item text="Cozy"></ui5-suggestion-item>
	<ui5-suggestion-item text="Compact"></ui5-suggestion-item>
</ui5-input>
inputPreview.addEventListener("suggestion-item-preview", function (event) {
	const item = event.detail.targetRef;

	quickViewCard.close(false, true, true); // close if already opened by another suggestion
	quickViewCard.openBy(item, true); // open with the current one
});

@ilhan007
Copy link
Member

3. User presses a key such as Ctrl + Shift + 1

To react on keyboard combinations like Ctrl + Shift + 1 you can listen for the keyup event and check the event.key:

inputPreview.addEventListener("keyup", function (event) {
	const combination = event.key === "1" && event.shiftKey && event.ctrlKey;
});

And, there is readonly property on the ui5-input, called "previewItem" you can always use to programatically get which is the item the user currently navigated to.

@ilhan007
Copy link
Member

ilhan007 commented Jun 17, 2020

Hello @codefactor as we discussed I left few comments above, explaining what we did to address the requests in the current issue.

And here is the link to the test page:
https://sap.github.io/ui5-webcomponents/master/playground/main/pages/Input/

ilhan007 added a commit that referenced this issue Jul 7, 2020
The change is related to the Quick View topic and affects the Input, InputSuggestions and Popover, and enables the following behaviour: (1) open an additional Popover from a suggestion on mouseover and suggestion-item-preview events, (2) to move the focus in that Popover, (3) to keep it open without a visible opener, and (4) the ability to get back via ESC.
Add parameter to the openBy method to prevent the popover from closing when its opener is not visible anymore
and use the old placement when the opener is gone (by default the popover would go to the top-left most corner).
Add public method Popup.prototype.applyFocus (the logic has been extracted from applyInitialFocus) that focuses the first focusable element inside the Popup
Change the focus retaining logic in Input/InputSuggestions as follows: returns the focus to the input field only when a suggestion is selected by the user, in other cases - does not, because otherwise focusing another popover would not be possible as the Input keeps getting focus again and again.
Previously it was not possible to use the "close" params with the ResponsivePopover, now it forwards them to the Popover.
Create a test page to show the entire flow

Related to: #1768
ilhan007 added a commit that referenced this issue Jul 7, 2020
The change is related to the Quick View topic and affects the Input, InputSuggestions and Popover, and enables the following behaviour: (1) open an additional Popover from a suggestion on mouseover and suggestion-item-preview events, (2) to move the focus in that Popover, (3) to keep it open without a visible opener, and (4) the ability to get back via ESC.
Add parameter to the openBy method to prevent the popover from closing when its opener is not visible anymore
and use the old placement when the opener is gone (by default the popover would go to the top-left most corner).
Add public method Popup.prototype.applyFocus (the logic has been extracted from applyInitialFocus) that focuses the first focusable element inside the Popup
Change the focus retaining logic in Input/InputSuggestions as follows: returns the focus to the input field only when a suggestion is selected by the user, in other cases - does not, because otherwise focusing another popover would not be possible as the Input keeps getting focus again and again.
Previously it was not possible to use the "close" params with the ResponsivePopover, now it forwards them to the Popover.
Create a test page to show the entire flow

Related to: #1768
@ilhan007
Copy link
Member

ilhan007 commented Jul 7, 2020

One more change to address the missing parts in the issue:

#1911
The change is related to the Quick View topic and affects the Input, InputSuggestions and Popover, and enables the following behaviour: (1) open an additional Popover from a suggestion on mouseover and suggestion-item-preview events, (2) to move the focus in that Popover, (3) to keep it open without a visible opener, and (4) the ability to get back via ESC.

test page:
https://sap.github.io/ui5-webcomponents/master/playground/main/pages/Input_quickview/

@codefactor
Copy link
Contributor Author

codefactor commented Jul 7, 2020

@ilhan007 ,

Can you please help me with some issues I'm having on my feature/wcQuickcard branch on the xweb/common-webcomponents repo?

The 2 issues I'm having are as follows:

  1. The Popover is not opening and closing consistently
  2. The listener on the mouseover event is not properly being triggered to activate the Popover
git clone https://github.wdf.sap.corp/xweb/common-webcomponents.git
cd common-webcomponents
git checkout feature/wcQuickcard
npm install
npm start

Open:
http://localhost:8081/test-resources/pages/Header.html

Then search for "ca" in the header --- you can try the following things to notice some issues:

  1. Arrow down to the first person
  2. Wait for Quickcard to open (0.5 seconds debounced)
  3. Arrow down to second person, and then back to first person, and also try going back up to the group header or actions above it
  4. Notice sometimes the Popover is not really closed properly -- and other times the popover does not open at all
  5. Also notice that using the mouse to hover to an item does not open the popup

You can see in the Header.hbs the following code:

    <ui5-input
      slot="searchField"
      id="search"
      placeholder="{{searchPlaceholder}}"
      value-state="{{globalSearch.searchValueState}}"
      show-suggestions
      @input={{_searchInput}}
      @submit={{_submitSearch}}
      @suggestionItemSelect={{_suggestionItemSelect}}
      @suggestionItemPreview={{_suggestionPreview}}
      @suggestionScroll={{_suggestionScroll}}
      @focusOut={{_reset}}>
......
    {{#each this.items}}
      <ui5-li
        data-path="{{this.path}}"
        class="{{this.class}}"
        icon="{{this.icon}}"
        image="{{this.image}}"
        description="{{this.description}}"
        info-state="{{this.infoState}}"
        info="{{this.info}}"
        @mouseover={{_suggestionPreview}}
        >{{this.label}}</ui5-li>
    {{/each}}
.......
    </ui5-input>
.......
  <ui5-popover id="qc">
    <xweb-person-quickcard subject="{{quickcardSubject}}" id-type="{{quickcardIdType}}" from-header></xweb-person-quickcard>
  </ui5-popover>
......

In short, the is passing the suggestionItemPreview event to the same function as the mouseover event on the <ui5-li> but for whatever reason the _suggestionPreview function only gets called for the keyboard suggestionItemPreview event and not the mouseover event. I can see, though, that by adding the event listener using addEventListener manually from the Javascript console in Dev Tools that the event is being triggered, but something is wrong with the way I am trying to get the mouseover event in this implementation with Handlebars / lit render.

@ilhan007
Copy link
Member

ilhan007 commented Jul 9, 2020

We prepared a change that makes the Quick View story working at least with the suggestion-item-preview event (still did not find why the mouseover is not fired) #1937

Once opened, both Suggestions Popover and QuickCardView will close if:

  • neither the SearchField nor the QuickCardView has the focus, because the user clicks somewhere outside or
    the user uses the TAB | SHIFT + TAB and the focus is somewhere else

Once opened, the QuickCardView remains open and Suggestions Popover closes if:

  • the focus moves to the QuickCardView, because the Popover.prototype.applyFocus method is called,
    the user clicks inside the QuickCardView or the user uses the TAB | SHIFT + TAB key and the focus is goes inside the QuickCardView

To open the QuickViewCard (note the the prevent-focus-restore attribute):

<ui5-popover prevent-focus-restore>

async _openQuickcardBy(person, targetRef /*, a11yAnnounce*/) {
     ...
    this._getElement("qc").openBy(targetRef, true /* preventInitialFocus */);
  }

To move the focus from the suggestions to the quickViewCard:

 <ui5-input @keyup={{_searchKeyup}}>

// Listen to the "keyup" event and if it the special combination is pressed
// focus the quickViewCard (perhaps a check if such is open should be added)
_searchKeyup(evt) {
    const combination = evt.key === "1" && evt.ctrlKey && evt.shiftKey;
    if (combination) {
        this._focusQuickcard();
    }
}

_focusQuickcard() {
    this._getElement("qc").applyFocus();
}

To get back from the quickViewCard to the SearchField on ESC pressed:

<ui5-popover prevent-focus-restore @before-close={{_onQuickCardClose}}>

// Listen when the quickViewCard closes and if it closes because of ESC,
// bring the focus to the Search Field
_onQuickCardClose (evt) {
    if (evt.detail.escPressed) {
        this._focusSearchField();
    }
}

 _focusSearchField() {
    this._getElement("search").focus();
}

@ilhan007 ilhan007 closed this as completed Jul 9, 2020
@ilhan007 ilhan007 reopened this Jul 9, 2020
@ilhan007
Copy link
Member

Hello Scott, your mouseover handler was not called, because it was not bound to the correct context. You have "each" statement in "each" statement in the Template, whereas the "_suggestionPreview" is available at the root context.
With the following code, the handler is now called:

 <ui5-suggestion-item @mouseover="{{../../context._suggestionPreview}}">
    {{this.label}}
</ui5-suggestion-item>

When you make it work you will see that the "item.getAttribute" in the handler fails, because the "mouseover" event does not provide the "item" detail param (as suggestionitemPreview), we will make it available so your code can handle both the and mouseover events the same way.

const { targetRef, item } = evt.detail;
const path = item.getAttribute("data-path");

@ilhan007
Copy link
Member

Here is the interaction after we merge the change mentioned

Screen Recording 2020-07-10 at 11.46.06 AM.zip

ilhan007 added a commit that referenced this issue Jul 17, 2020
Another PR to address the "QuickCardView" topic. The change keeps the Popover open, without an opener, if the focus is inside that popover.

add prevent-focus-restore protected property in addition to the preventFocusRestore param of Popup.prototype.close method, because the quickCardView might close due to user interaction - click, TAB, ESC.
remove the recently added _closeWithOpener param, as now the popover without an opener would remain open if the focus is inside it and will be closed otherwise.
QuickCardView Interaction (test it on http://localhost:8080/test-resources/pages/Input_quickview.html)

Once opened, both Suggestions Popover and QuickCardView will close if:
neither the SearchField nor the QuickCardView has the focus, because the user clicks somewhere outside or
the user uses the TAB | SHIFT + TAB and the focus is somewhere else

Once opened, the QuickCardView remains open and Suggestions Popover closes if:
the focus moves to the QuickCardView, because the Popover.prototype.applyFocus method is called,
the user clicks inside the QuickCardView or the user uses the TAB | SHIFT + TAB key and the focus is goes inside the QuickCardView

Closes: #1768
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants