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

API Reference Docs for Interactivity API #52948

Merged
merged 27 commits into from
Aug 2, 2023

Conversation

juanmaguitar
Copy link
Contributor

What?

API Reference Docs for Interactivity API

Why?

Solves #52922

@github-actions
Copy link

github-actions bot commented Jul 25, 2023

Flaky tests detected in 5bf1979.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/5726713376
📝 Reported issues:

@juanmaguitar juanmaguitar added the [Type] Developer Documentation Documentation for developers label Jul 30, 2023
@juanmaguitar juanmaguitar marked this pull request as ready for review July 30, 2023 20:09
Copy link
Member

@luisherranz luisherranz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey Juanma, amazing job. I think it's a great first version 🙂

Some comments below:


I'd sort the directives in a way that makes more sense from a learning journey perspective. For example:

  • data-wp-context
  • data-wp-bind
  • data-wp-class
  • data-wp-style
  • data-wp-text
  • data-wp-on
  • data-wp-effect
  • data-wp-init
  • data-wp-body

The other ones are still upcoming, so I don't know if we should document them yet or not. Probably not. Although maybe we could say that they are coming:

  • data-wp-show
  • data-wp-each
  • data-wp-dangerous-html
  • data-wp-slot/fill
  • data-wp-error

It's true that wp-show is still on the codebase but I want to remove it today. We haven't figured it out yet, so I prefer that people use data-wp-bind--hidden or data-wp-style--display to conditionally hide/show elements for now.

There are other ones that are a bit special and we should also document, but we can leave that for later:

  • data-wp-interactive
  • data-wp-ignore
  • data-wp-key

Maybe we could mention what is the directive value. I.e., for the majority of them, it would be something like:

It accepts a reference that points to a specific callback of the store. That callback is then executed when ___ happens and the value that it returns is used to ___.

  • data-wp-bind--attribute:
    • Executed when the element is created, and then each time that any of the properties of the state or context used inside the callback changes.
      • The callback receives the attribute name: attribute.
    • The returned value is used to change the value of the associated attribute.
      • If the value is true, the attribute is added: <div attribute>.
      • If the value is false, the attribute is removed: <div>.
      • If the value is a string, the attribute is added with its value assigned: <div attribute="value".
      • If the attribute name starts with aria- or data- and the value is boolean (either true or false), the attribute is added to the DOM with the boolean value assigned as a string: <div aria-attribute="true">.
  • data-wp-class--classname:
    • Executed when the element is created, and then each time that any of the properties of the state or context used inside the callback changes.
      • The callback receives the class name: className.
    • The returned value is used as a boolean to toggle (add or remove) the associated class name from the class attribute.
  • data-wp-style--cssproperty:
    • Executed when the element is created, and then each time that any of the properties of the state or context used inside the callback changes.
      • The callback receives the style property: styleProperty.
    • The returned value is used to change the value of the associated CSS property: <div style="cssproperty: value;.
  • data-wp-text:
    • Executed when the element is created, and then each time that any of the properties of the state or context used inside the callback changes.
    • The returned value is used to change the inner content of the element: <div>value</div>.
  • data-wp-on--event:
    • Executed each time the associated event is triggered.
      • The callback receives the event: event
    • The returned value is ignored.
  • data-wp-effect:
    • Executed when the element is created, and then each time that any of the properties of the state or context used inside the callback changes.
    • It can return a function. If it does, the returned function is used as cleanup logic, i.e., it will run just before the callback runs again, and it will run again when the element is removed from the DOM.
  • data-wp-init:
    • Executed when the element is created.
    • It can return a function. If it does, the returned function will run when the element is removed from the DOM.

wp-context accepts a stringified JSON, and wp-portal doesn't accept anything.

packages/interactivity/docs/2-api-reference.md Outdated Show resolved Hide resolved
packages/interactivity/docs/2-api-reference.md Outdated Show resolved Hide resolved
packages/interactivity/docs/2-api-reference.md Outdated Show resolved Hide resolved
packages/interactivity/docs/2-api-reference.md Outdated Show resolved Hide resolved
packages/interactivity/docs/2-api-reference.md Outdated Show resolved Hide resolved
packages/interactivity/docs/2-api-reference.md Outdated Show resolved Hide resolved
packages/interactivity/docs/2-api-reference.md Outdated Show resolved Hide resolved
packages/interactivity/docs/2-api-reference.md Outdated Show resolved Hide resolved
// render.php
wp_store( array(
'state' => array(
'myPlugin' => array(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should keep using myNamespace here for consistency?

Suggested change
'myPlugin' => array(
'myNamespace' => array(

@luisherranz luisherranz added the [Feature] Interactivity API API to add frontend interactivity to blocks. label Jul 31, 2023
@juanmaguitar
Copy link
Contributor Author

juanmaguitar commented Jul 31, 2023

The other ones are still upcoming, so I don't know if we should document them yet or not. Probably not. Although maybe we could say that they are coming:

data-wp-show
data-wp-each
data-wp-dangerous-html
data-wp-slot/fill
data-wp-error

There are other ones that are a bit special and we should also document, but we can leave that for later:

data-wp-interactive
data-wp-ignore
data-wp-key

@luisherranz It would be great to have an issue for each directive or a Tracking Issue we could link in the docs to help explain these directives are in progress

@juanmaguitar
Copy link
Contributor Author

@luisherranz Thanks a lot for the feedback 🙏
I have addressed all your comments and used most of your suggestions.
Please, feel free to add any other comments you may have.

Copy link
Member

@luisherranz luisherranz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice, Juanma! This is shaping quite nicely. I like the examples. They are simple and easy to follow but still enough to learn the concepts 🙂👏

I've added a few extra suggestions and corrections below but I'm preemptively approving it so you can merge it whenever you think it's ready.

The `wp-interactive` "activates" hydration for the DOM element and its children through the Interactivity API (directives and store).

> **Note**
> The use of `wp-interactive` is a requirement for the Interactivity API "engine" to work. In the following examples the `wp-interactive` has not been added for the sake of simplicity
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
> The use of `wp-interactive` is a requirement for the Interactivity API "engine" to work. In the following examples the `wp-interactive` has not been added for the sake of simplicity
> The use of `wp-interactive` is a requirement for the Interactivity API "engine" to work. In the following examples the `data-wp-interactive` directive has not been added for the sake of simplicity.

Comment on lines 50 to 51
The `wp-interactive` "activates" hydration for the DOM element and its children through the Interactivity API (directives and store).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can add an example?

Also, maybe we should stick to "interactive" and "interactivity" and avoid the use of hydration, which is a more technical term?

Suggested change
The `wp-interactive` "activates" hydration for the DOM element and its children through the Interactivity API (directives and store).
The `wp-interactive` directive "activates" the interactivity for the DOM element and its children through the Interactivity API (directives and store).
\```html
<!-- Let's make this element and its children interactive -->
<div data-wp-interactive>
I'm interactive now, and I can use directives!
<span>
I'm also interactive, and I can also use directives!
</span>
</div>
\```


#### `wp-effect`

It runs a callback **when the node is created and runs it again when the state or context changes**. You can attach several effects to the same DOM element by using the syntax`data-wp-effect--[unique-id]`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
It runs a callback **when the node is created and runs it again when the state or context changes**. You can attach several effects to the same DOM element by using the syntax`data-wp-effect--[unique-id]`.
It runs a callback **when the node is created and runs it again when the state or context changes**. You can attach several effects to the same DOM element by using the syntax `data-wp-effect--[unique-id]`. _The unique id doesn't need to be unique globally, it just needs to be different than the other unique ids of the `wp-effect` directives of that DOM element._


It runs a callback **when the node is created and runs it again when the state or context changes**. You can attach several effects to the same DOM element by using the syntax`data-wp-effect--[unique-id]`.

_Example of `wp-on` directive_
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
_Example of `wp-on` directive_
_Example of `wp-effect` directive_

Comment on lines +387 to +390
As a reference, some use cases for this directive may be:
- logging.
- changing the title of the page.
- setting the focus on an element with `.focus()`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
As a reference, some use cases for this directive may be:
- logging.
- changing the title of the page.
- setting the focus on an element with `.focus()`.
As a reference, some use cases for this directive may be:
- logging.
- changing the title of the page.
- setting the focus on an element with `.focus()`.
- changing the state or context when certain conditions are met.


The store is used to create the logic (actions, effects…) linked to the directives and the data used inside that logic (state, selectors…).

**The store is usually created in the `view.js` file of each block**, although it can be initialized from the `render.php` of the block (see [diagram](https://excalidraw.com/#json=FPTvzmKpyunGuFzWt5nzX,gs2vvsN0HEvnEHsQ9u1gPg)).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not entirely sure that this diagram adds any value here. It seems difficult to understand without more context.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right! I'll remove it from now and may use it in another more advanced explanation somewhere else

Comment on lines 474 to 475
- **Global state**: It is defined using the `store()` function, and the data is available to all the HTML nodes of the page.
- **Context/Local State**: It is defined using the `data-wp-context` directive in an HTML node, and the data is available to that HTML node and its children.
Copy link
Member

@luisherranz luisherranz Aug 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can add examples.

Suggested change
- **Global state**: It is defined using the `store()` function, and the data is available to all the HTML nodes of the page.
- **Context/Local State**: It is defined using the `data-wp-context` directive in an HTML node, and the data is available to that HTML node and its children.
- **Global state**: It is defined using the `store()` function, and the data is available to all the HTML nodes of the page. It can be accessed using the `state` property.
- **Context/Local State**: It is defined using the `data-wp-context` directive in an HTML node, and the data is available to that HTML node and its children. It can be accessed using the `context` property.
\```html
<!-- Access global state -->
<span data-wp-text="state.someText"></span>
<!-- Access local state (context) -->
<span data-wp-text="context.someText"></span>
\```
\```js
store( {
actions: {
someAction: ({ state, context }) => {
state.someText // Access or modify global state
context.someText // Access or modify local state (context)
},
},
} )
\```


#### Selectors

Also known as _derived state_, returns a computed version of the state.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Also known as _derived state_, returns a computed version of the state.
Also known as _derived state_, returns a computed version of the state. They can access both `state` and `context`.

} );
```

### Objects passed to callbacks
Copy link
Member

@luisherranz luisherranz Aug 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
### Objects passed to callbacks
### Argument passed to callbacks


When a directive is evaluated, the reference callback receives an object with:

- The **`store`** containing the `state`, `actions` and `effects`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- The **`store`** containing the `state`, `actions` and `effects`.
- The **`store`** containing all the store properties, like `state`, `selectors`, `actions` or `effects`.

@juanmaguitar juanmaguitar merged commit 5898968 into trunk Aug 2, 2023
50 checks passed
@juanmaguitar juanmaguitar deleted the docs/interactivity-api-reference branch August 2, 2023 11:35
@github-actions github-actions bot added this to the Gutenberg 16.4 milestone Aug 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Interactivity API API to add frontend interactivity to blocks. [Type] Developer Documentation Documentation for developers
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants