Frontity Slot Block

Description

It would be cool to have a way to inject Frontity Slots in the content created with Gutenberg, both for post content or template parts.

Requirements

  • Add slots in any part of the Gutenberg content.
  • Configure the name of each Slot.
  • Convert the Gutenberg block in a Frontity <Slot>.

Extra Functionalities

  • Add props that can be passed to the Slot.
  • Add default content if Fills not present using inner blocks.

Possible solution

@david and I had a pair programming session scheduled together and we took the opportunity to create the first version of the block and the Html2React processor:

I have created a shorter video explaining how it works:

This is the repository of the Gutenberg block is here GitHub - frontity/frontity-slot-block: A block to insert Frontity Slots directly in the block editor.. I still have to work on the readme.

The branch with the new processor is here https://github.com/frontity/frontity/compare/gutenberg-slot. I still have to make the PR.

Hi @luisherranz!
Not sure if I’m allowed to write anything here, so if I’m not, just delete it.

But, what is the pros of inserting react components into wp content via slots instead of just a processor? :slight_smile:

Hey, anyone can write anywhere here in the forums and participation is always encouraged :slightly_smiling_face:

It is a more explicit way to do it.

Imagine a team of content editors that need to inject custom ads, a newsletter form, and a feedback form into the content.

The developers of that project can instruct the content editors to use the Frontity Slot block with the following names, wherever the content editors need those parts inserted:

  • Frontity Slot: “Custom Ad 1”
  • Frontity Slot: “Custom Ad 2”
  • Frontity Slot: “Newsletter”
  • Frontity Slot: “Feedback form”

The developers just have to create a fill for each of those.

Of course they could agree on a different HTML structure and create a processor that captures that. For example, they could use a paragraph block with these texts:

  • Paragraph: “##Custom Ad 1##”
  • Paragraph: “##Custom Ad 2##”
  • Paragraph: “##Newsletter##”
  • Paragraph: “##Feedback form##”

But using Frontity Slots is more explicit, clean, and should be easier to maintain.

1 Like

We have merged the PR that adds the Slot Block processor: Processor for the Frontity Slot Block plugin by luisherranz · Pull Request #815 · frontity/frontity · GitHub

I have also created a readme for the Slot Block package: GitHub - frontity/frontity-slot-block: A block to insert Frontity Slots directly in the block editor.. I have renamed it to “Frontity Slot Block”.

Final Implementation

Pull Request and Repository

Requirements

  • Add slots in any part of the Gutenberg content.
  • Configure the name of each Slot.
  • Convert the Gutenberg block in a Frontity .

Functionalities

  • Use a Gutenberg block to add a <div> that can be identified later by a processor and contains the Slot name.
  • Use a processor to transform the <div> generated by the Gutenberg block in a Frontity <Slot> component that uses the name specified in the block.

Out of Scope

  • Add a way to pass props to the Slot.
  • Add a way to define default content if Fills not present using inner blocks. Maybe using Gutenberg Inner Blocks.

API changes

Backward compatible changes

A new processor was added to the @frontity/html2react package. It is located in the /processors/slot-block file and it can be used like this:

import slotBlock from "@frontity/html2react/processors/slot-block";

export default {
  state: {
    // ...
  },
  actions: {
    // ...
  },
  libraries: {
    html2react: {
      processors: [slotBlock],
    },
  },
};

Breaking changes

None.

Deprecated APIs

None.

Technical explanation

We created a very simple WordPress plugin that registers a new Gutenberg block. That block adds a <div> which has the class wp-block-frontity-frontity-slot and a data attribute called data-frontity-slot-name that contains the name of the slot:

<div class="wp-block-frontity-frontity-slot" data-frontity-slot-name="Some Slot Name"></div>

The content editors can add as many slots as they want:

Then, the Slot Block processor turns them into <Slot> components:

<Slot name="Some Slot Name" />

Finally, the Frontity user can add fills for those slots using the normal Slot/Fill behavior:

export default {
  state: {
    fills: {
      myPackage: {
        SomeFill: {
          slot: "Some Slot Name",
          library: "myPackage.SomeFill",
          props: {
            // some props...
          }
        }
      }
    }
  }
}

Demo

I made a video explaining how it works, although I renamed the block later to slot-block instead of gutenberg-block:

1 Like

Hi @luisherranz,

Do you think it would be possible for slots to work the other way around as well? Kind of like custom layouts in astra. So you make a slot in the theme, and then you can make a fill in the gutenberg editor, and hook into the slot from WP. That way customers or employees who do not want to touch the frontity code, can still insert content if they want.

Yes, I think it would be possible, and it sounds great!

I think it would be cool to be able to use a template part to define it (like Astra’s custom layout hooks) but also to add it in the post content. What do you think?

I’ve opened an issue to add documentation for this: Document the new "Frontity Slot Block" plugin and "slot-block" processor · Issue #42 · frontity/api-reference · GitHub

It sounds like a good solution. When it comes to template parts, is a plugin the best way to go about it, or a custom theme?

I think creating a template part is fine, as it doesn’t require either a plugin or a theme.

(post withdrawn by author, will be automatically deleted in 24 hours unless flagged)

Oh, I haven’t seen the new template parts page yet. Noticed it now. Is that new in 5.7?

I’m not sure, to be honest. I use to install the Gutenberg plugin :grinning_face_with_smiling_eyes:

is there a way this could be implemented on a per page/component level rather than through settings?

this would allow me to place slots in Wordpress that a specific page component can override, but that fill content might be dynamic pased on the post

eg (condensed pseudo-code)

const SomePage = () => {
  
  const data = state.source.get(state.router.link);
  const post = state.source[data.type][data.id];
  const Html2React = libraries.html2react.Component;

  return (
  <Container>

    {/* this outputs content containing gutenberg slots */}
    <Html2React html={post.content.rendered} /> 

    {/* these fill the slots in the post content above */}
    <Fill name="after paragraph 1">    
      <p>Some content after Paragraph 1 in the content { post.title.rendered }</p>
    </Fill>
  
    <Fill name="after paragraph 2">
      <p>Some content after Paragraph 2 in the content { post.author }</p>
    </Fill>

  </Container>
  )

}

thanks
J

So you want to add fills conditionally depending on the entity type?

Hi @luisherranz

actually no I wasn’t going that far here, I was literally just wanting to fill a named slot as per my pseudocode

so in the WP Gutenberg would be a Slot named “after paragraph 1” and then in my js template (which might be generic like post.js, or specific like home.js) I would just define fill content for those named slots.

So in my WP Gutenberg editor would be

some paragraph gutenberg block
(frontity slot name=“after paragraph 1”)
some more gutenberg content
(frontity slot name=“after paragraph 2”)

rendering my content out in my example would give me

some paragraph gutenberg block
some content after Paragraph 1 in the content Post Title
some more gutenberg content
some content after Paragraph 2 in the content 10

this gives me component level control over slot fills rather than at settings level

thanks
Joe

I see, thanks Joe.

Another question: what is the problem in this case with adding those Fill components to libraries.fills and using state.fills to configure them? Is it because you have different post templates that contain different fills?

Hi @luisherranz it’s theoretical currently but yes I was suggesting being able to have component-based definitions of the fills

My main use case is essentially eg I want to be able
to add placeholder slots in my Home page content field , and then fill it using data from other ACF fields on the homepage.

I understand that can likely be done through the libraries but felt like cluttering up the theme config for something that is just used in my home.js etc
(Once you start expanding it out across different page components with different fills) etc

Thanks
J

Ok, thanks for the feedback @codemonkeynorth :slightly_smiling_face:

1 Like