Problem/Motivation

#3622928: UX of the asynchronous component form was a big improvement:

  • we now have an inline modal instead of a popup dialog
  • no JS, no CSS (or only a little)
  • accessible

aa

However, we lost the little "settings" icon in the details summary, which had 3 advantages:

  • it tells users which props have more available sources according to context
  • it is smaller (less vertical space taken) and cleaner looking
  • if it disappears when in inline modal, it gives a clear indication of what is going on

Proposed resolution

Can we have an icon button inside the summary and hiding it while we are configuring the sources like that:
aa

Without too much JS/CSS and staying accessible ?

Using https://git.drupalcode.org/project/drupal/-/blob/main/core/misc/icons/78... ?

It is less important if it is an icon, but instead of "Configure", can we have "More"?

CommentFileSizeAuthor
ux-niw.png10.75 KBpdureau
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.

mogtofu33’s picture

Putting the icon inside the summary ties the button to the details element, and #3622982: Remove details element in component form? is still discussing whether to keep it. If props end up flat, or boxed but not collapsible, there is no summary left for the icon, so we would need two placements to maintain. I am pretty sure there is an impact.

A button inside a <summary> also toggles the details when clicked, so we would need JS to stop that. That goes against the goal of keeping JS minimal. It is also a control nested inside the disclosure button, which is a known risk for screen readers.

The benefits listed do not need the summary. The button can hide while its selector is open wherever it sits.

On the look, an icon alone is not enough. NN/g says "A text label must be present alongside an icon" and advises not to rely on hover, so a title tooltip does not solve it. The cog is also not a universally understood icon: Icon Usability.

On wording, I am not sure "Configure" or "More" tell users what the button does. "More" is generic, and the whole form already configures the component. Why not an explicit "Change source"? The accessible name could then be "Change source: Variant", which keeps the visible words first.

pdureau’s picture

Putting the icon inside the summary ties the button to the details element, and #3622982: Remove details element in component form? is still discussing whether to keep it. If props end up flat, or boxed but not collapsible, there is no summary left for the icon, so we would need two placements to maintain. I am pretty sure there is an impact.

Indeed, we don't need a summary for such a change, #3622982: Remove details element in component form? has this mockup for example:
aa

On wording, I am not sure "Configure" or "More" tell users what the button does. "More" is generic, and the whole form already configures the component. Why not an explicit "Change source"? The accessible name could then be "Change source: Variant", which keeps the visible words first.

There are 2 different cases:

  • When the default widget source is displayed, this is not a button to configure the widget but to open the source selector, so "More" will make sense.
  • When the settings summary of a more complex source is displayed, , "Configure" makes more sense, because we are opening the form of the same source

So either we find a word that works in both cases, or we use dynamic wording according to what is displayed.

pdureau’s picture

To also discuss: why the source selector is not mandatory? it was always like that? does it makes sense?

just_like_good_vibes’s picture

no source = default ?

pdureau’s picture

no source = default ?

The default source is already the first one of the select list, isn't it? So, if we allow the "no source", we will have twice the default source in the list, one after the other.

just_like_good_vibes’s picture

Assigned: Unassigned » just_like_good_vibes
Status: Active » Needs review

Hello,
i will review that one :), i am starting now

just_like_good_vibes’s picture

hello there, here is an updated proposition, summary and explanations bellow :

From the issue #3623704: Component form: configure button position & look
- Cog button inside the box title: dropped, because a control inside the title breaks screen readers, toggles the box, and needs CSS or icons.
- Show which props have other sources: already done, since the open button only appears when there's more than one source to pick from.
- Take less vertical space: not done, because moving the button needs CSS that each theme would render differently.
- Visual feedback when moving to configuration: unchanged, because the box already opens and takes the focus #3622928: UX of the asynchronous component form.
- Rename "Configure" (to "More" or similar): done differently, with labels that say the action: Choose source, Change source, Edit.

- Kept accessibility: the labels say the action and name the prop to screen readers, and the marker is plain text.
- Comment #2, no button inside the title: agreed, for the same accessibility reason.
- Comment #2, explicit wording like "Change source": adopted as is.
- Comment #3, different labels for picking a source and configuring a complex one: ok, with "Change source" and "Edit".
- Comments #4–6, "no source" option duplicates the default: left out, since it's a separate topic.

About MR !571
- Value in the closed box title: dropped, because when it showed was unpredictable: schema defaults showed as set, the value vanished when the selector opened, went stale after typing, and checkboxes behaved differently.
- FormattableMarkup with a uip-prop-box__value span: dropped, no CSS uses the class and the ": " couldn't be translated.
- The getValueLabel() and getTitleValue() helpers: dropped, because nothing needs them without the value in the title.
- The labels Choose source, Change source, Edit: kept, because they say what the button does and the visible word starts its accessible name.
- The labels were shown only on props: we need to support slots and with a shared method.
- Optional $label argument on buildSelectorToggleButton(): kept, since it's the smallest way to pass the action label.
- Default open label changed from "Configure" to "Edit": kept, because it's the right word when a summary hides the value.
- testOpenButtonNamesItsAction: kept, with one assertion trimmed.

My proposal
- New: "(applied)" marker copied from ui_styles ((applied)), visible in every theme with zero CSS and sharing ui_styles' translation.
- New: one rule in isApplied(): the stored source counts; a widget also needs a non-empty value; schema defaults and empty or unchecked widgets don't count.
- New: same rule for props and slot rows, open or closed, so users can learn it.
- New: slot box marked when any of its rows is, like the ui_styles groups; the props group isn't marked because it's a heading, not a box.
- New: source name in brackets on a prop title when the source isn't a typed field, as your indicator that its form is hidden behind a summary.
- New: isWidget() helper reading the source's own tags, which replaces two copies of the widget check.
- New: markApplied() helper, so the marker markup lives in one place.
- New: showCheckboxLabel() helper, which removes a duplicated checkbox fix and keeps buildClosedState() under the phpmd complexity limit.
- Updated: addClosedSummaryAndButton() moved to the base class, shared by props and slot rows, which deletes the slot form's duplicate.
- Updated: checkDetailsElement() adds the marker to the slot box title.
- Dropped: "Title: value (Source)" version, for the same unpredictability as the MR's value in the title.
- Dropped: live update while typing, because it needs JS; the marker updates on each row rebuild, as ui_styles does.
- New tests: testBoxTitleMarksApplied and testAppliedRowMarksItsBoxes, both failing without the change.
- Accepted limit: a picked but unfinished non-widget source shows "(applied)", because a stricter rule would never mark a configured block.
- Accepted limit: the source name in brackets updates only after Save when you switch source in an open selector.

pdureau’s picture

Review of the 2 MR (only the prop part for now):

Task MR 571 MR 575
Tell if more sources are available without opening the inline modal ⚠️ No. Does that mean we don't want that finally? ⚠️ No. Does that mean we don't want that finally?
Tell if value has been set without opening the inline modal ✅ Summary of the last configured source after a colon. ❌ 2 indicators:
  • Summary of the first configured source in between parenthesis.
  • "Applied" mark element like UI Styles

We need to pick one.

Live update of those 2 indicators ❌ Only when editing from inline modal ❌ Only when editing from inline modal
Dynamic wording of the button to open the inline modal ✅ "Change source" / "Edit" ✅ "Change source" / "Edit"
Position and look of the button to open the inline modal Still a regular button on the bottom left Still a regular button on the bottom left
Inline modal buttons wording ✅ "Save" / "Cancel" ✅ "Save" / "Cancel"
Required source selector ❌ No, but it must be. ❌ No, but it must be.
pdureau’s picture

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

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

i updated the proposition, and proposed a simple "(set)" marker when a value is set. lighter than the ui styles challenged version and the cropped summary.

the MR is 574.

@pdureau, in your previous comment, you may add an axe of comparison about "address slots?" , "address props?"

mogtofu33’s picture

Thanks for the review and the counter-proposal. I checked the four objections to MR !571 with a kernel probe on both branches, and three of them are real:

  • Schema defaults did show as set. An untouched boolean prop with default: true printed a value, because the check read the widget's settings summary instead of what the configuration stores.
  • The value did vanish when the selector opened.
  • Checkboxes did behave differently: a checked one printed Boolean, the widget title, not a value.
  • "Stale after typing" is true, but equally true of the marker: neither updates without JS, and your table marks live update as missing on both sides.

I also found two of my own: the separator was not translatable, and nothing truncated a long value.

So the gate in MR !574, isValueSet(), is right, and the display in MR !571 is the more useful one. MR !571 now merges them instead of picking a side:

  • The value shows only when the stored source_id matches the source on screen, which is your rule.
  • It is truncated to 40 characters, which answers the "cropped summary" worry.
  • It is composed with t('@title: @value'), so it translates.
  • A stored source with nothing to show falls back to (set), your "picked but unfinished" case.
  • An open row keeps the value, since it comes from stored configuration.

That answers "we need to pick one": a printed value already means set, so the mark is the fallback, not a second indicator.

I also took the slot part from MR !574, with credit: addClosedSummaryAndButton(), isWidget() and the value helper now live in ComponentFormBase, so the slot form loses its duplicate and slot rows get the same button labels. A slot row names its own value, like a prop: Component: UI Patterns Test component. A slot holds rows rather than one value, so its own box only marks: slot_free (set).

Two follow-ups, both out of scope here: CheckboxWidget::settingsSummary() returning the widget title rather than the value, and the required source selector from #3623704-5: Component form: configure button position & look.

mogtofu33’s picture

A quick word on why this one is still worth reviewing next to #3622982: Remove details element in component form?.

That issue decides whether a prop sits in a box. This one decides what the box says once it is closed. Without it, a closed box shows only the prop name, so the only way to know whether something is set is to open it, one prop at a time.

The rule here is narrow on purpose: only what the configuration stores counts, so a schema default or an empty widget stays unmarked. What shows is the source's own summary line, truncated, or (set) when there is nothing to show yet.

It helps either way. With boxes everywhere, it is what tells them apart. With flat rows, the boxes left are the complex sources, the ones whose value is otherwise hidden.