Problem/Motivation

When switching between the Behavior and Content tabs, the last active paragraphs is not persisted and not visible on screen.

Proposed resolution

As a followup of #2901995, I suggest we fix the window position while switching between Behavior and Content tabs for Paragraphs.

Remaining tasks

User interface changes

API changes

Data model changes

CommentFileSizeAuthor
#36 paragraphs_3025693_scroll_36-interdiff.txt3.53 KBBerdir
#36 paragraphs_3025693_scroll_36.patch12.37 KBBerdir
#35 paragraphs_3025693_scroll_35-interdiff.txt7.37 KBBerdir
#35 paragraphs_3025693_scroll_35.patch12.58 KBBerdir
#35 paragraphs_3025693_scroll_35-test-only.patch5.94 KBBerdir
#34 paragraphs_3025693_scroll_34.patch210.5 KBsasanikolic
#31 Patch 31 - behavior tab.png160.92 KBsasanikolic
#31 Patch 31 - content tab.png168.49 KBsasanikolic
#31 paragraphs_3025693_scroll_31-interdiff.txt2.33 KBsasanikolic
#31 paragraphs_3025693_scroll_31.patch12.87 KBsasanikolic
#28 paragraphs_3025693_scroll_28.interdiff.txt3.81 KBsasanikolic
#28 paragraphs_3025693_scroll_28.patch10.86 KBsasanikolic
#26 paragraphs_3025693_scroll_25.interdiff.txt1.79 KBmiro_dietiker
#26 paragraphs_3025693_scroll_25.patch8.29 KBmiro_dietiker
#25 paragraphs_3025693_scroll_20.interdiff.txt2.21 KBmiro_dietiker
#25 paragraphs_3025693_scroll_20.patch5.42 KBmiro_dietiker
#24 interdiff-3025693-22-24.txt1.82 KBjohnchque
#24 paragraphs_3025693_scroll_24.patch8.41 KBjohnchque
#23 Selection_088.png20.28 KBmiro_dietiker
#22 interdiff-3025693-20-22.txt3.62 KBjohnchque
#22 paragraphs_3025693_scroll_22.patch8.92 KBjohnchque
#21 paragraphs_3025693_scroll_20.interdiff.txt2.21 KBmiro_dietiker
#21 paragraphs_3025693_scroll_20.patch5.42 KBmiro_dietiker
#19 paragraphs_3025693_scroll_18.patch5.78 KBmiro_dietiker
#17 paragraphs_3025693_scroll_17.patch5.88 KBmiro_dietiker
#16 3025693-scroll-persistency-16-interdiff.txt5.36 KBsasanikolic
#16 3025693-scroll-persistency-16.patch5.64 KBsasanikolic
#14 3025693-scroll-persistency-14-interdiff.txt699 bytessasanikolic
#14 3025693-scroll-persistency-14.patch5.11 KBsasanikolic
#13 3025693-scroll-persistency-13-interdiff.txt2.84 KBsasanikolic
#13 3025693-scroll-persistency-13.patch5.17 KBsasanikolic
#11 3025693-scroll-persistency-11-interdiff.txt4.62 KBsasanikolic
#11 3025693-scroll-persistency-11.patch4.14 KBsasanikolic
#8 3025693-scroll-persistency-8-with-active-paragraph-test.patch2.97 KBsasanikolic
#8 3025693-scroll-persistency-8-interdiff.txt1.23 KBsasanikolic
#8 3025693-scroll-persistency-8.patch2.42 KBsasanikolic
#6 3025693-scroll-persistency-6-interdiff.txt3.3 KBsasanikolic
#6 3025693-scroll-persistency-6.patch2.44 KBsasanikolic
#3 3025693-scroll-persistency-3.patch1.71 KBsasanikolic
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

sasanikolic created an issue. See original summary.

miro_dietiker’s picture

Priority: Normal » Major

Promoting for better editing UX.

sasanikolic’s picture

My idea was to add a class to the first paragraph in the viewport and scroll to that when switching tabs. Does this make sense? It basically works, but not sure about the user experience. This attached patch does that.

sasanikolic’s picture

Status: Active » Needs review
miro_dietiker’s picture

Yeah we need such a reference. Two additional inputs though:

Sometimes i‘m interacting with the Paragraph that starts inside the Viewport. The first would then be the previous one and scroll too much up. I like to see the whole Paragraph in the viewport if possible.

Maybe we could check if there is an active paragraph, also by considering the form element in focus. If such an element is present, we should use its Paragraph as a reference. That would solve the first problem as well for many cases.

We still need a fallback if no element is in focus. Don‘t know which case happens how often - this needs testing.

sasanikolic’s picture

Did some refactoring and improvements for the scrolling position. The issues were caused by the sticky positioned elements, such as admin bar and sticky tabs.

Regarding the form element in focus, we don't have such thing yet, that's why I opened this issue the other day #3036530, where we would add the focused paragraph indicator. I think that would just add complexity to this issue.

Please test the new patch and see if that works better / as expected.

miro_dietiker’s picture

I understood that the other issue was about visually indicating the active element. Otherwise please extend its description to provide an API.
It's clear we need an API and know what is active, but i'm unsure about the visual indication of such an active Paragraph.

I wouldn't expect that this adds so much complexity here, except the one-off-problem is very well solved.?
See document.activeElement
https://developer.mozilla.org/en-US/docs/Web/API/DocumentOrShadowRoot/ac...
We can easily check if one of the form elements has focus and then determine its parent Paragraph widget as active.
Do you think it adds that much complexity?

sasanikolic’s picture

Fixed some scrolling issue in this patch.

Tried getting the active element on mouseup event, so whenever the user would click on a paragraph, we would get the current element and persist the position based on it, but the issue is with ckeditor iframe and the Edit paragraph button, as the event does not happen there. Adding also a patch with a function to test that.

miro_dietiker’s picture

Status: Needs review » Needs work

Did some research about what has a minimal complexity and still is of biggest value for our users.
So to be clear, we don't want to maintain workarounds like mouse-up events and other crazy event handlers.
Our approach will have some limitations, but it is the job of Core to indicate the active (form, widget) element and we will build on top of that once it is available.

Core Layout builder tries to identify the active element when opening actions in dialogs, see #2994909: Highlight active element while working with dialogs in Layout Builder

We only want to scroll if a Paragraphs field is inside the Viewport and the behavior tabs are present and sticky.
Thus we should start with fixing these tabs while scrolling into a Paragraph field.

Then while the sticky tabs are present, we can easily determine a highlighted reference Paragraph when clicking one of the tabs:

  • The first Paragraph who starts below the sticky tabs (and starts above the viewport end)
  • Or if missing, the first Paragraph in that field

That Paragraph will be marked as highlighted with a class.
The highlight class will apply the usual hover blue #f7fcff - maybe a bit stronger?
And then the class is immediately removed again, resulting in a CSS phase-out transition of the color highlight.

The user has then a visible reference in the Viewport.

A first version is fine if it only acts on most top level.
However we might prefer to apply this logic to the most nested Paragraph as a reference point.

miro_dietiker’s picture

Ah, almost forgot... The scrollto action after tab switching scrolls the highlighted reference paragraph to the same vertical screen offset as it was before! Don't put it to the viewport top.

sasanikolic’s picture

This patch includes the fixes mentioned above.

Note that this change for the background animation affects also the paragraphs hover state.

What do you mean by the same vertical screen offset as it was before? Currently it scrolls to the top of the first-level (parent) paragraph.

Berdir’s picture

Yes, and instead of scrolling to the top of that, it should consider the height difference that the paragraph had to the top so that it remains at basically the same position.

I'm also not quite sure how this makes without sticky content/behaviors, so we either need to include that or do that first in a separate issue.

sasanikolic’s picture

I added a lot of comments and fixes for the scroll position. I'm saving the current position on the content tab, so this should work now.

sasanikolic’s picture

Sorry for the spam, here i fixed the empty lines at the end of files.

miro_dietiker’s picture

Status: Needs review » Needs work
+++ b/js/paragraphs.admin.js
@@ -89,11 +115,45 @@
+            if ($(this).parent().attr('id') === 'behavior') {

Why would we only want to determine the position in one case?

You can scroll up / down on each of the two tabs. On each switch, we should determine the reference of the current situation before switching.

sasanikolic’s picture

This maintains the scroll positions for both tabs whenever the first paragraph is the same. Once we scroll to another paragraph, when switching tabs the page will scroll to the top of the new paragraph. Does this make more sense?
Also improved some comments.

miro_dietiker’s picture

Did some more testing here and there is some more work to do.

Much confused about the use of $allParagraphs.filter(function () {
And then not returning anything at all... I guess you intended .each?
See also

You can stop the loop from within the (each) callback function by returning false.

Let's avoid global variables like setScrollPosition. Instead markFirstVisibleParagraph can return true or even the element in case of success.
...

Here is a reimplementation of the calculation that also will need many less special cases...
Still needs more testing and maybe polishing.
We should not animate scrollto as the element visually appears persistent (stable vertical offset) with its scroll position. An animation adds confusion.

miro_dietiker’s picture

Issue tags: +Needs tests

We also need tests. :-)

miro_dietiker’s picture

More clean-ups and some todo's

miro_dietiker’s picture

We are still missing the tabs stickyness part in this issue.

miro_dietiker’s picture

Improved the code again to make it work with nested Paragraphs.
This even reduced code complexity again - wohoo!

Now tests for real.

johnchque’s picture

Starting to work on tests. Had some problems with setting the height of the browser. Will continue investigating tomorrow.

miro_dietiker’s picture

Status: Needs review » Needs work
FileSize
20.28 KB

Tested and the tabs stickyness works for me.

However the tests above contain multiple special cases of the sticky tabs positioning, varying toolbar cases and also a special case in the library edit dialog. This all would need to be tested with the various additional toolbar modules (Admin Toolbra, ..?) as well...

And i even found a bug on desktop when the secondary toolbar is collapsed:

So it seems we can only let this in as an opt-in (widget setting to enable sticky tabs) to avoid breaking UX for existing users. Then we can limit the supported cases explicitly and caring about more with proper test coverage (and thus document them) in follow-ups.

johnchque’s picture

Status: Needs work » Needs review
FileSize
8.41 KB
1.82 KB

Removing some css that is not needed, fixing the problem described in the screenshot of the previous comment.

miro_dietiker’s picture

Now the sticky position of the tabs work also on collapsed secondary toolbar level.

But when it is collapsed, the scrolling position is not preserved.

+++ b/js/paragraphs.admin.js
@@ -92,8 +140,45 @@
+          // If the tabs are sticky (offset positions are the same),
+          // find the first paragraph and attach a class to it.

I extended the calculation without that condition and added another early exit point to maintain top level elements better.

miro_dietiker’s picture

Berdir’s picture

Status: Needs review » Needs work

Looks like the tests need work, that's pretty empty still.

sasanikolic’s picture

Added the tests for switching the tabs and a default top position fix. I noticed in the test that the .toolbar-fixed was missing, therefore the paragraph tabs were not sticky.

Status: Needs review » Needs work

The last submitted patch, 28: paragraphs_3025693_scroll_28.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

miro_dietiker’s picture

Can you please explain / comment in tests about what you're testing?
I can not see that the test is scrolling to any specific position and yet it is expecting that the first item is not visible?

sasanikolic’s picture

I added some comments to the test. What I tried to test here is the scroll persistency, as I couldn't find any command to scroll to a specific element. I'd like to add that though. Do you know if some command for scrolling exists?

And yes, it is expecting that the first item is not visible, because when we add all those paragraphs, the viewpoint on that window size looks like in this screenshot of the content/behavior tab viewports attached.

Not sure why it fails, as the test passes locally.

Status: Needs review » Needs work

The last submitted patch, 31: paragraphs_3025693_scroll_31.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

miro_dietiker’s picture

Oh i thought we committed this long ago.

We're using this in production and i never had any issue with the position adjustment here, so it seems quite solid.

Re-reading test coverage in #31 and it looks fine now.
It only needs to pass.. :-)

sasanikolic’s picture

Status: Needs work » Needs review
FileSize
210.5 KB

I cleaned up the patch, I think there was an unrelated change in there for the ParagraphsExperimentalAddModesTest.

Berdir’s picture

Couldn't reproduce the test fail either but it also pretty pretty fickle with so many empty paragraphs.

I've changed it to have a string_long text field in there which I think is already a much better representation of how a real form looks. Limited the amount of paragraphs we add and tried to get an even baseline by moving to a defined position (the second of 4 paragraphs).

Also rewrote the initial part of the test to use our test helper methods to create node type and paragraph field, saves a ton of code and is considerably faster.

Lets see if testbot likes this more.

(Also removed the yarn lock file and fixed the unrelated field_group changes).

Berdir’s picture

Well that didn't help.

Did a lot of debugging, first thought it might be related to the test software overlay headless or not, but not sure. After updating to latest chromedriver version I did get a (different value), so lets try this approach to see if that helps.

Also removed an unused variable in JS.

  • Berdir committed 0e52320 on 8.x-1.x
    Issue #3025693 by sasanikolic, miro_dietiker, Berdir, yongt9412: Scroll...
Berdir’s picture

Status: Needs review » Fixed

Lets hope this doesn't cause any random fails or so :) Committed.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.