WordPress / gutenberg

The Block Editor project for WordPress and beyond. Plugin is available from the official repository.
https://wordpress.org/gutenberg/
Other
10.34k stars 4.13k forks source link

UI/UX for connecting block attributes to custom fields #53891

Closed michalczaplinski closed 1 week ago

michalczaplinski commented 1 year ago

Work has started to implement the vision outlined in Custom fields 🔗 Blocks. and is being tracked in https://github.com/WordPress/gutenberg/issues/53300.

However, we need a more holistic vision of the UI/UX for the connections between the blocks' attributes and the custom fields. This issue aims to explore the possible UI/UX for those connections.

Current State

2 PRs have been merged that allow connecting the Paragraph block's content attribute to custom fields:

Another (draft) PR is exploring connecting the Image block's url and title attributes to custom fields:

This is what connecting the attributes looks like at the moment for both Image and Paragraph blocks (includes the changes from the unmerged PR):

https://github.com/WordPress/gutenberg/assets/5417266/a3f6c43a-346e-433f-ad3f-5c41464e3339

This UX is not optimal and needs refinement.

Open Questions

Those are roughly in the order of importance:

How to edit the custom fields?

UI for connecting more than one attribute of a block to custom sources.

Currently, only the Image block has more than 1 connection, but this will change in the future. Having an input field per "connectable" attribute (as in the current MVP) is not tenable.

How to show the list of available fields? (ideally with autocomplete)

There is prior art for this:

UI for adding a new custom field inline

It should be possible to create new custom fields on the fly using the same UI where the attributes get connected to custom fields.

Interaction between existing block content and the connection value in the editor

If a block has existing content and then gets connected to a custom field, what should happen to this existing content? Ideally, we'd like to keep it in the background somehow, and if a user removes the connection, show that content again. Currently, we remove the existing content in the Paragraph block and show a placeholder. What should this process look like for other blocks and attributes?

Selecting a specific value from a custom field that is an array or object

Custom fields can be more than strings and numbers. We need some way to select/filter those.

If the connection has a default value, how should this be shown to the user?

We want the connections to define a "default" value that should be used in case the custom field we're connecting to does not exist. It should be indicated to the user that the "default" value is being used instead of the value from the connection.

UI for selecting a “connection source” (meta fields or something else)

This is not a priority because, for now, the only "connection source" is "custom fields", but there will be others in the future like "parent block" or another external source.

Validation

This one is probably optional for now, but ACF and similar plugins allow users to define validation rules for each field.

tresorama commented 1 year ago

This is a POC i made for myself some days ago of I would like this feature to be implemented... My vision about dynamic data is that they can be presented in any point of the conent (for fields of type text, number, or any other that can be casted to text).

POC - The UX

https://github.com/WordPress/gutenberg/assets/47954700/c56faccf-7625-483a-bd99-c76d9b695599

michalczaplinski commented 1 year ago

CC @WordPress/gutenberg-design

michalczaplinski commented 1 year ago

Nice @tresorama! Are you using https://github.com/WordPress/gutenberg/pull/42015 in your POC? It seems more related to the discussion around inline tokens (https://github.com/WordPress/gutenberg/discussions/39831) than the current issue.

How would you imagine your proposal working beyond plain text content, e.g., with Images/media?

tresorama commented 1 year ago

Thanks. I'm not using #42015 because i didn't know it exists :) I used a mini parser with the same idea to replace tokens with real value coming from the redux store. The dropdown in the toolbar is used only to copy and paste the token in the "attributes.content" string. Here i've shown the "edit" side only, but the an identical parser is needed in PHP side that will "preg_replace" the block content when rendered on frontend.

I haven't moved on over "textual" data because of time, but i think that for example "core/image" block can have an additional source in the initial modal (and also in "replace" popover)

Schermata 2023-08-25 alle 09 47 42

Or maybe move every source inside the same dropdown (link in Bricks, shown below) ??


Bricks UX with Dynamic Data

My vision is heavily influenced by Bricks Builder, so i'd like to see in Core Gutenberg a UX flow similar to Bricks.

Bricks can be tested freely in a playground going to https://try.bricksbuilder.io/ if anyone want to test it. You need to sign up an account (free) and then a Wordpress instance is spawn up for you, with ACF, Woocommerce, and other common plugin already installed (but deactivated).

Here is a recording of using Bricks with Dynamic Data

https://github.com/WordPress/gutenberg/assets/47954700/05a65779-f701-4d2f-8919-290248fe118d

Considerations:

Bricks show every possible Dynamic Data source in every dynamic data dropdown, even if :

For the first, Bricks check If type is wrong after user selection, and in case the type is wrong it fails silently (as in the video below). It is good to remember that Bricks is targeted to Developer only, which will know why it happens. Gutenberg IMO is targeted in between Common User and Developer, so maybe a UI for when type is wrong is a good addition, but not essential in early phase of the feature.

Here is an example of a type mismatch in Bricks

https://github.com/WordPress/gutenberg/assets/47954700/3de20d61-d8d3-490d-9167-0974f7045723

For the second, ACF doesn't store fields as post_meta ( but they have planned to migrating to post_meta in near future ) and this can cause some "overexposing" field like in Bricks. In my POC I get field used to populate the toolbar dropdown with this code

const useDynamicDataSources = (props: BlockEditProps<any>) => {
  const { attributes, context } = props;

  // extract dynamic data fields "names" and return as list

  // fetch data
  const post = useEntityRecord<Post>('postType', context.postType, context.postId);
  const acfFields = post.record.acf || {};

  // build list
  return [
    { section_name: 'Post', fields: ['post_title'].map(_ => "{" + _ + "}") },
    { section_name: 'ACF', fields: Object.keys(acfFields).map(_ => "{acf:" + _ + "}") },
  ] satisfies { section_name: string, fields: Array<string>; }[];

};

In case here is the full code of my POC


tresorama commented 1 year ago

Builder that solved the same problem that can be used as inspiration in this design phase are:

@michalczaplinski maybe you could add these in the main issue to have them togheter

bvlgn commented 1 year ago

The user should edit the custom fields (or other data sources) either inside the block content (or related popup) or in a block inspector panel. Not in an external editor!   I don’t think the user needs to know that they technically are adding content to a custom filed or other data source. But they should know what they are expected to enter. So when connecting attributes to a data source it is important we can add a placeholder and a label which would show when the input field in the block editor gets focus. This label could be shown in the toolbar for the block. 



Instead of trying to connect attributes to data sources from within the block’s UI we should offer an ‘Attributes’ panel. In this panel we make connections, add placeholders, labels, add input instructions, set defaults, set the attribute to be read only or read-write and allow creation of new data source fields.  Here we could also define options the user may select from and set any other configuration needs. This panel should by default only be available to administrators, I think.

When switching an attributes data source the current value should preferably be moved to the new data source. If the new data source already has a value then the user should choose which value to keep.   If the connection has a default value it should be filled in by default. The user can then overwrite it or leave it as is. If there is no default value a placeholder should be shown.   When it comes to validation and filtering maybe an API could be added and let the implementation to extenders? That said, a robust and complete API should be considered from the get go.



So values are mainly edited in the editor or a block inspector panel while attribute connections are configured in the Attributes block inspector panel.

gziolo commented 4 months ago

@michalczaplinski and @SantosGuillamot, is this issue still actionable? There are other issues opened that seem to cover similar topics.

michalczaplinski commented 4 months ago

@gziolo There isn't anything directly actionable, but we can keep this issue open for now and once work on the UI/UX picks up we can link from here and/or close this issue.

Quick summary:

Connecting block attributes to custom fields is one of the main aspects of the Block Bindings project. It was shipped in WP 6.5 (https://github.com/WordPress/gutenberg/issues/53300). Current work is tracked in:

gziolo commented 1 week ago

Implemented with:

More in What’s new in Gutenberg 19.0? (14 August):

https://github.com/user-attachments/assets/3169a3da-0c4d-4440-a5b9-26d0fe3e2697