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

Add Rich Text Component #2144

Merged
merged 13 commits into from
May 28, 2024
Merged

Add Rich Text Component #2144

merged 13 commits into from
May 28, 2024

Conversation

blittle
Copy link
Contributor

@blittle blittle commented May 22, 2024

WHY are these changes introduced?

Add a RichText component to easily render `rich_text_field` metafields. Thank you @bastienrobert for the original implementation. Fixes #621

Example usage:

import {RichText} from '@shopify/hydrogen-react';

export function MainRichText({richTextData}: {richTextData: string}) {
  return (
    <RichText
      data={richTextData}
      components={{
        paragraph({node}) {
          return <p className="customClass">{node.children}</p>;
        },
      }}
    />
  );
}

See docs at: https://shopify-dev.shopify-dev-8p8h.bret-little.us.spin.dev/docs/api/hydrogen/2024-04/components/richtext

Checklist

  • I've read the Contributing Guidelines
  • I've considered possible cross-platform impacts (Mac, Linux, Windows)
  • I've added a changeset if this PR contains user-facing or noteworthy changes
  • I've added tests to cover my changes
  • I've added or updated the documentation

Copy link
Contributor

shopify bot commented May 22, 2024

Oxygen deployed a preview of your bl-rich-text branch. Details:

Storefront Status Preview link Deployment details Last update (UTC)
Skeleton (skeleton.hydrogen.shop) ✅ Successful (Logs) Preview deployment Inspect deployment May 28, 2024 3:19 PM
optimistic-cart-ui ✅ Successful (Logs) Preview deployment Inspect deployment May 28, 2024 3:19 PM
vite ✅ Successful (Logs) Preview deployment Inspect deployment May 28, 2024 3:19 PM
subscriptions ✅ Successful (Logs) Preview deployment Inspect deployment May 28, 2024 3:19 PM
custom-cart-method ✅ Successful (Logs) Preview deployment Inspect deployment May 28, 2024 3:19 PM
third-party-queries-caching ✅ Successful (Logs) Preview deployment Inspect deployment May 28, 2024 3:19 PM

Learn more about Hydrogen's GitHub integration.

@blittle blittle changed the title Bl rich text Add Rich Text Component May 23, 2024
@blittle blittle marked this pull request as ready for review May 23, 2024 17:33
}

const Component =
components[node.type === 'list-item' ? 'listItem' : node.type] ??
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Follow the conventions of React to switch to camelCase. This makes it so that customizing the list item looks like:

import {RichText} from '@shopify/hydrogen';

export function MainRichText({text}: {text: string}) {
  return (
    <RichText
      data={JSON.parse(text)}
      components={{
        listItem({node}) {
          return <li className="customClass">{node.children}</li>;
        },
      }}
    />
  );
}

switch (node.type) {
case 'root':
return createElement(
Component as Exclude<CustomComponents['root'], undefined>,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not sure if there's a way to do this without casting 🤔

components={{
link: ({node}) => (
<Link
to={node.url}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Remix automatically handles if the destination is an external site.

Copy link
Contributor

@wizardlyhel wizardlyhel left a comment

Choose a reason for hiding this comment

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

Works as described but generates a lot of react key warning

Screenshot 2024-05-27 at 2 33 01 PM Screenshot 2024-05-27 at 2 34 56 PM

@wizardlyhel
Copy link
Contributor

wizardlyhel commented May 27, 2024

If you want to set up cart metafield to test, here are the steps

  1. In lib/fragments.ts, update the cart query fragment
  fragment CartApiQuery on Cart {
    updatedAt
    id
+    metafields(identifiers: [{
+      namespace: "custom",
+      key: "richtext",
+    }]){
+      namespace
+      key
+      type
+      value
+    }
    checkoutUrl
  1. In components/Cart.tsx, read the rich text metafield
export function CartMain({layout, cart: originalCart}: CartMainProps) {
  const cart = useOptimisticCart(originalCart);

  const linesCount = Boolean(cart?.lines?.nodes?.length || 0);
  const withDiscount =
    cart &&
    Boolean(cart?.discountCodes?.filter((code) => code.applicable)?.length);
  const className = `cart-main ${withDiscount ? 'with-discount' : ''}`;

+  // @ts-ignore
+  const metafieldValue = (cart.metafields && cart.metafields[0].value) || '';

  return (
    <div className={className}>
+      <RichText data={metafieldValue} />
  1. Open graphqli and run the following query, make sure to replace the cart id in the variable
mutation cartMetafieldsSet(
  $metafields: [CartMetafieldsSetInput!]!
  $language: LanguageCode, 
  $country: CountryCode
) @inContext(
  country: $country, 
  language: $language
) {
  cartMetafieldsSet(metafields: $metafields) {
    userErrors {
      code
      elementIndex
      field
      message
    }
  }
}

and the following variable

{
  "metafields": {
   "ownerId": "gid://shopify/Cart/Z2NwLXVzLWNlbnRyYWwxOjAxSFlYRkZCQ1FCUkVROFFIWDlYM0dOUkRa",
   "key": "custom.richtext",
   "type": "rich_text_field",
   "value": "{\"type\":\"root\",\"children\":[{\"type\":\"heading\",\"level\":2,\"children\":[{\"type\":\"text\",\"value\":\"Heading - cart metafield\"}]},{\"type\":\"paragraph\",\"children\":[{\"type\":\"text\",\"value\":\"This\",\"italic\":true},{\"type\":\"text\",\"value\":\" is a \"},{\"type\":\"text\",\"value\":\"text\",\"bold\":true},{\"type\":\"text\",\"value\":\" and a \"},{\"url\":\"/products/women-crewneck\",\"title\":\"title\",\"type\":\"link\",\"children\":[{\"type\":\"text\",\"value\":\"link\"}]},{\"type\":\"text\",\"value\":\" and an \"},{\"url\":\"https://shopify.com\",\"title\":\"Title\",\"target\":\"_blank\",\"type\":\"link\",\"children\":[{\"type\":\"text\",\"value\":\"external link\"}]}]}]}"
	},
  "country": "US",
  "language": "EN"
}

You should see the rich text metafield in cart

@blittle
Copy link
Contributor Author

blittle commented May 28, 2024

@wizardlyhel thank you for finding the key issue. It should be fixed.

@wizardlyhel
Copy link
Contributor

I'm still seeing the dup key warnings .. maybe the key need to propagate to the actual element that is being outputted instead of just passing to createElement?

@blittle
Copy link
Contributor Author

blittle commented May 28, 2024

A simpler way to test it is with a metafield on the product. Update the Product fragment to include:

const PRODUCT_FRAGMENT = `#graphql
  fragment Product on Product {
    id
    title
    vendor
    handle
    descriptionHtml
    description
+   extendedDetails:metafield(namespace: "custom", key: "extendeddetails") {
+     type
+     value
+   }

And then rendering on the PDP:

      {product.extendedDetails?.value ? (
        <RichText data={product.extendedDetails?.value} />
      ) : null}

@blittle blittle merged commit 30d18bd into main May 28, 2024
13 checks passed
@blittle blittle deleted the bl-rich-text branch May 28, 2024 21:00
@scottdixon
Copy link
Contributor

Just tested this now @blittle - so so good, feels like magic!

The only issue I noticed is new lines don't translate to BRs - should they? 🤔

image image

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.

[RTE Phase 1] Rich text editor updates in Metafield
4 participants