Skip to content

Conversation

@ahuseyn
Copy link
Member

@ahuseyn ahuseyn commented Feb 17, 2025

Tasks

  • I have signed a Contributor License Agreement (CLA) with WP Engine.
  • If a code change, I have written testing instructions that the whole team & outside contributors can understand.
  • I have written and included a comprehensive changeset to properly document the changes I've made.

Description

CoreList was rendering values attribute, which happens to return nested list items multiple times. New CoreListItem block fixes this issue by recursively rendering nested lists.

Related Issue(s):

Testing

  1. Setup a basic headless project with to be able to render blocks (https://toolkit.faustjs.org/docs/how-to/rendering-blocks/)
  2. Add the single component to wp-templates folder with the component below. This component has CoreListItem fragments (${blocks.CoreListItem.fragments.entry}) to support CoreListItem
import { gql } from "@apollo/client";
import { WordPressBlocksViewer } from "@faustwp/blocks";
import { flatListToHierarchical } from "@faustwp/core";
import blocks from "../wp-blocks";

export default function PostTemplate({ data }) {
  const { title, editorBlocks } = data?.post ?? { title: "" };
  const blockList = flatListToHierarchical(editorBlocks, {
    childrenKey: "innerBlocks",
  });

  return (
    <div className='is-layout-constrained'>
      <h1>{title}</h1>

      <WordPressBlocksViewer blocks={blockList} />
    </div>
  );
}

PostTemplate.query = gql`
  ${blocks.CoreParagraph.fragments.entry}
  ${blocks.CoreColumns.fragments.entry}
  ${blocks.CoreColumn.fragments.entry}
  ${blocks.CoreCode.fragments.entry}
  ${blocks.CoreButtons.fragments.entry}
  ${blocks.CoreButton.fragments.entry}
  ${blocks.CoreQuote.fragments.entry}
  ${blocks.CoreImage.fragments.entry}
  ${blocks.CoreSeparator.fragments.entry}
  ${blocks.CoreList.fragments.entry}
  ${blocks.CoreListItem.fragments.entry}
  ${blocks.CoreHeading.fragments.entry}
  query GetPost(
    $uri: ID!

  ) {
    post(id: $uri, idType: URI) {
      title
      content
      editorBlocks {
        name
        __typename
        renderedHtml
        id: clientId
        parentId: parentClientId
        ...${blocks.CoreParagraph.fragments.key}
        ...${blocks.CoreColumns.fragments.key}
        ...${blocks.CoreColumn.fragments.key}
        ...${blocks.CoreCode.fragments.key}
        ...${blocks.CoreButtons.fragments.key}
        ...${blocks.CoreButton.fragments.key}
        ...${blocks.CoreQuote.fragments.key}
        ...${blocks.CoreImage.fragments.key}
        ...${blocks.CoreSeparator.fragments.key}
        ...${blocks.CoreList.fragments.key}
        ...${blocks.CoreListItem.fragments.key}
        ...${blocks.CoreHeading.fragments.key}
      }
    }
  }
`;

PostTemplate.variables = (seedQuery) => {
  return {
    uri: seedQuery?.uri,
  };
};
  1. Create a post at your WordPress dashboard and add a list block to the post. Add nested list items to test the behavior.
  2. Run your nextjs project and check your post at http://localhost:3000/{your-post-slug}

Screenshots

Before After
Screenshot 2025-02-17 at 16 37 35 Screenshot 2025-02-17 at 16 36 37

Documentation Changes

N/A

Dependant PRs

N/A

@ahuseyn ahuseyn requested a review from a team as a code owner February 17, 2025 16:54
@changeset-bot
Copy link

changeset-bot bot commented Feb 17, 2025

🦋 Changeset detected

Latest commit: 9dc0abd

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@faustwp/blocks Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions
Copy link
Contributor

github-actions bot commented Feb 17, 2025

📦 Next.js Bundle Analysis for @faustwp/getting-started-example

This analysis was generated by the Next.js Bundle Analysis action. 🤖

This PR introduced no changes to the JavaScript bundle! 🙌

@colinmurphy
Copy link
Member

cc @justlevine

Copy link
Member

@colinmurphy colinmurphy left a comment

Choose a reason for hiding this comment

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

LGTM

@@ -0,0 +1,52 @@
---
'@faustwp/blocks': major
Copy link
Member

Choose a reason for hiding this comment

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

I don;t think this should be a major release. It should be a minor

Copy link
Member Author

Choose a reason for hiding this comment

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

The thing is, after this change we'll need to include blocks.CoreListItem.fragments to the queries to be able to render the lists. Without that CoreList won't work. That's why I came up with major release. How should we proceed in this case?

Copy link
Member

Choose a reason for hiding this comment

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

Would. existing users be affected when using ${blocks.CoreList.fragments.entry} only and not ${blocks. CoreListItem.fragments.entry}? if Yes then its a major release.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, existing users will stop seeing the list items if they just use ${blocks.CoreList.fragments.entry}.

Copy link
Contributor

Choose a reason for hiding this comment

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

You could include the ... on CoreListItem {} fragment inside CoreList.fragments.entry for backwards compatibility. It would just get merged with whatever is defined separately on CoreListItem.fragments.entry.

I'm not entirely sure how the overloading DX works for y'all from a SemVer POV though: Is there a reason a user would be overloading CoreList.fragments.entry (and therefore not get the ...on CoreListItem frag(s) ) but not overloading the CoreList React component (and therefore need the CoreListItem component and a frag to populate it)?

Copy link
Member Author

Choose a reason for hiding this comment

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

Thank you @justlevine for your suggestion. As we're using flatListToHierarchical on client side to build innerBlocks from editorBlocks flat list, it prevents us to benefit CoreListItem fragment inside CoreList.

Thus, we're intending to achieve backward compatibility by rendering the parsed CoreList attribute.values for those who don't add CoreListItem fragments temporarily and fully switching to CoreListItem with the first major release.

Screenshot 2025-02-20 at 12 59 13

Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure I understand the relevance of innerBlocks here, but if y'all have a solution that maintains backwards compat and stops this from beaking a breaking change, then no need for me to wallflower 🚀

Copy link
Member Author

@ahuseyn ahuseyn Feb 20, 2025

Choose a reason for hiding this comment

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

I was thinking something like this:

CoreList.fragments = {
  key: `CoreListBlockFragment`,
  entry: gql`
    fragment CoreListBlockFragment on CoreList {
      attributes {
        anchor
        backgroundColor
        className
        fontFamily
        fontSize
        gradient
        lock
        ordered
        reversed
        start
        style
        textColor
        type
        values
        cssClassName
      }
      innerBlocks {
        ... on CoreListItem {
          attributes {
            content
            anchor
            backgroundColor
            borderColor
            className
            fontFamily
            fontSize
            gradient
            lock
            metadata
            placeholder
            style
            textColor
          }
        }
      }
    }
  `,
};

@justlevine do you think this is the misinterpreted version of your suggestion? 😅

Update: I think this is the correct one, isn't it?

CoreList.fragments = {
  key: `CoreListBlockFragment ...CoreListItemFragment`,
  entry: gql`
    fragment CoreListBlockFragment on CoreList {
      attributes {
        anchor
        backgroundColor
        className
        fontFamily
        fontSize
        gradient
        lock
        ordered
        reversed
        start
        style
        textColor
        type
        values
        cssClassName
      }
    }
    fragment CoreListItemFragment on CoreListItem {
      attributes {
        content
        anchor
        backgroundColor
        borderColor
        className
        fontFamily
        fontSize
        gradient
        lock
        metadata
        placeholder
        style
        textColor
      }
    }
  `,
};


Example query:

```javascript
Copy link
Member

Choose a reason for hiding this comment

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

@ahuseyn

Great docs for the CHANGELOG 👏

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks @colinmurphy 🙂

@ahuseyn ahuseyn merged commit 4b1090a into canary Feb 21, 2025
19 checks passed
@ahuseyn ahuseyn deleted the refactor/CoreList-component branch February 21, 2025 16:38
@colinmurphy
Copy link
Member

Released in the latest version @faustwp/blocks version 6.1.0

#2044

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants