Problem/Motivation

ComponentForm has 2 issues:

  • it is complicated UX
  • it is sometimes slow

They are already addressed:

But there is another change we can do which will help on both subjects.

Proposed resolution

Today, when we load ComponentForm, the source selectors are populated for every props and slots, even if we will not edit them before saving the config.

Those selects are costly to build because we check source plugin availability and context matching for all of them.

Proposal: instead of populating the selects like today:

current

Let's generate a button with the selected/default source as a value:

proposal

When we click on it, an AJAX command replace the button with the expected select list.

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

pdureau created an issue. See original summary.

pdureau’s picture

Issue summary: View changes
goz’s picture

It's a performance solution, but, in my opinion, a bad thing for UX.
The idea is still great, may be we can find something to solve UX.

UX issue:
It's a button, we are not used to have a button in a form to display a select list / other options to configure switch a field. If i saw this button, i will don't know why it's here and what is its purpose. It's not intuitive.

Proposal:
1/ May be we could add some things with this button so we understand it's a default source and we can change it. May be adding an arrow inside the button, at right like a select list does ?
2/ Be more verbose, with text AND a button : <span>Current source : URL</span><button>Change source</button>

duaelfr’s picture

I like goz's second idea and I think this could also work when nothing has been configured yet:

Props

  • URL: Data from field (field_link) Change source for URL
  • Color: -None- Change source for Color

We would have to define a way to display a "summary" of the existing settings but this would be way more effective for performances because we would only need to load forms on demand. The downside is still usability because it's one more click in an UI that already needs a lot.

pdureau’s picture

Thanks both for your feedbacks :)

We would have to define a way to display a "summary" of the existing settings but this would be way more effective for performances

We have this now #3519282: [2.0.4] Add PluginSettingsInterface::settingsSummary()

smovs’s picture

I like proposal #2 by @goz.

It would improve performance by reducing unnecessary load and avoiding the need to build the dropdown each time, which also helps users notice that there are more options for selection.

asherry’s picture

This has definitely become more of an issue in our case. I'm using the components through ui_patterns_blocks in layout builder and the block edit form ends up with a load time of around 10 seconds each time. Then each subsequent time you change the slot source it's another 10 seconds.
I get why the interface is difficult, this is a needle in a haystack. This is basically, "hey, select pretty much anything in your entire site to embed here".

The only way I've gotten through this is to implement a hook_ui_patterns_source_info_alter and remove all the field plugins but I still need some of them. I brought the definition total from 4k to 600 but it's still slow.

At the very least I think that the interface needs to handle entity fields as a series of dropdowns and only load the definitions after some sort of context is set first.

If there is anything I can help with please let me know.

pdureau’s picture

StatusFileSize
new30.23 KB

Hello,

We have 3 big opportunities to improve performance of UI Patterns 2:

  • reducing the number of plugin derivatives (blocks, sources and derivable contexts): this will be one of the expected results of the current ambitious #ui_patterns-next plan
  • calculating the available source for each prop in the ComponentPluginManager itself, to heavily cache them in prop annotations, but this is part of a bigger strategy challenging the PropType plugins
  • the current issue, focused on component form

It's a performance solution, but, in my opinion, a bad thing for UX. The idea is still great, may be we can find something to solve UX.

So, we need to find a solution which is good both for performance and for UX. I am proposing to shamelessly copying the UX of ECA forms:

eca

So, to replace the current clunky UX with fieldsets and always visible sources selectors:

We can do something like that:

  1. At start, only the default source (so, most of a time, a "widget") in the form.
  2. Button triggering a modal with the (sometimes nested) sources selector & source form
  3. Once a source configured, the source settings summary is replacing the default widget.

Advantages:

  • Cleaner, Drupal-level accessible, interface, based on the work of 2 UX form Drupal Core & Drupal CMS
  • Performance improvements: On-demand lazy-loading sources retrieval :)
  • Just a guess: the ECA implementation may be easily reusable and already HTMX friendly

This UX proposal is for props only, there is already a ticket about slots UX: #3478643: UX of source selector for slots

pdureau’s picture

StatusFileSize
new13.06 KB
new18.03 KB
new16.12 KB
new6.68 MB
new30.23 KB
new13.06 KB
new18.03 KB
new16.12 KB

just_like_good_vibes made their first commit to this issue’s fork.

just_like_good_vibes’s picture

Hello All, we are really progressing on this issue, and the performance gains seems real. Someone wants to check? @asherry ?
many thanks in advance,

just_like_good_vibes’s picture

Assigned: Unassigned » pdureau
Status: Active » Needs review

a first working proposition to review :)

pdureau’s picture

Test with UI Patterns Field Formatters

UI: some widget are cropped

Example: checkbox
ss

UX: the name of the prop appears at the end of the prop form

We need to remove it.

UX: we need the source label before the settings summary

Not for the default widget.

UX proposal: move the button in the corner

Just a proposal:

.uip-prop-box summary + * {
  position: relative;
}
.uip-source-selector-toggle {
  top: 0;
  right: 0;
  position: absolute;
  margin: 0;
}

Settings summary

Maybe not necessary part of the scope of the current ticket, but we will need to add and improve the implementation of PluginSettingsInterface::settingsSummary().

For example, EntityLinksSource will need a label for the template and tell about absolute.

It is particularly important for the context switchers:

  • [Entity] ➜ Referenced [Entity] (entity_reference)
  • [Entity] ➜ [Field] (entity_field)
  • [Field item] ➜ Referenced [Entity]

Which can display both the ::settingsSummary() of the present source and the ::settingsSummary() of the selected source, recursively.

Test with Display Builder

In progress

Test with UI Patterns UI

To check.

pdureau’s picture

Assigned: pdureau » just_like_good_vibes
Status: Needs review » Needs work

Test with UI Patterns Field Formatters

UI: some

widget are cropped

✅ Checkbox is not cropped anymore in the main form
❌ but it is cropped in the modal now:
cropped
And sometimes there is an horizontal scrollbar. Are the modal dimensions constrained?

UX: the name of the prop appears at the end of the prop form

✅ Ok, removed.

UX: we need the source label before the settings summary

⚠️ it is added, but we need to add markup to organize the information here (no CSS needed):
aa

UX proposal: move the button in the corner

⚠️ done (in the bottom end, instead of top end, but that's OK)
But:

  • why .uip-prop-box summary + * .uip-source-selector-toggle--open instead of .uip-prop-box summary + * .uip-source-selector-toggle?
  • This selector don't work in Display Builder anyway, so we need .uip-prop-box .uip-source-selector-toggle instead.

Settings summary

Maybe not necessary part of the scope of the current ticket, but we will need to add and improve the implementation of PluginSettingsInterface::settingsSummary().

It is particularly important for the context switcher which can display both the ::settingsSummary() of the present source and the ::settingsSummary() of the selected source, recursively.

✅ Some changes have already be done, but we can do a follow-up for more.

Modal title

Instead of "Source of {{ prop }}" (Example: "Source of URL"), can we have just "{{ Prop }}"? Because:

  • We already know it is about source
  • The next information (the prop description) below is about the prop, not the source
  • We have the "Source" literal just after

Test with Layout Builder

TODO

Test with Display Builder

In progress

Test with UI Patterns UI

To check.

pdureau’s picture

just_like_good_vibes’s picture

Assigned: just_like_good_vibes » pdureau
Status: Needs work » Needs review

rebased, reworked, improved :)

Here is the whole picture of what is pushed, to ease the review.

Closed state:
- a prop loads only its saved source, nothing else. A source "widget" shows its form inline, for any other source, a summary is shown.
- the edit button (a pencil) sits in the box title. It is rendered server side, no JavaScript involved.
- summaries show the source label then its settings. Context switchers also show what they embed, as a nested list.

Open state:
- the pencil opens the prop form in a core dialog (Drupal.dialog). Drag, resize, Escape, theming: everything comes from core. Only 135 lines of JavaScript and 32 lines of CSS remain on our side.
- without JavaScript the same button opens the form inline, with a plain submit.
- the source select stays visible even with a single candidate, so a reopened chain shows all its levels.

Also:
- settingsSummary() added or completed for field formatter, path, views fields, menu, checkbox and textarea list, with a shared truncation "helper" method in SourcePluginBase.
- the label_map element is removed from field and views sources: the box title and the dialog title already name the prop.

to help the review :
- most of the diff is in ComponentFormBase (shared machinery) and ComponentPropForm (the two states open and close).
- wrapOrTitle() and addClosedSummaryAndButton() only exist to stay under the phpmd complexity threshold.
- slots are untouched. The follow-up issue about slots can reuse the base class machinery, and merging getSources() with getSourceDefinitions() could be one of its first step.

Tests: kernel tests for the two states, a Playwright test driving a full chain in the dialog, existing tests adapted.

just_like_good_vibes’s picture

pdureau’s picture

Test with UI Patterns Field Formatters

UI: some widget are cropped

✅ Checkbox is not cropped anymore in the main form
✅ Checkbox is not cropped anymore in the modal now
✅ No more horizontal bar

Maybe because we are nwo using the Core Modal API.

UX: we need the source label before the settings summary

✅ added

UX proposal: move the button in the corner

✅ moved in the details summary HTML element

⚠️ Too much spacing. Proposal

.uip-prop-box summary .uip-source-selector-toggle--open {
  margin: 0;
}

⚠️ You can use /core/misc/icons/787878/cog.svg instead, like Field UI does.

Settings summary

Implementation of PluginSettingsInterface::settingsSummary() has been improved but not reviewed yet.

It is particularly important for the context switcher which can display both the ::settingsSummary() of the present source and the ::settingsSummary() of the selected source, recursively.

Modal title

✅ Only the prop label

Test with Layout Builder

❌ the modal is not opening, the HTTP response look legit:

POST /layout_builder/update/block/defaults/node.article.default/0/actions/95012d30-2dba-4711-974d-ca69f65d8fe0?destination=/admin/structure/types/manage/article/display/default/layout&_wrapper_format=drupal_dialog.off_canvas&ajax_form=1&_wrapper_format=drupal_ajax

[{"command":"update_build_id","old":"form-tUuLq36VEzCdYjwQFyQvI6NhWiQa5F0422_OId6xbiE","new":"form-q0uc-FFmm5BcAl7aTK8U-V6JX8Jhw-6NTHs-S8KjtUM"},{"command":"insert","method":"html","selector":"#settings-formatter-settings-wrapper-settings-ui-patterns-variant-id-ui-patterns-prop-row-variant","data":"","settings":null}]

No JS error.

Test with Display Builder

❌ it opens a new page instead of a modal

Test with UI Patterns UI

To check.

pdureau’s picture

Assigned: pdureau » just_like_good_vibes
Status: Needs review » Needs work

(previous comment has been updated with the Layout Builder fail)

just_like_good_vibes’s picture

Ready for review, all comments addressed :)

pdureau’s picture

Look & feel

⚠️ Nearly perfect, we just need to add this in order to avoid some misalignment:

:is(.uip-prop-box, 
#drupal-off-canvas-wrapper .uip-prop-box) summary .uip-source-selector-toggle--open {
  height: auto;
}

Settings summary

Implementation of PluginSettingsInterface::settingsSummary() has been improved but not full reviewed. Let's merge like that and do some follow-ups if needed.

Test with UI Patterns Field Formatters

✅ OK, works well.

Test with Layout Builder

  • In layouts: ✅ OK, works well.
  • In blocks: ✅ OK, works well.
  • In field formatters (in blocks): ❌ I still have the same error

The modal is not opening, the HTTP response look legit:

POST /layout_builder/update/block/defaults/node.article.default/0/actions/95012d30-2dba-4711-974d-ca69f65d8fe0?destination=/admin/structure/types/manage/article/display/default/layout&_wrapper_format=drupal_dialog.off_canvas&ajax_form=1&_wrapper_format=drupal_ajax

[{"command":"update_build_id","old":"form-tUuLq36VEzCdYjwQFyQvI6NhWiQa5F0422_OId6xbiE","new":"form-q0uc-FFmm5BcAl7aTK8U-V6JX8Jhw-6NTHs-S8KjtUM"},{"command":"insert","method":"html","selector":"#settings-formatter-settings-wrapper-settings-ui-patterns-variant-id-ui-patterns-prop-row-variant","data":"","settings":null}]

No JS error.

Weird: the prop disappear on click.

Test with Display Builder

Tested with #3622023: Behaviors are not attached on htmx swaps outside the builder root (side panels).

It is not always working:

  • Page Layout: ✅ it is OK
  • Other buildables: ❌ it opens a new page instead of a modal
  • Other buildables, after clicking on a form element inside a widget (like select): ✅ it works

Test with UI Patterns UI

To check.

pdureau’s picture

Assigned: pdureau » just_like_good_vibes
Status: Needs review » Needs work
just_like_good_vibes’s picture

Assigned: just_like_good_vibes » pdureau
Status: Needs work » Needs review

ok, as we discussed, i have made some more changes :
- i added the code for the slots, originally planned for issue #3478643: UX of source selector for slots, but it is good to have it here .
- i updated the display builder fix in #3622023: Behaviors are not attached on htmx swaps outside the builder root (side panels) to ensure the new buttons get their ajax behavior at load
- i added more tests, in particular to check the appearance of the popup on the host plugins (field UI, views, ckeditor, LB...etc)

just_like_good_vibes’s picture

Assigned: pdureau » Unassigned
Status: Needs review » Fixed

this is a big one :)
a follow-up issue to be made by pdureau (incl how to nicely display settingsSummary)

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

Status: Fixed » Closed (fixed)

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