From ef3d654d315fe5701457928046b467ec747024fc Mon Sep 17 00:00:00 2001 From: bdenham Date: Mon, 16 Dec 2024 15:24:30 -0600 Subject: [PATCH 1/4] feat: docs for extending drop-ins with Commerce APIs --- src/content/docs/dropins/all/extending.mdx | 351 ++++++++++++++++++++- 1 file changed, 341 insertions(+), 10 deletions(-) diff --git a/src/content/docs/dropins/all/extending.mdx b/src/content/docs/dropins/all/extending.mdx index ca32027a..4e3cdc1a 100644 --- a/src/content/docs/dropins/all/extending.mdx +++ b/src/content/docs/dropins/all/extending.mdx @@ -49,13 +49,345 @@ Overloaded term in web development. Everything is a component. It's components a -## Extend with third-party components +## Extend drop-ins with Commerce APIs -This tutorial describes the steps needed to extend a drop-in by integrating a fictitious third-party ratings & reviews component in the product details drop-in. +The following steps describe how to add existing Commerce API services to a drop-in. For example, the Commerce API provides the necessary endpoints to fetch and update gift messages through GraphQL, but the checkout drop-in doesn't provide this feature out of the box. We will extend the checkout drop-in by adding a UI for gift messages and then integrating the Commerce GraphQL API to fetch and update those messages. -:::note[Performance] -Be vigilant about how you display and fetch data for your third-party component to ensure you avoid any Cumulative Layout Shifts (CLS) that could significantly affect the site's core web vital scores. -::: +### Step-by-step + + + + +### Add your UI to the drop-in + +The first step is to add a new UI component to the checkout drop-in. This component will allow users to enter a gift message for their order. We'll call this component `GiftOptionsField` and create it as a web component for fun as shown in the example implementation below. + +```js title='gift-options-field.js' +import { Button, Input, TextArea, provider as UI } from '@dropins/tools/components.js'; + +const sdkStyle = document.querySelector('style[data-dropin="sdk"]'); +const checkoutStyle = document.querySelector('style[data-dropin="checkout"]'); + +class GiftOptionsField extends HTMLElement { + static observedAttributes = ['cartid', 'giftmessage', 'fromname', 'toname', 'loading']; + + constructor() { + super(); + this.attachShadow({ mode: 'open' }); + + this._submitGiftMessageHandler = (event) => { + event.preventDefault(); + } + } + + set submitGiftMessageHandler(callback) { + this._submitGiftMessageHandler = callback; + } + + connectedCallback() { + this._formTemplate = document.createElement('template'); + + this._formTemplate.innerHTML = ` +

Gift Message

+
+
+
+
+ +
+
+ `; + + this.render(); + } + + attributeChangedCallback(name, oldValue, newValue) { + const toName = this.shadowRoot.querySelector('input[name="toName"]'); + const fromName = this.shadowRoot.querySelector('input[name="fromName"]'); + const giftMessage = this.shadowRoot.querySelector('textarea[name="giftMessage"]'); + const cartId = this.shadowRoot.querySelector('input[name="cartId"]'); + + switch (name) { + case 'cartid': + cartId.value = newValue; + break; + case 'giftmessage': + giftMessage.value = newValue; + break; + case 'fromname': + fromName.value = newValue; + break; + case 'toname': + toName.value = newValue; + break; + case 'loading': + if (newValue) { + toName?.setAttribute('disabled', ''); + fromName?.setAttribute('disabled', ''); + giftMessage?.setAttribute('disabled', ''); + } else { + toName?.removeAttribute('disabled'); + fromName?.removeAttribute('disabled'); + giftMessage?.removeAttribute('disabled'); + } + break; + } + } + + render() { + this.shadowRoot.innerHTML = ''; + + this.shadowRoot.appendChild(this._formTemplate.content.cloneNode(true)); + this.shadowRoot.querySelector('input[name="cartId"]').value = this.getAttribute('cartId'); + this.shadowRoot.querySelector('#gift-options-form').addEventListener('submit', this._submitGiftMessageHandler?.bind(this)); + + const submitWrapper = this.shadowRoot.querySelector('.submit-wrapper'); + const fromNameWrapper = this.shadowRoot.querySelector('.fromName-wrapper'); + const toNameWrapper = this.shadowRoot.querySelector('.toName-wrapper'); + const giftMessageWrapper = this.shadowRoot.querySelector('.giftMessage-wrapper'); + + UI.render(Input, + { + type: "text", + name: "toName", + placeholder: "To name", + floatingLabel: "To name", + value: this.getAttribute('toName'), + disabled: !!this.hasAttribute('loading') + })(toNameWrapper); + UI.render(Input, + { + type: "text", + name: "fromName", + placeholder: "From name", + floatingLabel: "From name", + value: this.getAttribute('fromName'), + disabled: !!this.hasAttribute('loading') + })(fromNameWrapper); + UI.render(TextArea, + { + name: "giftMessage", + placeholder: "Message", + value: this.getAttribute('giftMessage'), + disabled: !!this.hasAttribute('loading') + })(giftMessageWrapper); + UI.render(Button, + { + variant: "primary", + children: "Add Message", + type: "submit", + enabled: true, + size: "medium", + disabled: !!this.hasAttribute('loading') + })(submitWrapper); + + this.shadowRoot.appendChild(sdkStyle.cloneNode(true)); + this.shadowRoot.appendChild(checkoutStyle.cloneNode(true)); + } +} + +customElements.define('gift-options-field', GiftOptionsField); +``` +
+ + +### Render the UI into a checkout container + +Next, we need to render the `GiftOptionsField` component into the checkout drop-in by creating a container to render the component into. + +```js +const GiftOptionsField = document.createElement('gift-options-field'); +GiftOptionsField.setAttribute('loading', 'true'); +``` + +Then, add the container to the layouts of the checkout drop-in. The following example shows how to add the container to the `checkout` layout. + +```js title='commerce-checkout.js' +function renderMobileLayout(block) { + root.replaceChildren( + heading, + giftOptionsField, + ... + ); + + block.replaceChildren(root); +} + +function renderDesktopLayout(block) { + main.replaceChildren( + heading, + giftOptionsField, + ... + ); + + block.replaceChildren(block); +} +``` + + + + +### Add handler for gift message submission + +Now that we have the UI in place, we need to add a handler to submit the gift message to the Commerce API. We'll use the `fetch` API to send a GraphQL mutation to update the gift message. + +```js title='commerce-checkout.js' +giftOptionsField.submitGiftMessageHandler = async (event) => { + event.preventDefault(); + + const form = event.target; + const formData = new FormData(form); + const cartId = formData.get('cartId'); + const fromName = formData.get('fromName'); + const toName = formData.get('toName'); + const giftMessage = formData.get('giftMessage'); + + giftOptionsField.setAttribute('loading', 'true'); + console.log('form data', cartId, fromName, toName, giftMessage); + + const giftMessageInput = { + from: fromName, + to: toName, + message: giftMessage, + } + + fetchGraphQl(` + mutation SET_GIFT_OPTIONS($cartId: String!, $giftMessage: GiftMessageInput!) { + setGiftOptionsOnCart(input: { + cart_id: $cartId, + gift_message: $giftMessage + gift_receipt_included: false + printed_card_included: false + }) { + cart { + id + gift_message { + from + to + message + } + } + } + } + `, + { + variables: { + cartId, + giftMessage: giftMessageInput, + }, + }).then(() => { + refreshCart(); + giftOptionsField.removeAttribute('loading'); + }); +}; +``` + + + +### Extend the data payload for the drop-in + +To extend the data payload of a drop-in, you need to add a GraphQL fragment to the `cart` payload by modifying the `build.mjs` script at the root of your storefront project. For our example, the fragment should add the gift message data in the cart. Here's an example of what the GraphQL should look like: + +```js title='build.mjs' +/* eslint-disable import/no-extraneous-dependencies */ +import { overrideGQLOperations } from '@dropins/build-tools/gql-extend.js'; + +// Extend the cart fragment to include the gift message +overrideGQLOperations([ + { + // The name of the drop-in to extend + npm: '@dropins/storefront-cart', + // Additional fields to include in the cart results (gift_message) + operations: [ + `fragment CART_FRAGMENT on Cart { + gift_message { + from + to + message + } + }` + ], + }, +]); +``` + +When you run the install command, the `build.mjs` script will generate a new GraphQL query for the cart drop-in that includes the `gift_message` data. extend the cart fragment to include the gift message data. + + + + + +### Add new data to the payload + +Map the updated GraphQL query to the data that the cart events provide to listeners. In this way, the checkout drop-in can access gift message data. + +Configure the cart drop-in's initializer to add the new cart data to the existing cart payload. This includes the new data with the payload that the cart events provide to listeners. As an example, here is how it might be configured: + +```js title='cart.js' +/* eslint-disable import/no-cycle */ +import { initializers } from '@dropins/tools/initializer.js'; +import { initialize } from '@dropins/storefront-cart/api.js'; +import { initializeDropin } from './index.js'; + +initializeDropin(async () => { + await initializers.mountImmediately(initialize, { + models: { + CartModel: { + transformer: (data) => { + const { gift_message: giftMessage } = data; + return { + giftMessage, + } + } + } + } + }); +})(); +``` + +Now when the cart emits an event with cart data, the `giftMessage` data is included. + + + + + +### Retrieve the data and render it + +Get the data from the cart event and use it to populate the gift message fields on the checkout page. Here's an example of how you might do this: + +```js title='commerce-checkout.js' +// Event listener to hydrate the new fields with the cart data +events.on('cart/data', data => { + if (!data) return; + + const { id, orderAttributes, giftMessage } = data; + + // Update gift options fields + giftOptionsField.setAttribute('cartId', id); + if(giftMessage) { + giftOptionsField.setAttribute('giftmessage', giftMessage.message); + giftOptionsField.setAttribute('fromname', giftMessage.from); + giftOptionsField.setAttribute('toname', giftMessage.to); + } + giftOptionsField.removeAttribute('loading'); +}, { eager: true }); +``` + + + + + +### Summary + +After just a few changes, we were able to add a new feature to the checkout drop-in that allows users to add a gift message to their order. We added a new UI component, integrated the Commerce API to fetch and update gift messages, and extended the data payload for the drop-in to include the gift message data. You can apply these same concepts to any drop-in. + + + +
+ +## Extend drop-ins with third-party components + +The following steps guide you through adding a third-party component to a drop-in. We'll add a fictitious ratings & reviews component to the product details drop-in as an example. ### Prerequisites @@ -100,7 +432,6 @@ export default async function decorate(block) { // Fetch the component data setRatingsJson(product, thirdPartyApiKey); } - ``` @@ -171,9 +502,9 @@ events.on('eds/pdp/ratings', ({ average, total }) => { ### Delay loading large data sets -Our fictitious ratings & reviews component loads large blocks of text to display a product's reviews. So we need to ensure all that data is not loaded initially with the page. We need to delay loading the reviews until the user scrolls near the reviews section or clicks a "View All Reviews" button. This strategy will improve the page's First Contentful Paint (FCP) and Cumulative Layout Shift (CLS) scores. +Components like ratings & reviews typically load large blocks of text to display a product's reviews. In such cases, we need to ensure that those reviews are not loaded until the user scrolls near the reviews section or clicks a "View All Reviews" button. This strategy keeps the First Contentful Paint (FCP) and Cumulative Layout Shift (CLS) scores low. -Here's an example implementation using an Intersection Observer to trigger the delayed load when the user scrolls near the reviews section or clicks "View All Reviews": +The following example uses an Intersection Observer to load reviews only when a user scrolls near the reviews section or clicks "View All Reviews". ```js // Trigger the delayed load when the user scrolls near the reviews section or clicks "View All Reviews" @@ -208,9 +539,9 @@ observer.observe(reviewsSection); -### Conclusion +### Summary -This tutorial showed you the key steps required to integrate a fictitious third-party component into a drop-in. You've learned how to configure API keys, fetch data, and delay loading large data sets to improve page performance. You can now apply these concepts to other third-party components you want to integrate into your drop-ins. +Throughout this tutorial, we examined the key steps of integrating a fictitious third-party component. We learned how to configure API keys, fetch data, and delay loading data sets to improve page performance. You can apply these same concepts to any drop-in. From 4e39bc8cf30d3e317c068faefba9c75817723425 Mon Sep 17 00:00:00 2001 From: bdenham Date: Mon, 16 Dec 2024 15:45:17 -0600 Subject: [PATCH 2/4] feat: docs for extending drop-ins with Commerce APIs --- astro.config.mjs | 7 +-- src/content/docs/dropins/all/enriching.mdx | 2 +- src/content/docs/dropins/all/extending.mdx | 39 +---------------- src/content/docs/dropins/all/slots.mdx | 50 ++++++++++++++++++++++ 4 files changed, 57 insertions(+), 41 deletions(-) create mode 100644 src/content/docs/dropins/all/slots.mdx diff --git a/astro.config.mjs b/astro.config.mjs index 3e9bece7..a6254f95 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -31,9 +31,6 @@ export default defineConfig({ trailingSlash: 'ignore', outDir: './dist', - - - redirects: { '/customize/design-tokens': '/developer/commerce/storefront/dropins/all/branding', '/customize/enrich': '/developer/commerce/storefront/dropins/all/enriching', @@ -184,6 +181,10 @@ export default defineConfig({ label: 'Styling', link: '/dropins/all/styling/' }, + { + label: 'Slots', + link: '/dropins/all/slots/' + }, { label: 'Layouts', link: '/dropins/all/layouts/' diff --git a/src/content/docs/dropins/all/enriching.mdx b/src/content/docs/dropins/all/enriching.mdx index 8dd63563..2192e3fb 100644 --- a/src/content/docs/dropins/all/enriching.mdx +++ b/src/content/docs/dropins/all/enriching.mdx @@ -60,7 +60,7 @@ Content positioning is the placement of content and enrichment blocks on a webpa ### Slot API functions -The slots API provides several functions to add content within a drop-in component by specifying a slot name and a position. The slot API provides functions to add content to specific positions above and below the slot, such as prepend and append. See the full list of slot API functions here: [Extending drop-in components](/dropins/all/extending#big-picture) +The slots API provides several functions to add content within a drop-in component by specifying a slot name and a position. The slot API provides functions to add content to specific positions above and below the slot, such as prepend and append. See the full list of slot API functions here: [Understanding slots](/dropins/all/slots#big-picture) diff --git a/src/content/docs/dropins/all/extending.mdx b/src/content/docs/dropins/all/extending.mdx index 4e3cdc1a..f3374097 100644 --- a/src/content/docs/dropins/all/extending.mdx +++ b/src/content/docs/dropins/all/extending.mdx @@ -1,6 +1,6 @@ --- title: Extending dropin-in components -description: Learn about slots and how to use them to customize dropin-in components. +description: Learn about different methods to extend dropin-in components. --- import { Tabs, TabItem } from '@astrojs/starlight/components'; @@ -12,42 +12,7 @@ import { Steps } from '@astrojs/starlight/components'; import Tasks from '@components/Tasks.astro'; import Task from '@components/Task.astro'; -Using slots provides the deepest level of customization. Slots are built-in extension points in the drop-in. A slot provides a place in the drop-in component to add your own UI components and functions. This architecture makes it easy to change the default look, layout, and behavior. Let's learn how it works. - -## Big Picture - -![What is a slot?](@images/slots/what-is-a-slot.svg) - - - -1. `prependSibling`: A function to prepend a new HTML element before the slot's content. -1. `prependChild`: A function to prepend a new HTML element to the slot's content. -1. `replaceWith`: A function to replace the slot's content with a new HTML element. -1. `appendChild`: A function to append a new HTML element to the slot's content. -1. `appendSibling`: A function to append a new HTML element after the slot's content. -1. `getSlotElement`: A function to get a slot element. -1. `onChange`: A function to listen to changes in the slot's context. -1. `dictionary`: JSON Object for the current locale. If the locale changes, the `dictionary` values change to reflect the values for the selected language. - - - -## Vocabulary - - - -### Container - -Component that manages or encapsulates other components. Containers handle logic, fetch data, manage state, and pass data to the UI components that are rendered on the screen. - -### Slot - -Component that provides placeholders to add other components. You can use a drop-in component's built-in slots to add or remove UI components and functions. Or you can add your own additional Slots. - -### Component - -Overloaded term in web development. Everything is a component. It's components all the way down. This is why we need to be specific about what kind of component we are talking about. For example, from top-to-bottom, big-to-small, a **drop-in component** can contain multiple **container components** that can contain multiple **slot components** that can contain multiple **UI components**. - - +Drop-in components are designed to be flexible and extensible. This guide provides an overview of how to extend drop-in components to add new features, integrate with third-party services, and customize the user experience. ## Extend drop-ins with Commerce APIs diff --git a/src/content/docs/dropins/all/slots.mdx b/src/content/docs/dropins/all/slots.mdx new file mode 100644 index 00000000..397d12bf --- /dev/null +++ b/src/content/docs/dropins/all/slots.mdx @@ -0,0 +1,50 @@ +--- +title: Understanding slots +description: Learn about slots and how to use them to customize dropin-in components. +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; +import Diagram from '@components/Diagram.astro'; +import Vocabulary from '@components/Vocabulary.astro'; +import Aside from '@components/Aside.astro'; +import Callouts from '@components/Callouts.astro'; +import { Steps } from '@astrojs/starlight/components'; +import Tasks from '@components/Tasks.astro'; +import Task from '@components/Task.astro'; + +Using slots provides the deepest level of customization. Slots are built-in extension points in the drop-in. A slot provides a place in the drop-in component to add your own UI components and functions. This architecture makes it easy to change the default look, layout, and behavior. Let's learn how it works. + +## Big Picture + +![What is a slot?](@images/slots/what-is-a-slot.svg) + + + +1. `prependSibling`: A function to prepend a new HTML element before the slot's content. +1. `prependChild`: A function to prepend a new HTML element to the slot's content. +1. `replaceWith`: A function to replace the slot's content with a new HTML element. +1. `appendChild`: A function to append a new HTML element to the slot's content. +1. `appendSibling`: A function to append a new HTML element after the slot's content. +1. `getSlotElement`: A function to get a slot element. +1. `onChange`: A function to listen to changes in the slot's context. +1. `dictionary`: JSON Object for the current locale. If the locale changes, the `dictionary` values change to reflect the values for the selected language. + + + +## Vocabulary + + + +### Container + +Component that manages or encapsulates other components. Containers handle logic, fetch data, manage state, and pass data to the UI components that are rendered on the screen. + +### Slot + +Component that provides placeholders to add other components. You can use a drop-in component's built-in slots to add or remove UI components and functions. Or you can add your own additional Slots. + +### Component + +Overloaded term in web development. Everything is a component. It's components all the way down. This is why we need to be specific about what kind of component we are talking about. For example, from top-to-bottom, big-to-small, a **drop-in component** can contain multiple **container components** that can contain multiple **slot components** that can contain multiple **UI components**. + + From 124282f82998588c6b5cf3a19a6720ca84302cc0 Mon Sep 17 00:00:00 2001 From: Bruce Denham Date: Tue, 17 Dec 2024 15:04:47 -0600 Subject: [PATCH 3/4] Apply suggestions from code review Co-authored-by: James Calcaben Co-authored-by: Kevin Harper --- src/content/docs/dropins/all/extending.mdx | 18 +++++++++--------- src/content/docs/dropins/all/slots.mdx | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/content/docs/dropins/all/extending.mdx b/src/content/docs/dropins/all/extending.mdx index f3374097..2c856c16 100644 --- a/src/content/docs/dropins/all/extending.mdx +++ b/src/content/docs/dropins/all/extending.mdx @@ -16,7 +16,7 @@ Drop-in components are designed to be flexible and extensible. This guide provid ## Extend drop-ins with Commerce APIs -The following steps describe how to add existing Commerce API services to a drop-in. For example, the Commerce API provides the necessary endpoints to fetch and update gift messages through GraphQL, but the checkout drop-in doesn't provide this feature out of the box. We will extend the checkout drop-in by adding a UI for gift messages and then integrating the Commerce GraphQL API to fetch and update those messages. +The following steps describe how to add existing Commerce API services to a drop-in. For example, the Commerce API provides the necessary endpoints to fetch and update gift messages through GraphQL, but the checkout drop-in doesn't provide this feature out of the box. We will extend the checkout drop-in by adding a UI for gift messages, use the Commerce GraphQL API to update the message data on the cart, and extend the cart drop-in to include the message data when it fetches the cart. ### Step-by-step @@ -25,7 +25,7 @@ The following steps describe how to add existing Commerce API services to a drop ### Add your UI to the drop-in -The first step is to add a new UI component to the checkout drop-in. This component will allow users to enter a gift message for their order. We'll call this component `GiftOptionsField` and create it as a web component for fun as shown in the example implementation below. +The first step is to add a new UI component to the checkout drop-in. This component will allow users to enter a gift message for their order. We'll call this component `GiftOptionsField` and create it as a web component, as shown in the example implementation below. ```js title='gift-options-field.js' import { Button, Input, TextArea, provider as UI } from '@dropins/tools/components.js'; @@ -158,14 +158,14 @@ customElements.define('gift-options-field', GiftOptionsField); ### Render the UI into a checkout container -Next, we need to render the `GiftOptionsField` component into the checkout drop-in by creating a container to render the component into. +Next, we need to render the `GiftOptionsField` component into the checkout page by creating the `gift-options-field` [custom element](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements). ```js const GiftOptionsField = document.createElement('gift-options-field'); GiftOptionsField.setAttribute('loading', 'true'); ``` -Then, add the container to the layouts of the checkout drop-in. The following example shows how to add the container to the `checkout` layout. +Then, insert the custom element into the layouts defined on the checkout page. The following example updates the render function for mobile and desktop to insert the `giftOptionsField` element into the layouts. ```js title='commerce-checkout.js' function renderMobileLayout(block) { @@ -194,7 +194,7 @@ function renderDesktopLayout(block) { ### Add handler for gift message submission -Now that we have the UI in place, we need to add a handler to submit the gift message to the Commerce API. We'll use the `fetch` API to send a GraphQL mutation to update the gift message. +Now that we have the UI in place, we need to add a handler to save the gift message data. We'll use the `fetchGraphl()` function from the API to send a GraphQL mutation to set the gift message on the cart. ```js title='commerce-checkout.js' giftOptionsField.submitGiftMessageHandler = async (event) => { @@ -251,7 +251,7 @@ giftOptionsField.submitGiftMessageHandler = async (event) => { ### Extend the data payload for the drop-in -To extend the data payload of a drop-in, you need to add a GraphQL fragment to the `cart` payload by modifying the `build.mjs` script at the root of your storefront project. For our example, the fragment should add the gift message data in the cart. Here's an example of what the GraphQL should look like: +To extend the data payload of a drop-in, first you need to update the GraphQL fragment used by the cart drop-in to request the additional field. This is done by modifying the `build.mjs` script at the root of your storefront project. In the following example, the `CART_FRAGMENT` fragment is extended to include the gift message data whenever the cart drop-in requests the cart data from GraphQL: ```js title='build.mjs' /* eslint-disable import/no-extraneous-dependencies */ @@ -276,7 +276,7 @@ overrideGQLOperations([ ]); ``` -When you run the install command, the `build.mjs` script will generate a new GraphQL query for the cart drop-in that includes the `gift_message` data. extend the cart fragment to include the gift message data. +When you run the install command, the `build.mjs` script generates a new GraphQL query for the cart drop-in that includes the `gift_message` data. @@ -284,9 +284,9 @@ When you run the install command, the `build.mjs` script will generate a new Gra ### Add new data to the payload -Map the updated GraphQL query to the data that the cart events provide to listeners. In this way, the checkout drop-in can access gift message data. +Map the new GraphQL data to the payload data that the cart events provide to listeners so they can access the gift message values. -Configure the cart drop-in's initializer to add the new cart data to the existing cart payload. This includes the new data with the payload that the cart events provide to listeners. As an example, here is how it might be configured: +Configure the cart drop-in's initializer to add the new cart data to the existing cart payload. This is done by defining a transformer function on the CartModel. This function receives the GraphQL data and returns an object that gets merged with the rest of the cart payload. As an example, here is how it might be configured: ```js title='cart.js' /* eslint-disable import/no-cycle */ diff --git a/src/content/docs/dropins/all/slots.mdx b/src/content/docs/dropins/all/slots.mdx index 397d12bf..53683166 100644 --- a/src/content/docs/dropins/all/slots.mdx +++ b/src/content/docs/dropins/all/slots.mdx @@ -41,7 +41,7 @@ Component that manages or encapsulates other components. Containers handle logic ### Slot -Component that provides placeholders to add other components. You can use a drop-in component's built-in slots to add or remove UI components and functions. Or you can add your own additional Slots. +Component that provides placeholders to add other components. You can use a drop-in component's built-in slots to add or remove UI components and functions. Or you can add your own additional slots. ### Component From 14db946253d2830ab21060dd0b9db7fca3f7d27b Mon Sep 17 00:00:00 2001 From: bdenham Date: Tue, 17 Dec 2024 15:25:00 -0600 Subject: [PATCH 4/4] fix: update based on reviews --- src/content/docs/dropins/all/extending.mdx | 5 ++--- src/content/docs/dropins/all/slots.mdx | 4 +++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/content/docs/dropins/all/extending.mdx b/src/content/docs/dropins/all/extending.mdx index 2c856c16..40195b4e 100644 --- a/src/content/docs/dropins/all/extending.mdx +++ b/src/content/docs/dropins/all/extending.mdx @@ -25,7 +25,7 @@ The following steps describe how to add existing Commerce API services to a drop ### Add your UI to the drop-in -The first step is to add a new UI component to the checkout drop-in. This component will allow users to enter a gift message for their order. We'll call this component `GiftOptionsField` and create it as a web component, as shown in the example implementation below. +The first step is to create a UI for the feature and add it to the checkout drop-in. You can implement the UI however you want, as long as it can be added to the HTML DOM. For this example, we'll implement a web component (`GiftOptionsField`) that provides the form fields needed to enter a gift message. Here's an example implementation of the UI component: ```js title='gift-options-field.js' import { Button, Input, TextArea, provider as UI } from '@dropins/tools/components.js'; @@ -221,7 +221,6 @@ giftOptionsField.submitGiftMessageHandler = async (event) => { setGiftOptionsOnCart(input: { cart_id: $cartId, gift_message: $giftMessage - gift_receipt_included: false printed_card_included: false }) { cart { @@ -276,7 +275,7 @@ overrideGQLOperations([ ]); ``` -When you run the install command, the `build.mjs` script generates a new GraphQL query for the cart drop-in that includes the `gift_message` data. +When you run the install command, the `build.mjs` script generates a new GraphQL query for the cart drop-in that includes the `gift_message` data. diff --git a/src/content/docs/dropins/all/slots.mdx b/src/content/docs/dropins/all/slots.mdx index 53683166..6575f9a9 100644 --- a/src/content/docs/dropins/all/slots.mdx +++ b/src/content/docs/dropins/all/slots.mdx @@ -18,6 +18,8 @@ Using slots provides the deepest level of customization. Slots are built-in exte ![What is a slot?](@images/slots/what-is-a-slot.svg) +The following functions are available to all slots: + 1. `prependSibling`: A function to prepend a new HTML element before the slot's content. @@ -45,6 +47,6 @@ Component that provides placeholders to add other components. You can use a drop ### Component -Overloaded term in web development. Everything is a component. It's components all the way down. This is why we need to be specific about what kind of component we are talking about. For example, from top-to-bottom, big-to-small, a **drop-in component** can contain multiple **container components** that can contain multiple **slot components** that can contain multiple **UI components**. +In web development, this term is overused. That's why we need to be specific about the kind of component we are talking about. Here's a few examples of components from top-to-bottom: a **drop-in component** can contain multiple **container components** that can contain multiple **slot components** that can contain multiple **UI components**.