shopify / ui-extensions Goto Github PK
View Code? Open in Web Editor NEWLicense: MIT License
License: MIT License
For interfaces that make use of generics, let’s add the generics to the title.
checkout-ui-extensions-run V0.7.0
When an index.{ts,tsx,js}
file is not found, instead of throwing an exception as appears intended, an empty array is returned instead, this causes issues in the generated webpack config which will subsequently fail.
The issue is caused by this section of code in webpack-config.ts
, it's clear from the preceding check that it's not meant to return the result (an empty array) if no index source file was found.
checkout-ui-extensions-run serve
in a directory with no index.{ts,tsx,js}
or src/index.{ts,tsx,js}
.Exception stating index source file was not found is expected to have been thrown.
The fix for this as in the previous check is to change if (srcIndexFiles) {
to if (srcIndexFiles.length > 0) {
Considering the following, which has two <Layout />
instances in a <BlockStack />
You can apply this code to argo-checkout-template.
<BlockStack>
<CalloutBanner
title={`The body of this page was rendered by ${extensionPoint}`}
>
subtext
</CalloutBanner>
{/* <Layout />
* `500` represents `500px`
* `0.5` represents `50%`
* `1` represents `100%` */}
<Layout
media={[
{viewportSize: 'small', sizes: [1, 1], maxInlineSize: 0.95},
{viewportSize: 'medium', sizes: [300, 0.5], maxInlineSize: 0.95},
{viewportSize: 'large', sizes: [300, 0.3], maxInlineSize: 0.95},
]}
>
<BlockStack>
<Heading>Left Column</Heading>
<Image source="https://cdn.shopify.com/assets/images/logos/shopify-bag.png" />
</BlockStack>
<BlockStack alignment="leading">
<TextContainer>
<Heading>Right Column</Heading>
<HeadingGroup>
<Heading>My Post-Purchase Extension</Heading>
<TextBlock>
It could be a cross-sell extension, product review for past
purchases, request for more information from the buyer, or
anything else
</TextBlock>
<HeadingGroup>
<Heading>Description</Heading>
<TextBlock>
This is a non-exhaustive example, demonstrating provided UI
components
</TextBlock>
<Heading>initialState</Heading>
<TextBlock>{JSON.stringify(initialState)}</TextBlock>
</HeadingGroup>
</HeadingGroup>
</TextContainer>
<Button
onPress={() => {
console.log(`Extension point ${extensionPoint}`);
}}
>
Log extension point to console
</Button>
</BlockStack>
</Layout>
<Layout sizes={[0.1]}>
<Separator />
<TextContainer spacing="loose" alignment="center">
<TextBlock>
Bottom Text <Text emphasized>Stretches </Text>
across both columns. Bottom Text Stretches across both columns.
Bottom Text Stretches across both columns. Bottom Text Stretches
across both columns. Bottom Text Stretches across both columns.
Bottom Text Stretches across both columns.
</TextBlock>
<TextBlock>
In the <Text role="deletion">First</Text> Second Paragraph, Bottom
Text Stretches across both columns. Bottom Text Stretches across
both columns. Bottom Text Stretches across both columns. Bottom Text
Stretches across both columns. Bottom Text Stretches across both
columns. Bottom Text Stretches across both columns.
</TextBlock>
</TextContainer>
</Layout>
</BlockStack>
This code does produce expected results, with the bottom section spanning across the whole screen. However, the bottom section is pushed off to the right. I expected it to be centered.
What's really surprising, is if I change the 2nd layout to <Layout sizes={[0.9]}>
It renders like this:
Most properties in any given interface that make uses of any kind of type which makes use of a generic gets documented as T
.
When using a TextField
with type = "number"
like this:
<TextField
label={'Delivery frequency'}
type="number"
value={`${denormalizedSellingPlan.fulfillmentIntervalCount.value}`}
onChange={(value: string) =>
denormalizedSellingPlan.fulfillmentIntervalCount.onChange(
// temporary workaround, TextField.onChange should return value as Number
// and follow the standard https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/number
Number(value),
)
}
/>
should we follow input
and return a Number
instead?
checkout-ui-extensions
checkout-ui-extensions-react
post-purchase-ui-extensions
post-purchase-ui-extensions-react
Currently, we maintain a CHANGELOG for admin-ui-extensions
, but not for any of the other packages in this repo.
We should probably maintain a CHANGELOG for every component library in this repo.
checkout-ui-extensions
checkout-ui-extensions-react
useExtensionApi()
Please surface the location for dynamic extensions so that we know where in checkout it's rendering. I have multiple use cases that are much more complicated/blocked without this information. Trying to reuse a more generic extension for use in multiple locations but it doesn't know where it is so the content remains the same.
Maybe expose on the same hook where you show the extensions version? I think it's useExtensionApi()
?
Not aware of an alternative.
Currently the scaffolded app renders the string Welcome to the Checkout::Dynamic::Render extension!
below the cart. It's easy to miss as it's not visually distinct from the rest of the page. On smaller screens it's completely hidden behind a Rollup. I was initially confused as to why the string wasn't showing up as I usually have devtools open on the side and the page is forced into the smaller layout.
Desktop:
Mobile:
Edit file /path/to/file
to be able to change this textMany scaffolding apps for various frontend frameworks include these. A good example is CRA:
"@shopify/post-purchase-ui-extensions": "0.13.2",
"@shopify/post-purchase-ui-extensions-react": "0.13.2",
"react": "^17.0.0"
I am building a Post-Purchase Extension which makes POST requests to a GraphQL Rails server, which I am trying to authenticate using the JWT token. In the ShouldRender function I am accessing the JWT token from inputData. Then I construct the headers based on this:
extend('Checkout::PostPurchase::ShouldRender', async ({inputData, storage}) => {
const jwt_token = inputData.token;
let response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer ' + jwt_token,
},
body: ...
});
});
In my Rails server logs, I can see the request error-ing, due to the missing aud
claim, which should be set as the API KEY as per the JWT Shopify specification.
[ShopifyApp::JWT] Failed to validate JWT: [ShopifyApp::JWT::InvalidAudienceError] 'aud' claim does not match api_key
Digging through the Ruby JWT module I can see this error comes from this line here, which leads me to believe something is wrong with the token. Now, inspecting the JS console I log the token and then use the https://jwt.io/ tool to decode the token, which in turn looks like the following & proves it's missing some object keys from the JWT spec:
The token header is missing a "typ": "JWT"
:
{
"alg": "HS256"
}
The token payload is missing a few of the Claims from the specification
{
"iss": "shopify",
"sub": "a3c59a6b3c451c33b90e68871cd944de",
"input_data": {
"extensionPoint": "Checkout::PostPurchase::ShouldRender",
"initialPurchase": {
"referenceId": "a3c59a6b3c451c33b90e68871cd944de",
"customerId": 5788644180212,
"destinationCountryCode": "GB",
"totalPriceSet": {
"shopMoney": {
"amount": "25.98",
"currencyCode": "GBP"
},
"presentmentMoney": {
"amount": "25.98",
"currencyCode": "GBP"
}
},
"lineItems": [
{
"product": {
"id": 6636284346612,
"metafields": [],
"title": "Fertilizer",
"variant": {
"id": 39467655692532,
"metafields": [],
"title": ""
}
},
"quantity": 1,
"totalPriceSet": {
"shopMoney": {
"amount": "19.99",
"currencyCode": "GBP"
},
"presentmentMoney": {
"amount": "19.99",
"currencyCode": "GBP"
}
}
}
]
},
"locale": "en",
"shop": {
"id": 1234,
"domain": "mydomain.myshopify.com",
"metafields": []
},
"version": "unstable"
},
"iat": 1642930977
}
By comparison, the structure of a JWT token described here looks different:
Header
{
"alg": "HS256", -- The algorithm used to encode the JWT
"typ": "JWT", -- https://tools.ietf.org/html/rfc7519#section-5.1
}
Payload
{
"iss": "<shop-name.myshopify.com/admin>", -- The shop’s admin domain
"dest": "<shop-name.myshopify.com>", -- The shop’s domain
"aud": "<api key>", -- The Api key of the receiving app
"sub": "<user id>", -- The user the JWT is intended for
"exp": "<time in seconds>", -- when the JWT expires
"nbf": "<time in seconds>", -- when the JWT activates
"iat": "<time in seconds>", -- when the JWT was issued
"jti": "<random UUID>", -- A secure random UUID
}
Am I missing something or am I looking at the wrong thing?
See this PR for details: #292
There are circular dependencies being detected when running yarn docs:checkout
to generate documentation for checkout-ui-extensions
. If left unchecked, these cause fatal Maximum call stack size exceeded
errors.
The culprit of this issue are infinite recursive propType()
function calls from scripts/typedoc/shopify-dev-renderer/shared/index.ts
. There appears to be some component props that have a nested props object that references itself, thus being a circular dependency and the cause of a stack overflow through infinite recursion. A comment has been left in the file via #265 to outline where the problem occurs and the hacky workaround left in place to work around this unfortunate issue (note that I implemented this workaround while pairing with @lemonmade).
Our hunch is that there is a bug in the internal @shopify/docs-tools
package. We will follow up with the team maintaining this package as needed.
Drop API references in /api rather than /beta
Drop component references in /api rather than /beta
The doc gen script should output those files in the /api
directory within shopify-dev
.
Currently, the script generates {% sections %}{% highlight %}
. We can replace this with the new {% codeblock %}
tag.
checkout-ui-extensions
Properties listed in tables don't appear to be sorted in any logical ways making it hard to find props and their descriptions. Sorting them in alphabetical order would be a great improvements (it works really well in Polaris)
Visit the PhoneField page on shopify-dev.
useApplyDiscountCodeChange
to React hooks."@shopify/checkout-ui-extensions-react": "^0.15.0",
When you pick an extension point which is NOT registered in extension.config.yml
you're not notified in any way that you're doing something wrong. We should throw some sort of permission error when we detect that.
Checkout::Actions::RenderBefore
I expected to see some sort of permission error to be thrown.
"@shopify/post-purchase-ui-extensions": "0.10.1",
"@shopify/post-purchase-ui-extensions-react": "0.10.1",
"@shopify/checkout-ui-extensions-run": "0.7.0",
I found out that the supported props listed in https://shopify.dev/api/checkout-extensions/components/view are not matched with the implementation. It seems like the API reference is not up to date. I can see there are only two props supported below.
But in the implementation, there is no props that shown in the API references above, but more other supported props.
export interface ViewProps {
/**
* Adjust the maximum inline size.
*
* Numbers less than or equal to 1 are treated as percentages and numbers greater than 1 are treated as pixels.
*
* Examples:
* - `500` represents `500px`
* - `0.5` represents `50%`
* - `1` represents `100%`
*/
maxInlineSize?: number | Responsive<number>;
/**
* Adjust the padding.
*
* To shorten the code, it is possible to specify all the padding properties in one property.
*
* Examples:
* - `base` means blockStart, inlineEnd, blockEnd and inlineStart paddings are `base`
* - [`base`, `none`] means blockStart and blockEnd paddings are `base`, inlineStart and inlineEnd paddings are `none`
* - [`base`, `none`, `loose`, `tight`] means blockStart padding is `base`, inlineEnd padding is `none`, blockEnd padding is `loose` and blockStart padding is `tight`
*/
padding?: CSSShorthand<Spacing> | Responsive<CSSShorthand<Spacing>>;
/**
* Adjust the background.
*/
background?: Background | Responsive<Background>;
/**
* Sets one or multiple responsive background images.
*/
backgroundImage?: string | Responsive<string>;
/**
* Indicates if the background image should scale its container without cropping
* and stretching, or scale as large as possible to fill the container and stretching if necessary.
*/
backgroundFit?: BackgroundFit;
/**
* Sets the initial position of the background image.
* @defaultValue 'center'
*/
backgroundPosition?: BackgroundPosition;
/**
* Sets how background image are repeated.
* @defaultValue false
*/
backgroundRepeat?: boolean;
/**
* Adjust the border style.
*
* To shorten the code, it is possible to specify all the border style properties in one property.
*
* Examples:
* - `base` means blockStart, inlineEnd, blockEnd and inlineStart border styles are `base`
* - [`base`, `none`] means blockStart and blockEnd border styles are `base`, inlineStart and inlineEnd border styles are `none`
* - [`base`, `none`, `dotted`, `base`] means blockStart border style is `base`, inlineEnd border style is `none`, blockEnd border style is `dotted` and blockStart border style is `base`
*/
border?: CSSShorthand<BorderStyle> | Responsive<CSSShorthand<BorderStyle>>;
/**
* Adjust the border width.
*
* To shorten the code, it is possible to specify all the border width properties in one property.
*
* Examples:
* - `base` means blockStart, inlineEnd, blockEnd and inlineStart border widths are `base`
* - [`base`, `thick`] means blockStart and blockEnd border widths are `base`, inlineStart and inlineEnd border widths are `thick`
* - [`base`, `thick`, `thick`, `base`] means blockStart border width is `base`, inlineEnd border width is `thick`, blockEnd border width is `thick` and blockStart border width is `base`
*/
borderWidth?:
| CSSShorthand<BorderWidth>
| Responsive<CSSShorthand<BorderWidth>>;
/**
* Adjust the border color.
*/
borderColor?: BorderColor | Responsive<BorderColor>;
/**
* Adjust the border radius.
*
* To shorten the code, it is possible to specify all the border width properties in one property.
*
* Examples:
* - `base` means blockStart, inlineEnd, blockEnd and inlineStart border radii are `base`
* - [`base`, `none`] means blockStart and blockEnd border radii are `base`, inlineStart and inlineEnd border radii are `none`
* - [`base`, `none`, `tight`, `base`] means blockStart border radius is `base`, inlineEnd border radius is `none`, blockEnd border radius is `tight` and blockStart border radius is `base`
*/
borderRadius?:
| CSSShorthand<BorderRadius>
| Responsive<CSSShorthand<BorderRadius>>;
/**
* Changes the visibility of the element.
*
* 'hidden' visually hides the component while keeping it accessible to assistive technology (for example,
* a screen reader). Hidden elements do not take any visual space contrary to CSS visibility: hidden;
*/
visibility?: Visibility;
/**
* Changes the visibility of the element to assistive technologies.
*
* 'hidden' hides the component from assistive technology (for example,
* a screen reader) but remains visually visible.
*/
accessibilityVisibility?: AccessibilityVisibility;
/**
* Changes the display of the View.
*
* 'inline' follows the direction of words in a sentence based on the document’s writing mode.
* 'block' follows the direction of paragraphs based on the document’s writing mode.
*
* @defaultValue 'block'
*/
display?: Display;
/**
* A unique identifier for the View.
*/
id?: string;
}
The doc should up to date and align with implementation
"@shopify/post-purchase-ui-extensions": "0.13.0",
"@shopify/post-purchase-ui-extensions-react": "0.13.0",
Related API reference: https://shopify.dev/api/checkout-extensions/components/button
Can we add new props to allow customising the background colour and text/font colour for Button component? So that the button style can be aligned with the checkout page in case the store owner changes the theme or customising the checkout page.
N/A
Support new props: e.g. textColour, backgroundColour?
N/A
To make sure the post purchase page has the same styling as the checkout/payment page.
<View border="base" padding="base">
as per your example at https://github.com/Shopify/ui-extensions/blob/main/packages/post-purchase-ui-extensions-react/src/components/View/examples/basic-view.example.tsx#L7 padding and a border should be added around the <View/>
element.
The <View/>
component displayed a border
and padding
when the border
and padding
attributes were present.
<View border="base" padding="base"></View>
A border and padding around the element.
Now that we are getting closer to editions and are tophatting generated documentation, we should publish the public packages to match the doc output.
@shopify/checkout-ui-extensions-react 0.15.0
@shopify/shopify-cli-extensions 0.2.1
When a developer tries to render a string-based node like <div />
the error message isn't really descriptive as to why that's not allowed. The current error message just says:
main.js:10638 The above error occurred in the <div> component:
Problem is that there is no error above this one.
<div />
somewhereAn error message in the console which mentions that these kind of components cannot be used.
Devs can run yarn server
before running yarn generate
, which results in an unfriendly webpack error message.
We can improve this scenario by removing server.scripts
from package.json
and/or augmenting argo-run
.
Current output
(node:62170) UnhandledPromiseRejectionWarning: WebpackOptionsValidationError: Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration.entry[1] should be a string.
-> A non-empty string
at webpack (/Users/jared.dykstra/src/github.com/Shopify/argo-checkout-template/node_modules/webpack/lib/webpack.js:31:9)
at dev (/Users/jared.dykstra/src/github.com/Shopify/argo-checkout-template/node_modules/@shopify/argo-run/build/node/dev.js:36:41)
at run (/Users/jared.dykstra/src/github.com/Shopify/argo-checkout-template/node_modules/@shopify/argo-run/build/node/index.js:59:15)
(node:62170) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
(node:62170) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
✨ Done in 1.40s.
When this PR https://github.com/Shopify/docs-tools/pull/15 is merged and a new package is published, use the new package and output the new types it supports in the appropriate format.
Packages:
"@sentry/browser": "^6.13.2", "@sentry/tracing": "^6.13.2", "@shopify/post-purchase-ui-extensions": "0.10.1"
I'm trying to debug the post-purchase extension code using Sentry. But right after importing Sentry packages - the extension stops working. Everything works like a charm when I don't import Sentry.
The code:
import {
extend,
render,
useExtensionInput,
BlockStack,
Button,
CalloutBanner,
Heading,
Image,
Layout,
TextBlock,
TextContainer,
View,
} from '@shopify/post-purchase-ui-extensions-react';
import * as Sentry from '@sentry/browser';
import {Integrations} from '@sentry/tracing';
extend('Checkout::PostPurchase::ShouldRender', async ({inputData, storage}) => {
const initialState = await getRenderData();
const render = true;
if (render) {
// Saves initial state, provided to `Render` via `storage.initialData`
await storage.update(initialState);
}
return {
render,
};
});
// Simulate results of network call, etc.
async function getRenderData() {
return {
couldBe: 'anythinge',
};
}
/**
* Entry point for the `Render` Extension Point
*
* Returns markup composed of remote UI components. The Render extension can
* optionally make use of data stored during `ShouldRender` extension point to
* expedite time-to-first-meaningful-paint.
*/
render('Checkout::PostPurchase::Render', () => <App />);
// Top-level React component
export function App() {
const {extensionPoint, storage} = useExtensionInput();
const helloWorld = useExtensionInput();
console.log('hey1', helloWorld);
const initialState = storage.initialData;
return (
<BlockStack spacing="loose">
<CalloutBanner title="Post-purchase extension template">
Use this template as a starting point to build a great post-purchase
extension.
</CalloutBanner>
<Layout
maxInlineSize={0.95}
media={[
{viewportSize: 'small', sizes: [1, 30, 1]},
{viewportSize: 'medium', sizes: [300, 30, 0.5]},
{viewportSize: 'large', sizes: [400, 30, 0.33]},
]}
>
<View>
<Image source="https://cdn.shopify.com/static/images/examples/img-placeholder-1120x1120.png" />
</View>
<View />
<BlockStack spacing="xloose">
<TextContainer>
<Heading>Post-purchase extension</Heading>
<TextBlock>
Here you can cross-sell other products, request a product review
based on a previous purchase, and much more.
</TextBlock>
</TextContainer>
<Button
submit
onPress={() => {
// eslint-disable-next-line no-console
console.log(`Extension point ${extensionPoint}`, initialState);
}}
>
Primary button
</Button>
</BlockStack>
</Layout>
</BlockStack>
);
}
shopify/admin-ui-extensions v1.0.1
shopify/admin-ui-extensions-react v1.0.1
shopify/admin-ui-extensions v0.12.1
shopify/admin-ui-extensions-react v0.12.1
If the create form has a Radio button, Checkbox or Select component and the user cancels out of the form and immediately returns to it, the components appear to be unresponsive.
Source code for the create form:
import React from 'react';
import {
BlockStack,
Button,
Card,
CardSection,
Radio,
StackItem,
useContainer,
} from '@shopify/admin-ui-extensions-react';
function Create() {
const { close, done } = useContainer();
const [discountType, setDiscountType] = React.useState();
React.useEffect(() => {console.log('mounted');setDiscountType()}, []);
React.useEffect(() => console.log(discountType), [discountType]);
return (
<>
<BlockStack vertical={true}>
<Card title="Create Selling Plan" sectioned={true}>
<CardSection>
<BlockStack vertical={true} spacing="tight">
<StackItem>
<Radio
label="Discount (%)"
value="1"
name="discountGroup"
checked={discountType === '1'}
onChange={setDiscountType}
/>
</StackItem>
<StackItem>
<Radio
label="Flat amount ($)"
value="2"
name="discountGroup"
checked={discountType === '2'}
onChange={setDiscountType}
/>
</StackItem>
</BlockStack>
</CardSection>
</Card>
<Button title="Close" onPress={close} />
<Button title="Done" onPress={done} />
</BlockStack>
</>
);
}
export default Create;
Tags like this should be parsed by contentWithTags
. Currently they're ignored.
Because some folks will just look at the repo
"@shopify/post-purchase-ui-extensions": "0.13.0",
"@shopify/post-purchase-ui-extensions-react": "0.13.0",
N/A
It is not kind of a problem, but more like a request. Can we export all defined interfaces/models/types from the package: @shopify/post-purchase-ui-extensions? Currently only the top level interfaces are export which is good:
export type {
PostPurchaseRenderApi,
PostPurchaseShouldRenderApi,
PostPurchaseShouldRenderResult,
ChangeType,
ExplicitDiscountType,
} from './post-purchase';
But that will be more easier and helpful for people who are also using the Typescript to develop the post-purchase extension points if we can export all other types/interfaces, especially the following types/interfaces:
type CalculateChangesetResult =
| CalculateChangesetUnprocessedResult
| CalculateChangesetProcessedResult;
interface CalculatedPurchase
type Changes = (
| AddVariantChange
| AddShippingLineChange
| SetMetafieldChange
| AddSubscriptionChange
)[];
Is there any special reason or consideration that those interfaces/types are not export out?
N/A
N/A
N/A
@shopify/checkout-ui-extensions-react 0.15.0
@shopify/shopify-cli-extensions 0.2.1
A new projected created by our CLI with the typescript-react
template has type errors.
shopify extension create
and follow instructions (pick the ´typescript-react` templatesrc/index.tsx
in your editor -> Type ERRORThere should be no type errors when creating a brand new extension. This doesn't make for a good first time impression.
Did some digging and the issue is caused by multiple versions of @types/react
being present at the same time. One version v17.0.45
is installed by being a direct dependency of @remote-ui/react
and the other one is coming from @types/react-reconciler
which just has "@types/react": "*"
listed in its dependencies. This leads to that package installing @types/react v18.0.9
on top of the already existing 17.0.45
. Because both packages define the same types globally, there is a conflict and we'll end up with type errors in our editor as pictured above.
Reference code is correct, so somewhere in our docs generation we add an extra Example label.
SMS marketing partners have made a strong request to allow for customized SMS marketing consent capture in checkout, and to not be forced to only use the 1P feature we offer for this.
Since this feature can be optionally turned off in checkout using /settings, there is no real way (except on app review) to prevent partners from asking a merchant to turn off the 1P capture feature, and creating an extension which captures SMS compliance at checkout through an extension.
To avoid this being read/written to using the external call capability, we should add an extension API for it. This API should allow:
This has also been committed to by us (including Tobi/Glen) to Yotpo. Context from Egan Cheung below:
Hey Mani! Sorry we didn’t get to chat this through more deliberately, but a couple of things happened in rapid succession:
- Tomer spoke to Glen about his concerns around SMS consent collection as a whole and he scheduled a time to review with them.
- In the intervening time, Tomer spoke to Tobi about his concerns, specifically around customizing the UI and Tobi told him to use C1 checkout extensions to customize SMS consent collection.
- Also in the intervening time, I caught Glen up about the list of concerns Yotpo had and that the one we had not committed to yet was customizing the box. I let Glen know that one solution being considered was checkout extensions, though I did relay that due to the additive principle, we did not have alignment yet with the checkout team on this. That being said, in full transparency, I argued that I was in favour of it because:
the addition of a checkout extension is additive, and that would be the only thing we would allow
removal of the native sms collection would need to be manual (or simply not turned on), so the extension itself is not substituting or subtracting we would not be able to technically stop it from happening, anywayConsidering the arguments in 3a,b and c and with the subsequent knowledge that Tobi had already encouraged them to do so, Glen and I went in confirming that option to Tomer.
"@shopify/post-purchase-ui-extensions": "0.13.0",
"@shopify/post-purchase-ui-extensions-react": "0.13.0",
N/A
N/A
Is it feasible to allow to change font/add new font on post purchase extension page? Or does the post purchase page use the same font as the font used in checkout/payment page ALWAYS?
N/A
N/A
@shopify/checkout-ui-extensions-react
To help facilitate with realtime product data fetching as well as contextual product data based on the customer:
Please consider surfacing a way to communicate with the storefront api from our extension. Most apps are not eligible for the storefront api and so surfacing this in checkout would greatly improve both developer and customer experience (less chance for stale data).
It's becoming really difficult to store all the required product data for a checkout extension when there's so many variations a customer say see (pricing, language). Leveraging the storefront API to fetch data is performant and already support contextual api calls.
Please surface a React hook to fetch product data by gid or collection gid. It would be great if the following were support:
Storing all the data in a metafield or server-side and fetch via api call. If we're doing an external api call to fetch the data, it seems more performant to leverage the Storefront api at that point.
For example type Size
in BlockSpacing, Text, and Layout are all different but not treated that way. Currently docs for Layout are incorrect and listing the string literal values for BlockSpacing.
post-purchase-ui-extensions
The post-purchase Text and TextBlock components have the incorrect size props on shopify.dev docs.
Props for size component should be "extraSmall" | "small" | "base" | "large" | "extraLarge"
not "auto" | "fill" | number
This is a follow-up issue from Document Conditional Props using a Static file.
The conditional prop style helper docs are managed in a static markdown file. This will be hard to maintain long-term.
The exact solution will vary depending on how the conditional props have been implemented (at this time it's not clear).
ui-extensions
components()
script generator, you'll need to call the createDependencyGraph()
function from docs-tools
for a file that exports the style helpersdocs-tools
packagepropTypes()
in ui-extensions
to handle themEDIT: Fixed typo in createDependencyGraph
function name - @marvinhagemeister
Type checking for component examples is currently disabled. For example, here is post-purchase:
Otherwise, this results in an error error TS5055: Cannot write file 'path/to/file' because it would overwrite input file.
See original issue https://github.com/Shopify/checkout-web/issues/5189
checkout-ui-extensions-react
Textfield
Can we consider adding a date picker as a ui component? Even just using TextField + browser date field.https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/date
The use case is delivery date form field for products that require specifying a date such as flower delivery or food where the customer has to be home to receive.
Textfield with custom formatting to enter a date (prone to error from customers) and a custom Polaris-like calendar component using buttons.
argo-post-purchase
Post purchase initialPurchase API data
I'm having to call the Shopify checkout API to get all the information I need for eligibility which is causing a major problem:
I can't really cache this information since it's different for every checkout instance.
I am hoping the team might be able to reconsider surfacing additional data points to prevent the need of an API call:
Right now I call the customer API to grab the first & last name since I use that to personalize the offer. There's no other way get this information. I wonder if it could be solved by passing in the primary billing address like the checkout extension does: https://github.com/Shopify/argo/blob/main/packages/argo-checkout/src/extension-points/api/standard/index.ts#L262 & https://github.com/Shopify/argo/blob/main/packages/argo-checkout/src/extension-points/api/standard/index.ts#L394
Merchants sometimes want to limit post purchase eligibility by the products ordered based on tags and vendor/sku and this isn't surfaced on the Product interface: https://github.com/Shopify/argo/blob/main/packages/argo-post-purchase/src/extension-points/api/post-purchase/post-purchase.ts#L89
Honestly, vendor/sku is less important. Is there no efficient way to pass through the tags? It's such a key component to merchant merchandising efforts.
You're surfacing totalPriceSet
(https://github.com/Shopify/argo/blob/main/packages/argo-post-purchase/src/extension-points/api/post-purchase/post-purchase.ts#L67) which is great but can we get a subtotal value that excludes shipping and tax? Given tax and shipping are specific to the customer, some merchants like targeting dollar thresholds based on the subtotal since that's more consistent across customers.
When successfully applying a changeset, can we get the line item ids returned? It's for internal tracking and to remove if somehow payment is due.
Currently calling 1-2 Shopify APIs during the eligibility determination which wasn't a huge issue but is starting to become one with Shop Pay.
n/a?
When creating a product_discount extension / shopify function, we are adding metafield data into a namespace/key that is attached to the new discount being created.
Our expectation was that we could then read this metafield data from the checkout-ui-extension by specifying the namespace/key in the shopify.ui.extension.toml file.
However, the data is not being shown in the extension appMetafields.
After some discussion in the Shopify discord, it was mentioned that this use case may not have been considered yet.
https://discord.com/channels/842813079926603828/993570246361362462/994316477442302093
Expectation is that metafield data for the specified namespace/key combo will be available for the checkout ui extension to view and use when rendering the checkout extension.
argo-post-purchase package
The following types are not outputting / rendering in the API reference:
yarn docs:checkout
https://shopify-dev.myshopify.io/api/checkout/extension-points/api
Types output to the page
initialPurchase
of PostPurchaseRenderApi
takes the type of Purchase
but it seems to be missing the newly-added token
property.
Type:
interface Purchase {
/** Initial purchase's unique identifier */
referenceId: string;
customerId?: string;
destinationCountryCode?: string;
totalPriceSet: MoneyBag;
/** Items being purchased */
lineItems: LineItem[];
}
Actual payload:
referenceId: "51df3707...",
customerId: 3914168172700,
destinationCountryCode: "CA",
totalPriceSet: {...},
lineItems: [{…}],
token: "eyJhb..."
Thanks 👋
"@shopify/app": "^3.0.24",
"@shopify/checkout-ui-extensions-react": "^0.17.0",
"@shopify/cli": "^3.0.24",
"react": "^17.0.2"
onDismiss does not seem to fire for the <Banner>
component? I double checked everything so I don't think it's on my end?
<Banner
status="success"
onDismiss={() => console.log("onDismiss!")}
title={`${product.title} was successfully added to your cart.`}
/>
OnDismiss callback fires allowing me to set state and hide banner.
This issue applies to checkout-ui-extensions
The props table for UI components does not list the children
as an option. In some case, like the Checkbox
, it would be great to be able to define how the children is used (as <label>
for the checkbox in this case). In other cases, like the Divider
, its not obvious that it accepts a children and it opens a set of UI possibilities.
Visit the Divider page in shopify.dev.
children
is part of the props table, or specified in some way. This might not be as accurate for the vanilla JS context though. Something to consider.
"@shopify/post-purchase-ui-extensions": "0.10.1",
"@shopify/post-purchase-ui-extensions-react": "0.10.1",
I'm following the guide at https://shopify.dev/apps/checkout/post-purchase/getting-started-post-purchase-extension. Only the sample code runs. No changes in the callback inside "Checkout::PostPurchase::ShouldRender" are applied.
The changes in Checkout::PostPurchase::Render are visible on manual reload. (saving the file triggers a hot-reload but the following error is shown in the console: ExtensionSandboxPostPurchase.latest.en.5bf54cf4d521fa29dde1.worker.js:1 Uncaught (in promise) Error: No 'reload' method is exposed on this endpoint)
Follow the guide at https://shopify.dev/apps/checkout/post-purchase/getting-started-post-purchase-extension
At step 3, the page should look like the screenshot in the guide. It should show this image: https://cdn.shopify.com/s/files/1/0551/4084/3576/products/[email protected]
Instead, the image is not loaded. Only the "Click me" button is shown.
The results should be the same as the step by step guide.
I have also tried restarting the devlopment server, a different browser in private mode, etc.
checkout-ui-extensions-react
components
We'd like to use it to pop a confirmation.
make Modal component available for Post Purchase extension
Nothing else
Requesting this based on the description of https://github.com/Shopify/post-purchase-ui
If it's already planned or on the way to release, just close this ticket.
checkout-web
shopify-dev
- requires a manual process of copying packages to ui-extensions
and then running yarn docs:checkout
, which generates files in the local shopify-dev
repo, then a dev needs to run that using dev up
or spin
to preview the changes.There is a really useful package that I have been trying to get to work for the last 5 days.
Here is the link to the package:
https://github.com/Shopify/post-purchase-ui
There have also been 3 issues raised about this packaging all raising the same problem in the package.
There has only been 1 contributor on this package, I have tried to contact him with no luck.
I was wondering if someone in the Shopify team could take a look at this package and solve this tiny little issue that keeps coming up.
Here are a few discoveries/documentation about the issue:
addWebpackConfig
function to the webpack config, but once that is added, the following error occurs:I have tried a lot of different things to make it work but no luck. Hope someone can help
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.